DocsCapabilitiesWebMCP
WebMCP
In-page tools a browsing agent can call directly.
Why an agent cares
It lets a page hand an agent named tools instead of making it drive the UI, which is the difference between a reliable action and a screen-scrape. Tools register in JavaScript, so this is captured from the live page rather than parsed out of the HTML.
Adoption
Early pilots. Named early adopters exist, behind flags or trials. Nothing has been independently measured yet. For this one in particular, browsers are trialling it, but almost no publisher has shipped it.
Direction of travel: ▲ rising, as at .
Chrome origin trial in 149 to 156 and an Edge flag, but Spronta's Jul 2026 survey put publisher deployment at close to zero outside demonstrations.
| Adopter | Depth | Evidence |
|---|---|---|
| Google Chrome (origin trial 149-156) | preview | developer.chrome.com |
| Microsoft Edge (flag, 147+) | preview | spronta.com |
| Angular (declareWebMcpTool) | preview | angular.dev |
| Expedia, Booking.com, Shopify | announced | spronta.com |
What we check
| Check | Severity | Raises | On whose authority |
|---|---|---|---|
| WebMCP Tool Missing Name | high | usability | Lumar readiness bar, beyond W3C WebMCP draft (Web Machine Learning CG), Chrome docs — WebMCP |
Supporting documents: W3C WebMCP draft (Web Machine Learning CG), Chrome docs — WebMCP Lumar readiness bar: no specification requires this. Bad: a tool (declarative form or imperative registerTool) has no name, so agents have nothing to call. A registerTool call without one is rejected outright under the W3C draft; the declarative form's rules aren't written yet, so this is reported as a readiness fault rather than a specification violation. Fix: give every tool a name (the declarative toolname attribute, or registerTool's name field). | |||
| WebMCP Invalid Tool Name | high | usability | Lumar readiness bar, beyond W3C WebMCP draft (Web Machine Learning CG) |
Supporting documents: W3C WebMCP draft (Web Machine Learning CG) Lumar readiness bar: no specification requires this. Bad: a tool name is outside what the W3C draft allows for registerTool (1-128 characters, only A-Z a-z 0-9 _ - .), so it is rejected there; the declarative form has no published naming rules, so this is a readiness fault rather than a specification violation. Fix: rename it within those characters, e.g. search_flights. | |||
| WebMCP Tool Missing Description | high | usability | vendor profile: Chrome docs — WebMCP |
Supporting documents: Chrome docs — WebMCP Related guidance in Chrome docs — WebMCP. Bad: a declarative form tool has no tooldescription, which Chrome's declarative API expects (the W3C draft doesn't specify the declarative form yet), so an agent can't know what the tool does. Fix: add a tooldescription attribute saying what the tool does and when to use it. | |||
| WebMCP Imperative Missing Description | high | conformance, usability | specification: W3C WebMCP draft (Web Machine Learning CG) |
Supporting documents: W3C WebMCP draft (Web Machine Learning CG) Required by W3C WebMCP draft (Web Machine Learning CG). Bad: a registerTool call has no (or an empty) description, which is required, so agents can't tell what the tool does. Fix: pass a description saying what it does and when to call it. | |||
| WebMCP Imperative Missing Execute | high | conformance, usability | specification: W3C WebMCP draft (Web Machine Learning CG) |
Supporting documents: W3C WebMCP draft (Web Machine Learning CG) Required by W3C WebMCP draft (Web Machine Learning CG). Bad: a registerTool call omits its execute handler, so the tool is described but can never actually run. Fix: pass an execute function implementing the tool. | |||
| WebMCP Input Schema Not An Object | high | conformance, usability | specification: W3C WebMCP draft (Web Machine Learning CG) |
Supporting documents: W3C WebMCP draft (Web Machine Learning CG) Required by W3C WebMCP draft (Web Machine Learning CG). Bad: a registerTool call passes inputSchema as a JSON string. The WebMCP dictionary member is an object (it was a string until 14 Aug 2026), so a current browser rejects the registration and the tool never exists for agents. Fix: pass the schema object itself, not JSON.stringify of it: inputSchema: { type: "object", properties: { … } }. | |||
| WebMCP Duplicate Tool Name | high | usability | Lumar readiness bar, beyond W3C WebMCP draft (Web Machine Learning CG) |
Supporting documents: W3C WebMCP draft (Web Machine Learning CG) Lumar readiness bar: no specification requires this. Bad: two tools share the same (case-sensitive) name, so calls are ambiguous and one tool shadows the other. Names are compared across declarative forms and registerTool calls together: a duplicate registerTool call is rejected under the W3C draft, while a collision between the two surfaces is a readiness fault rather than a specification violation. Fix: give every tool a unique name. | |||
| WebMCP Param Missing Description | medium | usability | vendor profile: Chrome docs — WebMCP |
Supporting documents: Chrome docs — WebMCP Related guidance in Chrome docs — WebMCP. Bad: a tool parameter has no usable description (no toolparamdescription, associated label, or aria-description), so agents can't supply it correctly. Fix: describe every parameter, e.g. toolparamdescription="Departure date, YYYY-MM-DD". | |||
| WebMCP Imperative Missing Input Schema | informational | nothing | specification: W3C WebMCP draft (Web Machine Learning CG) |
Supporting documents: W3C WebMCP draft (Web Machine Learning CG) W3C WebMCP draft (Web Machine Learning CG) permits this, so it never fails the site. Informational (does not affect webMcpValid): a registerTool call omits inputSchema; fine for a parameterless tool, but agents can't validate arguments when it does take input. Consider declaring a JSON Schema for the tool's inputs. | |||
Examples
Both run through the same checks as a live scan: the first passes, the second is flagged.
<form
toolname="subscribe_newsletter"
tooldescription="Subscribe an email address to the newsletter."
action="/api/subscribe"
method="post"
>
<label>
Email
<input name="email" type="email" toolparamdescription="Subscriber email address" required />
</label>
<button type="submit">Subscribe</button>
</form>
<script>
if (document.modelContext) {
(async () => {
await document.modelContext.getTools();
document.modelContext.registerTool({
name: "get_order_status",
description: "Look up the status of an order by its ID.",
inputSchema: {
type: "object",
properties: { orderId: { type: "string", description: "Order identifier" } },
required: ["orderId"],
},
async execute({ orderId }) {
return { status: "shipped", orderId };
},
});
})();
}
</script><form toolname="subscribe_newsletter" action="/api/subscribe" method="post">
<input name="email" type="email" required />
<button type="submit">Subscribe</button>
</form>
<script>
if (navigator.modelContext) {
navigator.modelContext.registerTool({
name: "get_order_status",
async execute(args) {
return { status: "unknown" };
},
});
}
</script>Specifications
| Document | Revision | Kind |
|---|---|---|
| W3C WebMCP draft (Web Machine Learning CG) | Draft, 30 September 2026 | specification |
| Chrome docs — WebMCP | Living document | vendor profile |
| Chrome docs — declarative API (form annotations) | Living document | vendor profile |
| Chrome docs — imperative API (registerTool) | Living document | vendor profile |
Last re-read against the published documents: .