The author's whole job: call document.modelContext.registerTool
once, with four fields you already understand from MCP. We read each one, then wire it to real
page code.
In Lesson 1 you placed WebMCP as the
in-page sibling of MCP and CDP. Now you play the website author. Your entire
surface is one method — registerTool — and its shape is the MCP tool descriptor you
already know, with the handler being a local JavaScript function.chrome
Here is a real registration, verbatim in shape from Chrome's imperative-API guide. Read it before the explanation — you can already guess most of it.
name — the stable id the agent calls. description — natural language;
this is the prompt the agent reads to decide whether to use the tool, so write it well.
inputSchema — a JSON Schema; the browser can validate the agent's input against it
before your code runs. execute — your async handler, receiving the validated
input and an AbortSignal, doing the real work, and returning a result.spec
execute is you
keeping it. Description quality ≈ tool quality.execute returns
In current Chrome, execute returns a plain string (or a value that
gets serialized to text) — the message the agent receives. Heads-up on churn: earlier WebMCP
drafts used an MCP-style {content:[{type:"text",text:…}]}. Teach yourself the plain-string
form Chrome ships today, and check the spec if you see the older shape.imperative-api
AbortSignalA tool should only exist while the page can actually do it. You unregister a tool by aborting the signal you passed at registration — no separate "unregister" method.spec
The other useful option is exposedTo — an array of origins allowed to
see the tool. Combined with the Permissions-Policy "tools" feature, this is WebMCP's
trust model. We give it a full lesson later; just know registration is where trust starts.
You are used to building UI for humans — buttons, forms, layout. WebMCP asks you to also publish the same capabilities as a machine contract. The button and the tool can call the very same function; you're just giving the agent a labelled front door instead of making it hunt for the button.
An execute handler runs on input chosen by an agent, which may be steered by
untrusted page content or a malicious prompt. Validate and sanitize inside execute just
as you would a network request handler — inputSchema checks shape, not intent. Never let a
tool do more than the current user is allowed to do.
You don't need the origin trial to feel the shape. Open any page, turn on the flag
(chrome://flags/#enable-webmcp-testing → Enabled → relaunch — full setup is
Lesson 3), open DevTools Console, and paste:
If document.modelContext is undefined, the flag isn't on yet — that's
exactly what Lesson 3 fixes. Ask me if the console throws something unexpected.
execute return to the agent?Chrome's Imperative API guide
— the source of the examples above (pizza-layer + to-do). Read its full registerTool
walkthrough, then the spec's tool dictionary
for every optional field.