WebMCP is a proposed web standard that allows a web page to present its capabilities to AI agents as structured, schema-typed tools, rather than requiring agents to reverse-engineer the user interface. The proposal is being developed within the W3C Web Machine Learning Community Group, with engineers from Google and Microsoft among its editors. It brings together several earlier initiatives in this space, such as Microsoft’s “Web Model Context” explainer, Chrome’s “script tools” prototype, and the open-source MCP-B project.

Before diving deeper, two caveats that shape the entire discussion. First, WebMCP is not a finalized web standard. It exists as an experimental W3C Community Group draft, currently undergoing a Chrome origin trial, and its API surface is still subject to ongoing changes. Second, Angular happens to be the first major framework to provide built-in support for it, but that support is explicitly experimental and not a stable feature: the APIs are named with "Experimental" and may break outside of a major release. Keep this lens in mind throughout. This technology is meant for understanding and prototyping, not for production commitments.

This is the first installment of two. Here we explore what WebMCP truly is, what it intentionally excludes, and how the API functions conceptually. The second part examines Angular’s experimental support, the associated security model, and a realistic perspective on adoption.

From DOM Scraping to Contracts: Understanding WebMCP (Part 1) — figure 1

The interface gap

Today’s browser agents interact with websites like a translator deciphering a language they only partially know. The agent examines the page through DOM dumps, accessibility trees, screenshots, or a mix of these, passes that representation to a large model, then infers which element is the “Checkout” button, generates a click, waits, re-inspects, and continues. Playwright MCP (which relies primarily on accessibility snapshots), browser-use, and the various “computer use” agents all operate on variations of this loop.

It functions, barely, and it breaks down in three consistent ways:

Latency. Each step involves a round trip through a large model, frequently a multimodal one.

Cost. Images and raw DOM dumps are token-expensive relative to the minimal signal they convey (e.g., "there is a search field here").

Non-determinism. The agent is guessing intent from presentation. A CSS change, a delayed ad, or a variant in an A/B test can disrupt the entire chain. Failure rates accumulate over multi-step operations.

This diagnosis isn’t controversial. The W3C explainer itself cites precisely these issues as motivation for WebMCP: representations derived from DOM content and screenshots are costly to handle and fragile to interpret, making page-declared, structured capabilities the preferred solution. The goal isn’t smarter agents but eliminating the translation cost incurred with every action.

What WebMCP is, and three things it isn’t

WebMCP enables a web page to present its functionality (whether JavaScript functions or plain HTML forms) as tools: named, described, schema-typed actions an in-browser AI agent can find and invoke directly. The conceptual shift is one of control. Instead of the agent deducing what your page can do, the page states it explicitly: “here are my capabilities, with the parameters each takes, and what it returns.”

Before continuing, three clarifications that will prevent a faulty mental model:

1. WebMCP is not MCP. Despite the name, it doesn’t implement the MCP wire protocol. There’s no JSON-RPC, no client-server transport, and no intention to adopt MCP’s resources or prompts. Only the concept of tools survives. Early drafts considered bringing the full MCP protocol into the browser; the group intentionally chose a different path because MCP lacks a native understanding of web concepts like origins, browser permissions, or tab lifecycle. What WebMCP shares with MCP is the vocabulary and mental framework: tools with names, descriptions, and JSON Schemas. A WebMCP-enabled page is similar to an MCP server. The page becomes a “server” that lives only as long as the tab does.

2. WebMCP isn’t intended for headless or fully autonomous agents. This is an explicit non-goal in the spec. The design assumes human involvement by nature: the human’s UI stays primary, agent tools enhance it, and sensitive actions are expected to route through user approval. If you need unattended background automation, you’re exploring the wrong layer.

3. WebMCP doesn’t replace backend MCP. They serve different purposes. A flight-booking site might provide WebMCP tools for an agent in the user’s browser to manage the search flow within the user’s session, while also operating a conventional MCP server so Claude or ChatGPT can access its API server-side. Different consumers, different trust models.

So why not simply recommend everyone deploy backend MCP servers? The spec’s explainer lists three drawbacks with the backend-only strategy, which are worth understanding because they justify WebMCP’s existence:

  • UI disintermediation. A backend agent bypasses your interface entirely. Users lose visibility and control; you lose the shared screen where a human can watch, adjust, and confirm agent actions.
  • State and auth replication. A backend MCP server operates outside the user’s browser session. It requires its own authentication and its own state copy, including the cart a user partially filled manually before calling the agent.
  • Developer burden. You must build and maintain a separate backend surface. With WebMCP, the same client-side functions powering your components can be exposed to agents directly.

The last point carries an honest caveat: the economic logic assumes your frontend logic is callable. If your business logic is embedded in event handlers, extracting it into clean functions is the actual migration cost, though that refactor improves your codebase regardless of whether agents ever appear.

How it works: contracts, not clicks

WebMCP defines two API surfaces. What follows is a conceptual overview, not a tutorial. The exact forms are still evolving, which is itself a relevant detail.

The imperative API

A page registers a tool with a name, a model-readable description, a JSON Schema for inputs, and an execute callback. Adapted from the official explainer:

const controller = new AbortController();

await document.modelContext.registerTool({
  name: 'add-todo',
  description: "Add a new item to the user's active todo list",
  inputSchema: {
    type: 'object',
    properties: {
      text: { type: 'string' },
    },
    required: ['text'],
  },
  async execute({ text }) {
    await addTodoItemToCollection(text);
    return { content: [{ type: 'text', text: `Added: "${text}"` }] };
  },
}, { signal: controller.signal });

If you’ve written an MCP server, every field seems familiar. That’s intentional. Two specifics deserve attention.

First, deregistration occurs through AbortSignal, matching the pattern used by fetch and event listeners. This may seem minor, but it indicates WebMCP is being shaped as a web platform API, not a protocol port. SPAs are anticipated to register and remove tools as views transition: checkout tools exist only while the checkout view does.

Second, a point many early guides already misstate: the namespace has shifted twice. The proposal’s initial drafts employed window.agent; Chrome shipped the API as navigator.modelContext, and Chrome’s official documentation now clearly states navigator.modelContext is deprecated as of Chrome 150 in favor of document.modelContext. Same API, migrating namespace, three names in under a year. Use this to gauge how early the spec is.

The declarative API

For static sites and standard forms, JavaScript isn’t required. Annotate a form and the browser deterministically converts it into a tool, generating the input schema from the form controls:

<form toolname="book_table"
      tooldescription="Reserve a table at the restaurant"
      toolautosubmit>
  <input name="date" type="date"
         toolparamdescription="Reservation date" />
  <input name="partySize" type="number"
         toolparamdescription="Number of guests" />
  <button type="submit">Book</button>
</form>

Some details that most coverage overlooks:

  • toolautosubmit is opt-in. Without it, the agent fills the fields and the browser focuses the submit button, requiring a human to click. Human-in-the-loop, embodied as an HTML attribute.
  • The current draft proposes CSS pseudo-classes, :tool-form-active and :tool-submit-active, enabling you to style the form while an agent is completing it and when it awaits human review. Agent activity becomes a visible UI state. These are still part of an evolving specification rather than broadly implemented functionality.
  • SubmitEvent gains an agentInvoked property and a respondWith() method, allowing your submit handler to differentiate agent-driven submissions and provide a structured outcome (or a validation error) to the agent without page navigation. This completes the loop: the agent learns whether the action succeeded and can plan accordingly.
  • For form submissions that do navigate cross-document, the response channel remains unresolved. One suggestion under consideration is to use the first <script type=”application/ld+json”> element on the destination page as the tool response. If you’ve spent years adding schema.org markup for SEO, that idea might feel fitting.

The cross-origin model

Tool registration is disabled by default in cross-origin iframes; an embedding page must explicitly grant it via the tools Permissions Policy (<iframe allow=”tools”>). A tool can also be restricted to specific secure origins with exposedTo, and getTools() returns only same-origin tools unless the caller explicitly requests others via fromOrigins. Additionally, Chrome enables WebMCP only in origin-isolated documents: a page opting out of origin isolation (like through document.domain) has the APIs fully disabled. In short: a random third-party widget on your page can’t quietly expose tools on your behalf. Someone gave early thought to the enterprise requirements.

From DOM Scraping to Contracts: Understanding WebMCP (Part 1) — figure 2

MCP, skills, and the third way

Here’s the framing I find most helpful for placing WebMCP in the agent-tooling ecosystem.

Traditional MCP provides strict schema guarantees. When the agent calls a tool, arguments are validated against a contract. Yet every connected server’s tools occupy the context window regardless of relevance to the current task. It doesn’t scale well for the long tail.

Skills tackle the token issue with progressive disclosure: only a title and description are in context, with full instructions loading on demand. But a skill is fundamentally a text prompt; there’s no schema guarantee at the point of action.

WebMCP introduces a third pattern: contextual tools with full schemas. The tools available depend on where the agent is: the page, the route, the component currently shown. Move from search results to a product page, and set_filter disappears while add_to_cart shows up. You receive MCP’s determinism along with skills-like contextual loading, driven by the application’s own lifecycle.

This pattern extends beyond WebMCP itself. It offers a glimpse of where agent tooling generally appears to be heading: tools loaded by task context rather than globally pre-registered. (The two concepts are already merging. An open spec issue explores letting site authors ship a higher-level skill that coordinates multiple WebMCP tools.)

That’s precisely why Angular’s implementation deserves scrutiny: a framework with a dependency injection tree, a router, and component lifecycles already has the mechanics to express “these tools exist in this context” natively.

In part two, we examine Angular v22’s experimental WebMCP support, from application-level tools to Signal Forms that describe themselves to agents, then critically assess the security model of running tools within an authenticated session, and close with a pragmatic view of who actually calls these tools today.