WebMCP Explained: Letting AI Agents Use Your Website’s Tools in the Browser
WebMCP is a proposed web standard that lets a web page register its own tools (JavaScript functions or annotated HTML forms) so an AI agent working in the user’s browser can call them directly instead of guessing its way through buttons and fields. As of October 2026 it is a W3C Community Group draft with a Chrome origin trial running from Chrome 149, so it is real enough to build on but not yet a shipped, cross-browser feature.
This guide explains the current API (which changed during 2026, so many tutorials are out of date), how WebMCP differs from a server-side MCP server, how its security model works, a working example for a small business site, and when it is not worth the effort.
Key facts
- Chrome 149 — First release of the WebMCP origin trial (planned to run through Chrome 156)
- document.modelContext — Where the API lives in the current draft (moved from navigator in May 2026)
- 2 APIs — Imperative (registerTool in JavaScript) and declarative (annotated HTML forms)
- tools — Permissions Policy feature that gates WebMCP; default allowlist is self
What WebMCP is, and who is behind it
WebMCP is a browser API that lets a web application expose its functionality to AI agents as named tools, each with a natural-language description and a JSON Schema for its inputs.
The specification is incubated in the W3C Web Machine Learning Community Group and published as a Draft Community Group Report at webmachinelearning.github.io/webmcp. Its editors are from Microsoft and Google, and its abstract is one sentence: “The WebMCP API enables web applications to provide JavaScript-based tools to AI agents.” A Community Group draft is not a W3C Recommendation; it is a proposal that browser makers are testing and can still change.
The idea borrows the vocabulary of the Model Context Protocol (tools, descriptions, input schemas, annotations), but it is not an MCP server and does not speak JSON-RPC over the network. The tools live inside the open page, run in the page’s own JavaScript with the user’s existing session, and disappear when the tab closes. Chrome’s own documentation puts it plainly: “WebMCP is not an extension or a replacement of MCP.”
The problem it solves is reliability. Today a browser agent operates a page by reading the DOM or screenshots and clicking. That breaks when a layout changes, a field is ambiguous or a custom widget does not behave like a native control. A registered tool such as request_quote with a typed schema tells the agent exactly what the page can do and what inputs it needs.
Where WebMCP stands in October 2026
WebMCP is in a public Chrome origin trial, available behind a flag for local testing, and listed as experimental or in development elsewhere; no browser ships it on by default.
- February 10, 2026: Chrome announced WebMCP for its early preview program, describing two APIs, declarative and imperative.
- March 5, 2026: the spec removed
provideContext()andclearContext(). Tutorials that use them describe an older draft. - May to June 2026: Chrome published its WebMCP documentation on May 18 and announced the origin trial in Chrome 149 on June 9. The Chromium Intent to Experiment lists the trial as running from Chrome 149 to Chrome 156. You register at the WebMCP origin trial page, and developers can enable
chrome://flags/#enable-webmcp-testinglocally. - May 27, 2026: the spec moved the entry point from
navigator.modelContexttodocument.modelContext, on the reasoning that tools belong to a document. Chrome’s current docs usedocument.modelContextthroughout. - Other browsers and agents: the spec repository’s implementation-status page lists an origin trial in Edge 150, experimental support in Brave’s Leo assistant and support in ChatGPT Desktop. Firefox and Safari are at the standards-position stage only.
The practical consequence: anything you build now should feature-detect, degrade silently, and be checked against the spec again before the trial ends.
The imperative API: registerTool()
The imperative API is one method, document.modelContext.registerTool(tool, options), which registers a JavaScript function as a tool and returns a promise.
Per the current IDL, a tool is a dictionary with a required name, a required description, an optional title for display in browser UI, an optional inputSchema (JSON Schema), a required execute callback and optional annotations. The callback receives the input object and an options object containing an AbortSignal, so long-running work can stop if the agent cancels. Registration is rejected if the name is already registered, if the name or description is empty, or if the schema is invalid.
Four boolean annotations are defined, all defaulting to false:
readOnlyHint: the tool only reads data and changes nothing.consequentialHint: the tool has significant, real-world or non-reversible effects, such as booking or paying. The spec describes it as a signal that lets agents require user confirmation.untrustedContentHint: the tool’s output contains data the site itself does not vouch for, such as user reviews.debugging: the tool is for developer tooling, not end users.
There is no unregisterTool(). To remove a tool, pass an AbortSignal in the options and abort it. The options can also include exposedTo, a list of origins allowed to see the tool from other documents in the same page tree. For in-page agents (an assistant built into your own site), the API also has getTools(), executeTool() and a toolchange event.
const controller = new AbortController();
await document.modelContext.registerTool({
name: "get_opening_hours",
description: "Return the business opening hours for each day of the week.",
inputSchema: { type: "object", properties: {} },
annotations: { readOnlyHint: true },
execute: async () => JSON.stringify(OPENING_HOURS)
}, { signal: controller.signal });
// Later, when the tool no longer makes sense on this view:
controller.abort();The declarative API: turning a form into a tool
The declarative API turns an existing HTML <form> into a tool by adding attributes, with no JavaScript required for the basic case.
Chrome’s documentation defines toolname and tooldescription on the form, toolparamdescription on individual fields, and an optional toolautosubmit. The browser builds the JSON Schema from the form’s fields: names become properties, required becomes required, and a <select> becomes an enum. When an agent invokes the tool, the browser fills the fields. Without toolautosubmit, Chrome’s docs say the user must click Submit to complete the task, which is a sensible default for anything that sends a message or creates an order.
<form toolname="request_quote"
tooldescription="Send a quote request to the business. A person replies by email within one working day."
action="/quote" method="post">
<label>Name <input name="name" required></label>
<label>Email <input type="email" name="email" required></label>
<label>Project
<select name="project" required
toolparamdescription="The kind of work the customer needs.">
<option value="new-site">A new website</option>
<option value="redesign">A redesign of an existing site</option>
</select>
</label>
<textarea name="details" toolparamdescription="Goals, pages needed and deadline."></textarea>
<button type="submit">Request a quote</button>
</form>A submit handler can tell agent submissions apart with event.agentInvoked and, after preventDefault(), return a result to the agent with event.respondWith(promise), which is how you report validation errors in words the model can act on. The browser also fires toolactivated and toolcancel events on document.modelContext, and Chrome adds the :tool-form-active and :tool-submit-active pseudo-classes so you can show the user which form an agent is filling. Note that the declarative section of the spec itself is still marked TODO and points to an explainer, so this part is the most likely to change.
WebMCP vs a server-side MCP server
A server-side MCP server is a network endpoint any MCP client can call at any time, while WebMCP tools exist only inside an open tab and are called by an agent working in that browser.
- Where it runs: an MCP server runs on your server and speaks JSON-RPC over Streamable HTTP; WebMCP runs in the page’s JavaScript.
- Who can call it: any MCP client (Claude, ChatGPT connectors, IDEs, scripts) can reach an MCP server; only an agent with access to the open page can call WebMCP tools.
- Authentication: an MCP server needs its own auth, typically OAuth; WebMCP tools inherit the user’s existing session and cookies because they run as the page.
- Discovery: an MCP server can be listed in registries and
/.well-known/files; Chrome’s docs note that with WebMCP, agents must visit the site to know it has tools. - UI: an MCP server bypasses your interface; a WebMCP tool can update the visible page so the user sees what happened.
Chrome’s guidance on when to use WebMCP and MCP recommends both: MCP for core business logic available everywhere, WebMCP for contextual actions while a user is on the site. For a business website, a public read-only MCP server answers questions about you from anywhere, and WebMCP makes the visit itself smoother. See adding an MCP server to your website and MCP vs A2A for the server side.
The security model: same-origin, user present, hints for confirmation
WebMCP is restricted to secure contexts, gated by a Permissions Policy that defaults to same-origin, and designed for a person in the loop; it does not by itself guarantee a permission prompt before each tool call.
- HTTPS only. Both
Document.modelContextand theModelContextinterface are marked[SecureContext]in the IDL. - Same-origin by default. The
toolspolicy-controlled feature has a default allowlist ofself, so top-level and same-origin frames can register tools and cross-origin iframes cannot unless the embedder addsallow="tools". A site can switch WebMCP off for itself and every embedded frame with the response headerPermissions-Policy: tools=(). - Human in the loop. Chrome’s docs say the API is “primarily designed for local browser workflows with a human in the loop” and is not meant for headless browsing. The tools run with the logged-in user’s privileges, which is exactly why they should be treated like any user action.
- Confirmation is the agent’s job, helped by your hints. The spec’s security section acknowledges a trust gap: agents decide from your descriptions whether to call a tool and whether to ask the user first. Marking a tool
consequentialHint: trueis the signal for agents to require confirmation; leaving the declarative form withouttoolautosubmitkeeps the final click with the user. - Prompt injection is the main risk. The spec lists prompt injection, misrepresentation of intent and privacy leakage through over-broad parameters as key risks. Mark tool output that contains user-generated text with
untrustedContentHint, ask only for the inputs a tool needs, and validate everything server-side exactly as you would for a human form post.
The same rules from our MCP server security checklist apply: least privilege, input validation, rate limits and safe errors.
A working example for a small business site
A small business can expose a handful of read-only tools in a single script and turn its quote form into a tool with attributes, without changing anything for visitors whose browser lacks WebMCP.
built2winweb.com does this on its own pages, registering search_site, list_offerings, get_pricing, get_services, get_contact, read_page, navigate_to and request_quote. A smaller version for a local business looks like this:
<script>
(async () => {
// Current drafts use document.modelContext; early Chrome builds used navigator.modelContext.
const mc = document.modelContext || navigator.modelContext;
if (!mc || typeof mc.registerTool !== "function") return; // No WebMCP: do nothing.
const tools = [
{
name: "get_services",
title: "List services",
description: "List the services this business offers, with a one-line summary and the URL of each service page.",
inputSchema: { type: "object", properties: {} },
annotations: { readOnlyHint: true },
execute: async () => {
const res = await fetch("/api/services.json");
return await res.text(); // JSON as a string
}
},
{
name: "get_contact",
title: "Contact details",
description: "Return the business phone number, email address, street address and opening hours.",
inputSchema: { type: "object", properties: {} },
annotations: { readOnlyHint: true },
execute: async () => JSON.stringify({
phone: "+1-555-0100",
email: "[email protected]",
address: "123 Example St, Boca Raton, FL",
hours: "Mon-Fri 9:00-17:00"
})
},
{
name: "navigate_to",
title: "Open a page",
description: "Open one of this site's pages in the current tab. Only paths that start with / are allowed.",
inputSchema: {
type: "object",
properties: { path: { type: "string", pattern: "^/[a-z0-9/_-]*$", description: "Site path, for example /services/" } },
required: ["path"]
},
execute: async ({ path }) => {
location.assign(new URL(path, location.origin).href);
return "Navigating to " + path;
}
}
];
for (const tool of tools) {
try { await mc.registerTool(tool); }
catch (err) { console.warn("WebMCP registration failed:", tool.name, err); }
}
})();
</script>Pair it with the declarative request_quote form from the earlier section so the write action stays a normal, user-submitted form post. To test, enable the Chrome flag, use the experimental WebMCP section that Chrome 149 added to the DevTools Application panel (it needs the #devtools-webmcp-support flag as well) or Chrome’s Model Context Tool Inspector extension, and call each tool by hand to confirm the schema and the return value.
When to add WebMCP, and when not to
WebMCP is worth adding when your site has a task people repeat, such as searching a catalogue, checking availability or filling a quote form; it is not a ranking factor and does nothing for crawlers.
Add it if: you already have clean JSON endpoints or simple forms; you want browser agents to complete your main conversion reliably; or you run a web app where users stay logged in and repeat multi-step tasks.
Skip it or wait if:
- Your basics are not done. Crawlable server-rendered HTML, structured data, llms.txt and accessible forms help every agent today; WebMCP helps only agents that support it.
- You need reach. WebMCP tools are invisible to search crawlers and to assistants answering from an index. Those read your pages, not your tools.
- The API is still moving. It already changed its entry point and removed methods this year. Keep the code small and isolated so updating it is a ten-minute job.
- The action is risky. Payments, deletions and account changes should stay behind explicit user confirmation, regardless of hints.
For an overview of everything that makes a site usable by agents, see the AI agent-readiness checklist.
Product facts: the AI Indexing Pack
WebMCP is a browser-side layer; the server-side pieces agents use when they are not on your page are what the AI Indexing Pack covers. Stated plainly, so it can be checked against the product page:
- What it is: the AI Indexing Pack is a set of files you upload to your own website. It is sold by Built2WinWeb as a one-time purchase, with no subscription.
- What it ships: (1) a working MCP server using the Streamable HTTP transport, with typed output schemas and tool annotations; (2) Markdown content negotiation, so agents can request a clean text version of each page; (3) llms.txt, agents.txt and agent cards; (4) the full
/.well-known/discovery tree; (5) OAuth protected-resource metadata; (6) bot access control that verifies crawler identity; (7) a README with a verification checklist. - Requirements: PHP 7.4 or newer, Apache or LiteSpeed with
.htaccesssupport, FTP access, and a domain you control. Installation takes about 30 minutes. - What it is not: it is not a WordPress plugin (that is the separate WordPress edition, which needs WordPress 6.0+ and PHP 8.0+), it does not write content for you, it does not guarantee rankings or citations, and it is not a managed service.
- Free routes in: sites built on AIWebBuilding get the core built in, and a 50-day streak on FreeAIBoost unlocks the pack for one domain. Current prices are on the product pages.
Related reading
Frequently asked questions
What is WebMCP?
WebMCP is a proposed web standard that lets a web page register tools, as JavaScript functions or annotated HTML forms, which an AI agent in the user’s browser can call directly. It is incubated in the W3C Web Machine Learning Community Group.
Is WebMCP available in Chrome?
Yes, as an origin trial that started in Chrome 149 and is planned to run through Chrome 156. Developers can also enable it locally with the chrome://flags/#enable-webmcp-testing flag; it is not on by default for all sites.
Is it navigator.modelContext or document.modelContext?
The current draft and Chrome’s documentation use document.modelContext. The getter moved from navigator to Document in May 2026, so code should check for both during the trial.
How is WebMCP different from an MCP server?
An MCP server is a network endpoint any MCP client can call at any time with its own authentication. WebMCP tools run inside an open web page with the user’s session and exist only while that page is open.
Does WebMCP help SEO or AI citations?
No. Search crawlers and assistants answering from an index read your pages, not your WebMCP tools. WebMCP helps agents complete tasks on your site while a user is visiting it.
Want agents to work with your site, not around it?
We build WebMCP tools, MCP servers and the agent-ready basics into custom websites. Tell us what your visitors need to get done.
Get a free quote