By · Founder, Stacktree · Last updated
blog

Define the tools once. Humans get forms, agents get schemas.

WebMCP is the browser's answer to a question MCP already answered for servers: how does an agent act on an app without guessing at its UI? Chrome has it in origin trial, Microsoft co-authored it, and the registration call costs three kilobytes of feature-detected code. So our dashboard now speaks it. Here is what shipped, the code, and an honest read on where the standard actually stands.

Get started free

What is WebMCP?

WebMCP (Web Model Context Protocol) is a proposed web standard that lets a web page register tools AI agents can discover and call through the browser. A page describes each action it supports, a name, a description, a JSON Schema for inputs, and registers it on document.modelContext. An agent operating in that browser calls the tool directly, with the user's existing session and permissions, instead of navigating the human UI by screenshot and click. It is incubated in the W3C Web Machine Learning Community Group by Microsoft and Google, and Chrome ships it today behind an origin trial.

The browser half of a familiar idea

MCP solved tool use for agents that live outside the browser: Claude Code calls publish_html on our MCP server and a site exists. But a second kind of agent is arriving, one that operates inside the browser, alongside a signed-in human. Today that agent's only interface to a web app is the human one: read the DOM or a screenshot, find the button, click, hope the modal is where it was last week. Every dashboard becomes a vision problem.

WebMCP's bet is that pages should just say what they can do. The page registers tools, the browser mediates, the agent calls them. Same JSON Schema discipline as MCP, same result shape (content blocks), but the execution happens in the page's own JavaScript with the user's own session. No tokens to mint, no API client to configure: if the human could do it from the page, the agent can be handed the same capability, explicitly, with the page's own validation in the path.

What we shipped: one catalog, three surfaces

The Stacktree dashboard now has a command palette (⌘K) built on agentk, an open-source cmdk extension we built for exactly this pattern. Every command in it is defined as a tool: a name, a description, and a JSON Schema for its parameters. Set a password, set an email gate, set an expiry, mint a share link, delete a site. The palette renders forms straight from the schemas, so a human types ⌘K, picks "Set password", and gets a generated form with validation.

Those same definitions are then registered on document.modelContext, feature-detected, when the browser exposes it. The verbs deliberately mirror our MCP server's tools: set_password, set_expiry, set_email_gate mean the same thing whether an agent reaches us over MCP from Claude Code, over REST with an API key, or in-browser over WebMCP. One catalog; the surface is just a door.

That is the actual point, beyond any one standard. Tools described as data instead of buttons hard-wired to handlers serve three consumers at once: the palette UI for humans, WebMCP for in-browser agents, and an LLM tool list whenever we want natural-language intent in the palette itself. Adding the third surface cost a useEffect.

The registration code, in full

This is the production code, not a sketch. The only abstraction is executeTool, the same function the palette's forms call:

// Chrome 150 moved the API from navigator.modelContext
// to document.modelContext; accept either.
function getModelContext() {
  const mc = document.modelContext ?? navigator.modelContext;
  return mc && typeof mc.registerTool === 'function' ? mc : null;
}

useEffect(() => {
  const mc = getModelContext();
  if (!mc || tools.length === 0) return;
  for (const tool of tools) {
    mc.registerTool({
      name: `stacktree_${tool.name}`,
      description: tool.description,
      inputSchema: tool.inputSchema,
      execute: async (params) => {
        const text = await executeTool(tool.name, params);
        return { content: [{ type: 'text', text }] };
      },
    });
  }
  return () => {
    for (const tool of tools) mc.unregisterTool(`stacktree_${tool.name}`);
  };
}, [tools]);

Notes that matter in practice. The cleanup function is not optional: in a single-page app the available tools change with state (our site list is an enum in the schema, refreshed when sites change), so stale registrations must come down. The result shape, content blocks with typed parts, is MCP's, which is what makes the two protocols feel like one vocabulary. And the whole thing is a no-op in every browser that does not expose modelContext, which today is most of them.

Where the standard honestly stands

Plainly: WebMCP is early, and anyone telling you otherwise is selling something. The spec is a draft in the W3C Web Machine Learning Community Group. Chrome implements it behind an origin trial, and Chrome's own documentation labels the API "under active discussion and subject to change". The rename is the proof: code written against navigator.modelContext in February was deprecated by Chrome 150 in favor of document.modelContext. Microsoft co-authored the spec and has said more Edge news is coming; Firefox and Safari are in the discussion but have committed to nothing.

So no, your users' browsers mostly cannot call our WebMCP tools today. We shipped the registration anyway, and the next section is the reasoning, because it is a cost-benefit calculation other teams will face soon.

Why ship against a moving spec

The cost side: because the palette already defines every action as a JSON Schema tool, WebMCP registration was about thirty lines, feature-detected to zero effect elsewhere. If the API renames again, we change one accessor. The downside is bounded at trivial.

The benefit side is the same reason we published llms.txt, machine-readable pricing, and an x402 catalog before most of their consumers existed: agent-readable surfaces compound. When a browser agent first looks at the Stacktree dashboard and asks "what can I do here", the answer is already structured, already versioned with our MCP vocabulary, already tested by every human who used the palette, because they are the same tools. Day one of the standard landing is day one of it working here.

And for an agent-first host specifically, this is not a side bet. Our users' agents publish the sites; their humans review them in this dashboard. The gap between those two has always been the place where someone falls back to clicking. WebMCP is the first credible proposal for closing it from the browser side, and a publish primitive should be fluent in every protocol agents use to act. MCP for the editor, REST for the script, x402 for the payment, WebMCP for the page.

FAQ

Frequent questions

What is WebMCP? +
WebMCP (Web Model Context Protocol) is a proposed web standard, incubated in the W3C Web Machine Learning Community Group by Microsoft and Google, that lets a web page register tools AI agents can discover and call through the browser. A page describes each tool with a name, a description, and a JSON Schema for its inputs, and registers it on document.modelContext. An agent operating in the browser then calls the tool instead of guessing its way through your UI by clicking.
What is the difference between WebMCP and MCP? +
MCP connects agents to servers: an agent like Claude Code calls tools exposed by a separate process over the Model Context Protocol. WebMCP moves the same idea into the page itself: the running web app registers tools in the browser, and agents that operate inside that browser call them with the user's existing session, permissions, and context. They are complementary. Stacktree exposes the same publishing verbs over both.
Is WebMCP available in browsers today? +
Not by default. Chrome implements it behind an origin trial, and the API surface is still moving: Chrome 150 deprecated navigator.modelContext in favor of document.modelContext. Microsoft co-authored the spec and Edge previews are landing. Firefox and Safari are engaged in the standards discussion but have not committed to ship dates. Feature-detected registration costs a page nothing in the meantime.
How do you register a WebMCP tool? +
Call document.modelContext.registerTool() with a name, description, inputSchema (JSON Schema), and an async execute function that returns content blocks, the same result shape MCP servers use. Feature-detect first, since most browsers do not expose modelContext yet. unregisterTool() removes a tool, which matters in single-page apps where available actions change with state.
Why would a dashboard expose WebMCP tools? +
Because the alternative is an agent driving your UI by screenshot and click, which is slow and brittle. A dashboard that registers set_password or create_share_link as schema-described tools lets an in-browser agent do in one call what would otherwise take a fragile click sequence, inside the user's authenticated session, with the page's own validation. The tools are the same ones the human runs from the command palette, so nothing is duplicated.
Does WebMCP replace Stacktree's MCP server? +
No. The MCP server is how agents outside a browser (Claude Code, Cursor, custom agents) publish and manage sites, and it stays the primary agent surface. WebMCP registration covers the complementary case: an agent helping a signed-in human inside the dashboard. Same verbs, same vocabulary, different door.
Keep reading

Related guides

References

Sources and further reading

Your agent publishes. Your dashboard cooperates.

Sites your agent ships over MCP, managed by humans or in-browser agents through one schema-defined tool catalog. Start free.

Sign up free →