Right now, when an AI agent visits your website, it guesses. It screenshots the page, reads the DOM, and tries to infer what your buttons do and which link goes where. It’s the digital equivalent of handing someone a menu in a language they don’t read and watching them point at pictures.
That guessing is slow and brittle, and it’s easy to get wrong. Worse, from the agent’s point of view your site barely exists as something it can act on. It’s a wall of pixels to be parsed, not a set of capabilities to be used. As more people delegate real tasks to agents, the sites that stay un-actionable get skipped.
WebMCP fixes that. It lets your site expose structured, named tools an agent can call directly, with no screenshots and no guessing. I added it to my own WordPress site this week, built to the official W3C standard with a fallback so it works in today’s browsers, and you can see it live on my /mcp/ page. This is the next entry in a series I’ve been running here: I implemented Google’s agentic resource discovery spec and walked through adding an Open Knowledge Format bundle to WordPress. Those made my site machine-readable. WebMCP makes it machine-actionable. Here’s every file.
Key Takeaways
- WebMCP lets a website expose callable tools (with names, schemas, and descriptions) that AI agents invoke directly, instead of scraping the page.
- Two different projects share the name: the official W3C standard (
document.modelContext) and jasonjmcghee’s library (a localhost bridge that works today). The standard is the destination; the library is the bridge. - The durable approach is to define your tools once in the spec’s shape, then feature-detect: register natively when the browser supports it, fall back to the library when it doesn’t.
- The tool description is conversion copy aimed at an AI: the meta description of the agentic layer.
- This is a first-mover positioning and learning play, not a traffic channel yet. Build it to be early and to understand it, not for this quarter’s sessions.
What WebMCP actually is (and why there are two of them)
Before any code, you need the lay of the land, including the fact that “WebMCP” refers to two different things.
Callable tools instead of a guessing game
WebMCP is a way for your site to hand an AI agent a set of structured tools instead of a page to decode. Each tool has a name, a description, an input schema that defines its parameters, and an execute function that does the work. The agent reads the tool list, picks the right one, and calls it the same way it would call any other function.
It borrows directly from the Model Context Protocol (MCP), the standard for connecting AI models to external tools, and shares its vocabulary: tools, schemas, parameters. The difference is that WebMCP is client-side and web-native. There’s no separate server to install and host, because the tools live in your page’s JavaScript.
Two projects that share the name
This trips everyone up, so let’s clear it now. Two distinct projects are both called WebMCP:
- The official W3C standard, maintained by the Web Machine Learning Community Group, with contributors from Microsoft and Google. It defines a native browser API:
document.modelContext.registerTool({...}). This is the long-term, standards-track version. (webmachinelearning/webmcp) - jasonjmcghee/WebMCP, an open-source JavaScript widget that works in any browser today. It runs a localhost-only websocket bridge between your MCP client and the website, and you connect by pasting a one-time token into a small on-page widget.
Here’s the detail that resolves the confusion: jasonjmcghee now points people toward the official spec. So the right mental model isn’t “which one do I pick.” It’s “the standard is where this is going, and the library is how I bridge to it until browsers catch up.” You build for the first and lean on the second to ship now.
| Project | What it is | API | Works today? | Use it for |
|---|---|---|---|---|
| Official W3C spec | Native browser standard | document.modelContext.registerTool() | Chrome early preview only | The destination |
| jasonjmcghee/WebMCP | JS widget + localhost bridge | new WebMCP().registerTool() | Yes, any browser | Today’s fallback |
Can you actually use WebMCP today?
Short answer: yes, two ways, one native and early, one library-based and universal. Both have real limits worth being honest about.
The native path: Chrome has an early preview
The native document.modelContext API is real, but early. You can turn it on in Chrome behind a flag at chrome://flags/#enable-webmcp-testing for local development, and there’s an origin trial available from Chrome 149 for testing it on a live origin. (Chrome for Developers)
What you don’t have yet is stable, cross-browser support. No other browser ships it, and even in Chrome it’s explicitly subject to change. So the native API is something you can build and test against today, but not something a random visitor’s browser will speak this year.
The reality check: near-zero agents speak it yet
For the library fallback, the bar is higher than the marketing suggests. A visitor has to run npx @jason.today/webmcp on their own machine to start the bridge, then generate a token and paste it into your widget. Almost nobody is doing that yet.
And there’s a deeper gap nobody has solved: discovery. Even with perfect tools on your page, nothing tells an agent they exist before it visits. There’s no registry of WebMCP-enabled sites, no index. So be clear-eyed: this is a first-mover credibility and learning play. You build it now to understand the shape of agentic search and to be early, not because it drives traffic this quarter.
The approach: build to the standard, fall back for today
Here’s the decision that makes this whole thing durable, and it’s where my build differs from every other WebMCP tutorial I’ve seen: define your tools once, in the official spec’s shape, then feature-detect the transport.
Concretely, each tool is a plain object, { name, description, inputSchema, execute }, which is exactly what the W3C API expects. Then a small adapter decides how to register them:
- If
document.modelContextexists in the browser, register the tools natively. No bridge, no token, no widget. - If it doesn’t, fall back to jasonjmcghee’s vendored widget so the page still works in every browser right now.
The payoff is that you write to the future and ship in the present. The day Chrome (or any browser) turns native WebMCP on for real, your page upgrades itself with zero rewrite, and the token-paste friction simply disappears. Most existing guides wire everything straight to the library. Same destination, but you’d have to rip it out and redo it later. This way you don’t.
Browser supports document.modelContext? | What happens |
|---|---|
| Yes | Register the tools natively (no widget, no token) |
| No | Load the fallback widget and token bridge |
The build, file by file
This is a WordPress child theme. There are five pieces, and every snippet below is the real code running on /mcp/. The best part: the tools mostly wrap the WordPress REST API you already have, so there’s almost no new backend to write.
The page: a /mcp/ template via the slug hierarchy
The page itself is a child-theme template named page-mcp.php. WordPress’s template hierarchy automatically applies a file named page-{slug}.php to any page with that slug, so a page with the slug mcp renders through this file with no template-picker step. It holds the hero, a short connect guide, and the tool list.
<?php
/** /mcp/ WebMCP connection hub. Auto-applies to the page with slug "mcp". */
get_header();
?>
<header class="page-hero">
<h1>Connect your AI agent to this site</h1>
<p>This site speaks WebMCP. Connect your MCP client and your agent can
search the blog, pull full articles, and look up services on its own.</p>
</header>
<!-- connect steps + tool list -->
<?php
get_footer();
The tools: define once, in the spec’s shape
The tools live in assets/js/mcp-tools.js. Here’s one real tool, search_posts, in full. Note the shape matches the official spec exactly, and the execute function just calls the WordPress REST API and returns a content array:
{
name: 'search_posts',
description: 'Search the SEO blog by keyword and return matching posts ' +
'(title, slug, URL, excerpt). Use this first when the user asks what ' +
'Todd has written about a topic.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Keyword or phrase to search for.' }
},
required: ['query']
},
execute: function (args) {
var url = WP + 'posts?search=' + encodeURIComponent(args.query) +
'&per_page=10&_fields=title,slug,link,excerpt,date';
return fetchJson(url).then(function (posts) {
return { content: [{ type: 'text', text: formatPosts(posts) }] };
});
}
}
Key insight
That description field looks like documentation, but it’s really conversion copy aimed at the model choosing a tool. It’s the meta description of the agentic layer. Vague descriptions get your tools ignored; sharp ones get them used. It’s the one part of this build only an SEO tends to notice.
I registered five tools total:
| Tool | What it returns | Backed by |
|---|---|---|
search_posts | Matching posts (title, slug, URL, excerpt) | WP core REST (wp/v2/posts) |
get_post | Full plain-text content of one post | WP core REST |
list_posts | Most recent posts | WP core REST |
get_services | The service offerings | Custom route tmor/v1/services |
get_consulting_info | Structured “who is Todd + how to engage” | Custom route tmor/v1/site-info |
Three of those (search_posts, get_post, list_posts) run entirely off WordPress’s built-in wp/v2/posts endpoint, with zero new backend. The other two hit custom routes I’ll cover next.
Then comes the adapter, the feature-detection block that picks the transport:
// Native: the official W3C spec. No bridge, no token, no widget.
if (document.modelContext && typeof document.modelContext.registerTool === 'function') {
tools.forEach(function (t) { document.modelContext.registerTool(t); });
return;
}
// Fallback: jasonjmcghee's widget, works in every browser today.
var mcp = new window.WebMCP({ color: '#FFD300' });
tools.forEach(function (t) {
mcp.registerTool(t.name, t.description, t.inputSchema, t.execute);
});
Same tool definitions feed both paths. That’s the whole trick.
The custom endpoints: two REST routes
Two of my tools needed data WordPress core doesn’t expose, so I registered two read-only REST routes in inc/mcp-tools.php under a tmor/v1 namespace: /services and /site-info. Registering a route is a few lines:
register_rest_route( 'tmor/v1', '/site-info', array(
'methods' => 'GET',
'callback' => 'tmor_mcp_site_info_route',
'permission_callback' => '__return_true', // Public, read-only marketing data.
) );
The site-info payload is hand-authored on purpose. It’s the agent-facing pitch, the structured answer a model reads back when someone asks it “who is this person and how do I hire them.” It’s the machine-callable sibling of my AI information page, which is the same idea written for humans. One source of truth; edit it in one place.
Loading it safely: conditional enqueue + discovery
You don’t want the widget and tool scripts loading on every page. In functions.php, an is_page('mcp') check loads them only on /mcp/:
if ( is_page( 'mcp' ) ) {
wp_enqueue_script( 'webmcp', $theme_uri . '/assets/js/vendor/webmcp.js', array(), $ver, true );
wp_enqueue_script( 'tmor-mcp-tools', $theme_uri . '/assets/js/mcp-tools.js', array( 'webmcp' ), $ver, true );
}
Watch out
Vendor the source build of jasonjmcghee’s webmcp.js, not the tagged release. The release artifact is wrapped as a CommonJS/IIFE bundle that exposes no browser global, so dropping it in via a script tag silently does nothing: no error, no widget. The source build defines the WebMCP class globally, which is what you actually want. I lost real time to that before reading the bundle.
Finally, make the page findable: add a footer-menu link to /mcp/ and an “Agent Tools (WebMCP)” section to your llms.txt so anything reading that file knows the tools exist.
Connecting an agent and testing it
This is the payoff, actually watching an agent call your site. There are two paths depending on the browser.
For the native path, enable the Chrome flag, load /mcp/, and your tools register automatically against document.modelContext, with no widget and no token. For the fallback path, run npx @jason.today/webmcp to start the bridge, ask your MCP client for a connection token, and paste it into the yellow widget in the corner of the page.
Either way, verify the plumbing first: open /wp-json/tmor/v1/services and /wp-json/tmor/v1/site-info in a browser and confirm each returns JSON. Then ask your connected agent to “search the blog for AI search” and watch it call search_posts and hand back real results. You can see the whole thing live on my /mcp/ page.
What this means for SEO
Step back from the code, because this is where it gets interesting for anyone doing search. WebMCP is the front edge of a new optimization layer, and it maps cleanly onto things you already know.
Tool discoverability is the new indexing problem: agents can’t use tools they can’t find. Tool descriptions are the new meta descriptions: copy written to win a selection, except the chooser is a model. Schema and parameter design is the new on-page structure: clear, well-named inputs are what make an agent’s call succeed instead of fail. And “agentic CRO” is coming: A/B testing tool descriptions and monitoring how often agents complete a task successfully.
This is the action layer sitting on top of the work of getting cited in AI search and the broader shift toward agentic-led growth. It’s answer engine optimization with hands. And to say it one more time, because the honesty matters: build this to be early and to learn the terrain, not for traffic this quarter.
Conclusion
Next Steps
- Read both repos, the official spec at
webmachinelearning/webmcpand jasonjmcghee’s library, so you know the destination and the bridge. - Enable
chrome://flags/#enable-webmcp-testingand try the nativedocument.modelContextAPI in a throwaway page. - Pick three to five tools your site already supports through the WordPress REST API.
- Ship a /mcp/ page with the define-once, feature-detect pattern, then add it to your
llms.txt.
Getting your site ready for agents is the same instinct as getting it ready for AI answers. It’s all answer engine optimization, just earlier on the curve.
WebMCP-on-WordPress Checklist
- Decide your tools: pick three to five actions your site already exposes through the WordPress REST API.
- Vendor the widget: download the source build of jasonjmcghee’s
webmcp.jsinto your child theme, not the tagged release. - Write the tools once: define each as
{ name, description, inputSchema, execute }in a JS file, withexecutecalling your REST endpoints. - Add the adapter: register natively via
document.modelContextwhen present, otherwise fall back to the widget. - Add any custom data: register read-only
tmor/v1REST routes for anything core REST doesn’t already cover. - Create the page: add
page-mcp.phpfor a /mcp/ page and enqueue the scripts only on that page. - Make it discoverable: add a footer link and an “Agent Tools (WebMCP)” entry in
llms.txt. - Test both paths: confirm the REST endpoints return JSON, then connect an agent via the Chrome flag or the npx bridge and token.
Frequently Asked Questions
What is WebMCP?
WebMCP is a way for a website to expose structured tools, each with a name, description, input schema, and an execute function, that an AI agent can call directly instead of screenshotting the page and guessing. It shares its vocabulary with the Model Context Protocol but runs client-side, in the browser.
Is WebMCP the same as MCP?
No, though they’re closely related. MCP (Model Context Protocol) connects AI models to external tools, usually through a server you install and host. WebMCP borrows MCP’s concepts (tools, schemas, parameters) but is web-native and client-side. The tools live in your page’s JavaScript, with no separate server to run.
Can I use WebMCP today?
Yes, two ways. Native support exists in Chrome behind the chrome://flags/#enable-webmcp-testing flag, with an origin trial from Chrome 149. For every other browser, jasonjmcghee’s library works now via a localhost bridge and a one-time token the visitor pastes into an on-page widget.
Do I need to be a developer to add WebMCP to WordPress?
Yes. It involves child-theme PHP and JavaScript, so you’ll need to be comfortable editing theme files. The good news is the tools mostly wrap the WordPress REST API you already have, so most of the work is defining tools and writing descriptions, not building new backend logic.
Should I use the official spec or the jasonjmcghee library?
Both. Define your tools once in the official spec’s shape (document.modelContext), then use the jasonjmcghee library as a fallback for browsers that don’t support the native API yet. When browsers ship native WebMCP, your page upgrades with no rewrite. The spec is the destination; the library is how you ship today.
Will WebMCP help my SEO right now?
Not in traffic terms. Almost no agents speak WebMCP yet, and tool discovery is unsolved. Its value today is first-mover positioning and learning the mechanics of agentic search before competitors do. Treat it as early answer engine optimization, not a near-term traffic channel.