Every enterprise site I work on has picked up a new class of visitor over the past two years. AI agents now navigate interfaces that were designed entirely for humans, and they do it by looking at the page and guessing. WebMCP is a proposed web standard that replaces the guessing with a declared contract.
It is early. WebMCP entered a public origin trial in Chrome 149, and the API surface is still moving. But the architectural idea is sound enough that platform teams should understand it now, before agent traffic shows up as a line item in the conversion report.
Actuation is screen scraping with better marketing
Chrome's documentation uses the term actuation for what agents do today: simulating mouse clicks and keyboard input as though a human were driving the browser. It works, sometimes. A single link click is reliable. A five-step checkout with a custom date picker, a conditional field, and a validation state that only appears after blur is not.
The failure mode will be familiar to anyone who has run an enterprise integration program. We stopped screen scraping partner systems a decade ago because parsing someone else's interface is a contract nobody agreed to. Rename a CSS class in a sprint and the integration breaks in production, silently, with no test that catches it. Agent actuation has exactly this shape, except the party doing the scraping is a language model with a probabilistic notion of what your button means.
WebMCP inverts the relationship. Instead of the agent inspecting an element to infer its purpose, the site declares the purpose. The agent stops interpreting and starts calling.
What WebMCP actually is
WebMCP is a proposed open web standard developed in the W3C Web Machine Learning Community Group. It gives a page a way to register tools: named functions with a description and a JSON Schema for their inputs. An agent running in the browser discovers those tools, calls them with schema-conformant arguments, and receives structured output back.
The Chrome for Developers documentation frames the capability around three things:
- Discovery. A standard way for a page to register tools with an agent, so the agent knows a checkout or filter_results tool exists rather than inferring it from markup.
- JSON Schemas. Explicit input and output definitions, which narrows the space where a model can hallucinate a parameter.
- State. A shared view of current page context, so the agent knows what is actually available to act on right now.
Two deployment properties matter. Tools execute visibly on your page, so the user watches the work happen and your design, brand, and human-centered flows stay intact. And the whole thing is a progressive enhancement, so a browser without WebMCP support simply renders the site you already have.
Two APIs, two levels of effort
The Declarative API: annotated forms
If your forms are well built, the declarative path is close to free. You add two attributes to a form element: toolname and tooldescription.
<form toolname="createSupportRequest"
tooldescription="Submits a request for customer support."
action="/submit">
<label for="firstName">First name</label>
<input type="text" name="firstName" id="firstName">
<select name="team" required
toolparamdescription="Determines what team this request is routed to.">
<option value="returns">Return my purchase.</option>
<option value="shipping">Check where my package is.</option>
<option value="website">Get help on the website.</option>
</select>
<button type="submit">Submit</button>
</form>The browser derives the JSON Schema from the form itself. Field names become properties, required fields become required, and select options become an enum. Labels supply parameter descriptions unless you override them with toolparamdescription. Remove either annotation and the tool unregisters.
By default the agent fills the form and the user clicks submit. Add toolautosubmit and the model can submit directly. Either way you get instrumentation. The SubmitEvent carries an agentInvoked boolean, and respondWith() lets you hand the model a structured result instead of letting it infer success from a redirect. The window fires toolactivated and toolcancel events, and Chrome applies the :tool-form-active and :tool-submit-active pseudo-classes so users can see which part of the page an agent is touching.
That last detail is not cosmetic. If an agent is filling a form on a user's behalf, the user needs to see it happening. Visible actuation is what makes the interaction auditable.
The Imperative API: registered JavaScript tools
For anything that is not a form, you register tools in JavaScript through the imperative API.
if ('modelContext' in document) {
await document.modelContext.registerTool({
name: 'get_order_status',
description:
'Look up orders in a given timeframe. Returns order number, shipping status, and location.',
inputSchema: {
type: 'object',
properties: {
timeframe: {
type: 'string',
enum: ['today', 'last_7_days', 'last_30_days'],
description: 'Timeframe for the order lookup.',
},
},
required: ['timeframe'],
},
annotations: {
readOnlyHint: true,
untrustedContentHint: true,
},
execute: async ({ timeframe }, { signal }) => {
const res = await fetch(`/api/orders?range=${timeframe}`, { signal });
return JSON.stringify(await res.json());
},
});
}Three things in that snippet are worth calling out. The execute function receives an AbortSignal as its second argument, which you should pass through to any fetch so a cancelled tool call does not leave work running. Registration accepts its own AbortController signal for unregistering, which matters in component frameworks where tools should follow mount and unmount lifecycles. And as of Chrome 153, unregistering no longer breaks in-flight executions.
The same interface exposes getTools() and executeTool() if you want to build your own in-page agent surface, plus a toolchange event when the available tool list changes.
One planning note. The interface has already moved. Earlier drafts registered tools on window.navigator.modelContext. Current Chrome documentation uses document.modelContext, with the navigator path deprecated. If you are budgeting for this work, budget for a moving target.
WebMCP is not the same thing as server-side MCP
The naming causes confusion, so it is worth being precise. A traditional MCP server exposes tools to an agent over a transport outside the browser. The agent connects with its own credentials, and you build and secure a second surface: authentication for agents, authorization for agents, rate limiting for agents.
WebMCP tools run inside the user's tab, in the user's existing session. Authentication is already resolved because the user is logged in. Entitlements are already resolved because the session carries them. For a large share of enterprise use cases, that is the entire value proposition. You are not standing up a parallel identity model just to let an agent check an order status.
The tradeoff is scope. Chrome is explicit that headless scenarios are not the design target. WebMCP is an assistance layer for local browser workflows with a human in the loop, not an automation backend. If you need unattended machine-to-machine access, you still want a server-side MCP implementation or a conventional API.
The security surface
WebMCP is gated in two ways. It is only available in origin-isolated documents, so a page that opts into document.domain through the Origin-Agent-Cluster: ?0 header cannot use it at all. Both APIs also sit behind the tools permissions policy, which defaults to self. Cross-origin iframes cannot register tools unless the parent delegates with allow="tools".
Cross-origin sharing is double opt-in. The hosting page lists permitted origins in exposedTo at registration time, and the consuming page has to explicitly request that origin through the fromOrigins option on getTools(). Neither side gets access by default.
Treat every registered tool as a public API endpoint. This is the part I would put on the design review agenda. A registered tool is callable by software you did not write, with arguments produced by a model that may have been influenced by content on the page. JSON Schema validates input shape, not authorization. Validate server side, enforce entitlements server side, apply rate limits, and log agent-invoked calls separately so you can separate them during an incident. The untrustedContentHint annotation exists precisely because tool output can carry injected instructions back into the model.
What this means if you run a DXP
The instrumentation work is component-level, not page-level. Your site search, your faceted filters, your quote request, your support intake, your product configurator. If you are running a composable front end with a shared component library, you annotate the form component once and every page that renders it inherits agent readability. If you are on a monolithic templated stack, you are adding scripts to templates one at a time and the cost scales with your page count. That difference is worth quantifying before anyone commits to a date.
There is also a content modeling question that most teams will get wrong the first time. Tool names and descriptions are the model's entire understanding of what your site can do. That text is content. It deserves the same treatment as any other content: authored by someone who understands the task, versioned, reviewed, and translated per locale. Hardcode a tool description in a component file and your German site will describe its support form in English. Model it as a field in your CMS and it flows through the governance you already have.
What is honestly still missing
- Distribution. WebMCP is in an origin trial, agent-side support remains thin, and no other browser vendor has publicly committed to shipping it. Microsoft co-authoring the proposal is a positive signal, but a proposal is not a standard.
- Discoverability. An agent has to land on your page to learn that your tools exist. There is no sitemap equivalent for tools today.
- Refactor cost. Chrome acknowledges that complex interfaces will need JavaScript work to expose application and interface state cleanly. If your state lives in a tangle of jQuery and server-rendered partials, finding the tool boundary will be the expensive part.
- Spec churn. The interface moved from navigator to document within a few months. Anything you build during the trial, you will revisit.
How I would approach it this quarter
- Find the three or four tasks agents already attempt on your site. Support intake, site search, account lookup, and quote requests are the usual suspects. Your logs will tell you.
- Start declarative. Annotate the forms that already have proper labels and validation. It is the lowest-cost path to a real test.
- Ship behind feature detection as a progressive enhancement. Nothing about a WebMCP tool should change the experience for a browser that does not support it.
- Run every tool through your existing API security review. Server-side validation, entitlement checks, rate limits, and audit logging that flags agent-invoked calls.
- Measure completion rates for agents and humans separately using agentInvoked. If you cannot measure the difference, you cannot make the case for expanding the work.
- Move tool names and descriptions into your content model before you have fifty of them scattered across component files.
- Test with the Model Context Tool Inspector extension, which shows registered tools, calls them manually, and confirms your schemas parse the way you intended.
The takeaway
WebMCP does not make your site agent-ready in the marketing sense of that phrase. It makes a specific, bounded set of tasks reliable for a specific, bounded set of clients, without you surrendering control of the interface or standing up a second identity surface. That is a reasonable trade, and a rare one this early in a standard's life.
My recommendation to platform teams is the one I give for most origin trials. Do not rewrite anything. Pick two forms, annotate them, measure what happens, and build the internal knowledge now, so that when this stabilizes you are extending a pattern rather than starting a project. The teams that struggle with agent traffic will be the ones who waited for the standard to be finished before they started thinking about it.




