Every page on gaffer.sh now registers four typed WebMCP tools that a browser agent can call instead of scraping the DOM: docs search, pricing, MCP install config, and the signup URL. It took under 150 lines of Astro and inline JavaScript, no dependencies and no bundler config. Since shipping on 2026-08-28, gaffer.sh has recorded zero WebMCP tool calls from a real agent. That number is the point of this post.
Status, honestly
WebMCP is a W3C Community Group draft, not a shipped web standard. Chrome exposes it only in an origin trial, and no mainstream agent invokes the tools. We do not expect traffic from it this year.
Gaffer already serves five machine-readable surfaces (llms.txt, llms-full.txt, an OpenAPI 3.1 file, an RFC 9727 API catalog, and an MCP server card) and answers Accept: text/markdown on every page. WebMCP is the sixth. Adding one more surface to a site already built for machine readers is cheap enough that waiting for the spec to settle buys nothing.
What is WebMCP?
WebMCP is a browser API that lets a web page register typed tools an AI agent can call directly, instead of the agent driving the page by reading rendered HTML and synthesizing clicks. The spec is a draft in the W3C Web Machine Learning Community Group; the proposal and API were contributed by Google and Microsoft.
A tool is a name, a human-readable description, a JSON Schema describing its input, and a function that runs when an agent calls it. The page decides what exists. The agent sees a typed interface rather than a rendered document, so “what does this cost” becomes one call with a structured answer instead of a parse of a pricing grid that changes every redesign.
The tools run inside the page, with the user’s session and the user’s cookies. That is the whole security model, and it is why every tool we registered is read-only.
How is WebMCP different from an MCP server?
An MCP server is a separate process an agent connects to deliberately, with its own credentials and its own lifetime. WebMCP tools live inside a page, exist only while the tab is open, and inherit whatever session the browser already has.
| MCP server | WebMCP | |
|---|---|---|
| Where it runs | A process the agent launches or connects to | Inside the open page |
| Auth | Its own API key | The user’s existing browser session |
| Lifetime | As long as the client is connected | As long as the tab is open |
| Discovery | Config file, registry, or an explicit install | Load the page and look |
| Typical caller | A coding agent in your editor or terminal | A browser agent, in theory |
The discovery row is the structural weakness. There is no manifest, no .well-known entry, and no registry for WebMCP. An agent learns a page has tools by loading that page first. So WebMCP can make an already-in-progress visit cheaper, but it cannot make an agent decide to visit. A server-side MCP server, like Gaffer’s, is installed once and then available to every future question. That is the model behind test memory for coding agents.
Which agents can call WebMCP tools today?
None of the mainstream ones. As of July 2026, Gemini, Claude, ChatGPT, and Perplexity all ignore WebMCP tools, per one July 2026 survey of the ecosystem.
Browser support and consumer support are separate problems, and both are early:
- Chrome announced WebMCP for its early preview program in February 2026, exposes it behind a flag (
chrome://flags/#enable-webmcp-testing), and opened a public origin trial in Chrome 149. The survey above lists the trial as running through Chrome 156. - Edge has experimental support behind a flag.
- Firefox and Safari participate in the Community Group and have committed to nothing.
- Callers today are Chrome’s own “Model Context Tool Inspector” extension and the community MCP-B project’s extension (now shipped as Rook). Google has said Gemini in Chrome will consume WebMCP tools, which would make it the first mainstream consumer.
A page can therefore register tools that a browser understands and that nothing asks for. That is the current state of gaffer.sh.
How do you register a WebMCP tool?
Call document.modelContext.registerTool() with a name, a description, a JSON Schema for the input, and an execute function that returns the result.
const controller = new AbortController()
await document.modelContext.registerTool({ name: 'example.get_pricing', title: 'Get pricing', description: 'Current plans with price, storage, and retention.', inputSchema: { type: 'object', properties: { currency: { type: 'string', description: 'ISO 4217 code' }, }, }, annotations: { readOnlyHint: true }, execute: async ({ currency }, { signal }) => { const res = await fetch(`/api/pricing?currency=${currency ?? 'USD'}`, { signal }) return res.json() },}, { signal: controller.signal })Four details worth knowing before you write one:
- Tool names are 1 to 128 characters of
[A-Za-z0-9_.-]. - There is no
unregisterTool. You remove a tool by aborting the signal you passed at registration. - The spec moved the entry point from
navigator.modelContexttodocument.modelContextin mid-2026 (Chrome 150 deprecates the old name, per the July survey), so feature-detect both. annotations.readOnlyHinttells the agent the call has no side effects.
Full reference: the imperative API docs.
There is also a declarative form for anything already expressed as a form: put toolname and tooldescription on the <form>, toolparamdescription on the fields, and the browser derives the schema. SubmitEvent.respondWith() returns a structured result, and agentInvoked tells you an agent submitted it rather than a person. We have no forms worth exposing, so we skipped it.
What tools did we put on gaffer.sh, and why?
Four read-only tools, on every page, covering the four things a visitor’s agent would otherwise have to scrape.
| Tool | What it returns |
|---|---|
gaffer.search_docs | Up to 10 {title, url, description} hits from the curated index at /llms.txt |
gaffer.get_pricing | The Free, Pro, and Team table, computed at build time from the same package that renders the pricing page, so it cannot drift |
gaffer.install_mcp | The claude mcp add command, or the mcpServers JSON for Cursor and generic clients |
gaffer.signup_url | The register URL with UTM tags, so an agent-driven signup lands in analytics as its own channel |
“What does it cost”, “how do I install it”, “where is the doc about X”, “where do I sign up”. Nothing here writes anything, nothing takes free-form text into a mutation, and every tool carries readOnlyHint: true. Given that these execute with the visitor’s session, a write tool would need a threat model we have not written yet.
Each call also emits a PostHog event with the tool name and the page. That instrumentation is how we will know the day a real agent shows up, rather than finding out from a blog post.
Why ship something no agent can call?
Because the cost was an afternoon and the site is already where we document how Gaffer talks to agents. This is not a bet on the spec winning. If WebMCP stalls, we delete one component.
The agent-readiness surface was already there. A product whose pitch is that agents can query your test history should be reachable by an agent through the front door too. Writing about agent readiness while a browser agent has to scrape our pricing table would be a bad look, and a fair one.
The honest risk is the discovery gap. Even if Gemini in Chrome ships tool calling tomorrow, the agent still has to be on our page first, and nothing about WebMCP changes that. So this is a small improvement to visits that already happen, not a new channel.
What would change the verdict on WebMCP?
- Gemini in Chrome actually calling tools. Google has said it will consume them. Until it lands, the number in our PostHog dashboard stays at zero.
- The origin trial ending at Chrome 156. Trials end in a ship, an extension, or a quiet death. Which one happens tells you more than the spec text does.
- Firefox and Safari. Participation in a Community Group is not an implementation commitment. A positive standards position from either would change the calculus.
- Any discovery mechanism at all. A manifest or
.well-knownentry would turn WebMCP from a page enhancement into something an agent can find on purpose.
The MCP server is the part that helps an agent today
WebMCP is speculative. Gaffer’s MCP server is not: install it once and your coding agent can query test history, flaky tests, and pass-rate trends from your editor. Unlimited users on every plan. See how agents use test history for what that looks like in practice.
Start Free
Related
- Test intelligence for AI tools - Why coding agents need structured test history, not raw logs
- Gaffer for AI agents - Why Gaffer is built for agent-driven workflows
- MCP server docs - Install and tool reference
- AI agent test memory - Giving a coding agent history across runs