I Added WebMCP to My Site in 100 Lines. Here's Why You Should Too.
AI-generatedLast week I spent an afternoon adding WebMCP to this site. The whole thing is about a hundred lines of TypeScript. It exposes two actions — listing my blog posts and sending me a contact message — as structured tools that an AI agent running inside the browser can call directly.
I don't know for certain that WebMCP is the standard that wins. Nobody does yet. But I added it anyway, and I think most people building for the web should too. The reasoning is simple: the cost is tiny, the downside is nothing, and if this is even roughly how agents end up interacting with the web, the people who were there early will have shaped how their business gets represented to every agent that follows.
Let me make the case.
What WebMCP actually is
You already know the shape of this problem. AI agents are starting to use websites — booking things, filling forms, pulling information — on behalf of a user. Today they mostly do it by looking at the rendered page: screenshotting the DOM, guessing which <div> is the "Submit" button, typing into fields they hope are the right ones. It works until your layout changes, an A/B test swaps a label, or a cookie banner eats the click. It's brittle, slow, and burns tokens interpreting pixels.
WebMCP flips that around. Instead of the agent reverse-engineering your UI, you declare what your site can do. It's the Model Context Protocol — the same idea behind MCP servers — brought into the page itself. The browser exposes a modelContext object, and you register tools on it:
const mc =
(document as { modelContext?: ModelContext }).modelContext ??
(navigator as Navigator & { modelContext?: ModelContext }).modelContext
if (!mc?.registerTool) return
mc.registerTool({
name: 'send-contact-message',
description:
'Send a message to Felix Hans (Pyrra web studio) by email — a project ' +
'inquiry, a question about the BFSG accessibility check, or general contact.',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Name of the sender' },
email: { type: 'string', description: 'Replies go here' },
message: { type: 'string', description: 'Plain text, max 5000 characters' },
},
required: ['name', 'email', 'message'],
},
async execute(input) {
// ...validate, then POST to the same /api/contact the form already uses
},
})
That's it. A name, a description written for a model to read, a JSON Schema for the inputs, and a function that does the work. The agent no longer hunts for my contact form — it reads that this site can send Felix a message, asks the user to confirm, and calls the function. Structured input, structured result, no DOM archaeology.
It's a Chrome origin trial right now — experimental, behind a flag, document.modelContext in recent builds and navigator.modelContext before that. This is genuinely early. I want to be honest about that, because the honesty is what makes the rest of the argument hold up.
How WebMCP differs from a classic MCP server
If you've built an MCP server, the mental model is identical — tools, descriptions, JSON Schema inputs — but the location changes everything. A classic MCP server runs on a backend and exposes tools to an AI application out-of-band. WebMCP exposes tools from the page the user is already on, which means the agent inherits the user's session, their login, their permissions. It's not calling your API as a stranger; it's acting inside the tab as the person sitting there. That's a fundamentally more useful place for a lot of tasks to happen — and it's why the front end is where this belongs.
The two things I exposed — and why only two
I registered exactly two tools:
list-blog-posts— read-only, pulls the index from my existing/feed.xml.send-contact-message— writes, by reusing the same/api/contactendpoint my form already posts to.
I could have exposed a dozen. I deliberately didn't. The best practice here mirrors good MCP server design: few tools, clear boundaries, no overlap. An agent handed thirty vaguely-named functions makes worse decisions than one handed two obvious ones. Two tools that each map cleanly to a real user intent — "find something to read" and "get in touch" — is a better surface than an exhaustive API dump.
Notice what I didn't build: no new backend. list-blog-posts reads the feed I already generate. send-contact-message calls the endpoint my contact form already hits. WebMCP was a thin adapter over capabilities that existed. That's the part people underestimate — for most sites, the actions worth exposing are already implemented. You're not building features. You're describing them.
Why "early" is the actual argument
Here's the part I care about. The case for adding WebMCP now isn't "it's the future, trust me." It's that the economics are lopsided in a specific way.
The cost is close to zero. One afternoon. A hundred lines. No new infrastructure, no new endpoint, no new thing to maintain when it's built on top of endpoints you already maintain. If WebMCP goes nowhere, I've lost an afternoon and a file I can delete in thirty seconds. That's the entire downside.
The upside compounds, and it compounds for whoever's there first. When an agent can either scrape your competitor's form and guess, or call your clean, self-describing tool, which site do you think it completes the task on? Which one does it recommend when the user asks "who should I contact about this"? Early adopters don't just get a technical edge — they get to define the vocabulary. My tool descriptions are written in my words: what my studio does, what the BFSG accessibility check is, when to book a call instead of emailing. I'm handing agents a script for how to represent my business, before anyone else in my niche has written one.
This is a cheap option on a big maybe. In finance terms, adding WebMCP now is buying a long-dated call option for almost nothing. If the agentic web arrives, the option pays off enormously. If it doesn't, the option expires and you're out the premium — an afternoon. You don't take that bet because you're certain. You take it because the payoff is asymmetric and the entry price is a rounding error. Waiting until it's "proven" means waiting until the advantage is gone, because by then everyone has one.
The people who added structured data (Schema.org) to their pages in 2011 didn't know rich snippets would matter. The ones who did it early got the rich results first and learned the ropes while it was cheap. WebMCP has the same smell.
It degrades gracefully — which is why the risk is real-low, not fake-low
The reason I can say "zero downside" and mean it is progressive enhancement. The very first thing my code does is check whether modelContext even exists:
if (!mc?.registerTool || registered) return
No agent-capable browser? The function returns immediately and nothing happens. Human visitors never know it's there — the site is byte-for-byte the same for them. The contact form still works. The blog still works. WebMCP is purely additive: a capability that lights up only for clients that can use it, and is invisible to everyone else. There's no version where adding it makes the normal experience worse.
That's the difference between a cheap bet and a reckless one. A reckless bet on unproven tech means rewriting your stack around it. This is the opposite — a self-contained module, feature-detected, that touches nothing else.
The parts to take seriously
I'd be doing the same thing I criticize other people for if I pretended this was all upside. Two things deserve real thought:
Anything that writes needs a confirmation gate. My send-contact-message tool validates input and, by convention, the agent confirms the message with the user before calling it. You do not want an agent firing off actions — payments, bookings, emails — without a human in the loop. Read-only tools are safe to expose freely. Write tools need guardrails, and the guardrails are your responsibility, not the browser's.
Treat tool output as untrusted, both directions. The spec has an untrustedContentHint annotation for a reason. If your tool returns content that came from users, mark it — you don't want a comment field turning into a prompt-injection vector for the agent reading it. This is a new surface, and new surfaces have new failure modes. Being early means you also get to learn these while the stakes are small.
Neither of these is a reason not to adopt. They're reasons to adopt carefully — start with read-only tools, add writes with confirmation, annotate honestly.
My take
WebMCP might not be the thing. But "might not be the thing" is doing a lot less work than it sounds like when the cost of being wrong is one afternoon and a deletable file, and the cost of being late is that your competitors have already taught every agent how to talk about their business instead of yours.
That's the whole trade. Cheap to try, invisible when idle, and disproportionately valuable if the agentic web shows up the way it looks like it might. I took the bet. If you build for the web, I think you should look at it too — and if you want to see the hundred lines or talk it through, just message me. There's now more than one way to do that.