The scene plays out every time an AI agent has to do something on a website. Screenshot, read the DOM, find the button, click, wait, repeat. I've written that kind of automation for months: a React form field that ignores input because el.value = ... never reaches the value trackers, a comment editor that collapses if you scroll while typing, a CSS selector that breaks on the next redesign. An agent that browses like a human inherits all of a human's fragility, with none of the reflexes.
On August 8th I flipped the problem around on my own site: instead of letting agents guess where the "Book a call" button is, the page tells them. The mechanism is called WebMCP, and it fits in 158 lines.
WebMCP: the MCP contract, moved into the page
If you know MCP, the protocol for plugging external tools into an LLM, you already know the idea. A classic MCP server runs somewhere, exposes tools with a name, a description and a parameter schema, and the agent calls them. WebMCP takes that same contract and moves it into the browser: the web page itself declares its tools, in JavaScript, through a new browser API.
document.modelContext.registerTool({
name: 'open_booking_popup',
description: 'Open the Cal.com booking popup...',
inputSchema: { type: 'object', properties: { ... } },
execute: async (args) => { ... },
});
An agent driving the visitor's browser discovers these tools and calls them directly. No screenshots, no CSS selectors, no form-guessing. And since the code runs inside the page, it rides on the visitor's session: cart, account, browsing context.
On the standards side, this is a W3C draft pushed by Google and Microsoft, last published in April 2026. Chrome has it in an origin trial from version 149 through 156. The API already moved once along the way: it used to live on navigator.modelContext, it now lives on document.modelContext, and Chrome 150 deprecated the old surface while the origin trial still ships it. My component tries both, in that order. That's daily life with a spec in incubation, and a good reason to keep the whole thing in one file.
Three tools, 158 lines
In practice, my site registers three tools on every page, from a 158-line Next.js component mounted in the layout:
get_consulting_servicesreturns structured JSON: services, pricing, contact. What an agent would need ten requests to reconstruct by scraping, it gets in one call.get_booking_linkreturns the direct Cal.com link for the discovery call, in the right language.open_booking_popupis the interesting one: it opens the Cal.com booking popup on the page, prefilled with the name, email and context the agent passes in. The agent prepares everything, the human just picks a slot.
All of it is strict progressive enhancement: if the browser doesn't implement the API, the component does nothing. No risk for current visitors, no dependency, no impact on page load.
An agent shouldn't have to guess where the button is. The page can tell it.
The missing link: how an agent learns the tools exist
Registering tools is half the job. The other half, which the spec doesn't cover yet, is discovery: an agent landing from Google has no idea your page exposes anything. There is no standard convention for advertising WebMCP tools outside the page.
Until one emerges, I laid down three layers that point to each other:
- the
llms.txt, which agents already read, gains an "Agent Tools" section listing the three tools, their parameters, and an invitation to load a page instead of scraping; - the page's schema.org markup declares a
ReserveActionpointing at the booking, readable by classic crawlers; - the
robots.txtpoints to that section of thellms.txt.
An agent that runs a search, lands on the site and reads the llms.txt now knows it has better options than clicking around. It's a deliberate redirection of agent traffic onto the structured path.
Testing a standard nobody implements yet
Early-implementer problem: no mainstream assistant calls these tools today. To check the mechanism holds, I injected a mock of document.modelContext into the browser, reloaded the app, and played the agent myself. The three tools register, and calling open_booking_popup with a test name and email does open the Cal.com popup: the parameters show up in the iframe URL, the form comes prefilled.
I also wired a counter: every tool call sends a webmcp_tool_call event to my analytics. The day a real agent calls one of these tools, I'll see it. For now the counter reads zero, and that's expected.
The tool exists, nobody calls it yet. Which is exactly when installing it costs the least.
Should you equip your site now?
The honest answer: nothing is urgent, and the bet is asymmetric. The origin trial runs until Chrome 156, the spec can still move, and your visitors don't browse with an agent. But the entry cost is one 158-line component and two text files, and the trajectory is easy to read: agentic browsers are coming, and when they're here there will be two kinds of sites. Those that expose clean, callable, bookable actions. And those that agents keep scraping, with the reliability I described in the opening.
For an SMB site, the most valuable conversion is usually a booked meeting. Making that action callable by an agent means that the day a business owner says "find me a consultant and book a slot", their assistant can do it on your site rather than your competitor's.
If this is your kind of problem, integrating agents and MCP into an existing stack is exactly the work I do. We can talk.
