WebMCP · Reference

WebMCP in one page

The entry point, the author API, the consumer API, and the tooling · a moving draft — verify against the spec

The shape of it

A page registers tools on document.modelContext. The browser is the host: it holds the registry and mediates between the page and an in-browser agent. No server, no JSON-RPC, no socket — same-origin JavaScript.spec Older name navigator.modelContext is being renamed to document.modelContext.

Turn it on

MechanismHow
Flag (local dev)chrome://flags/#enable-webmcp-testing → Enabled → relaunch (Canary 146+)
Origin trial (real site)Register domain (Chrome 149+), embed the token — no flag for visitors
Check it's livetypeof document.modelContext → "object"

Author API — register tools

CallDoes
registerTool(tool, opts)Publish a tool. Returns a Promise.
await document.modelContext.registerTool({ name: "add_todo", // 1–128 chars, [A-Za-z0-9_-.] title: "Add to-do", // optional human label description: "Add an item to the list", // NL prompt the agent reads inputSchema: { type:"object", properties:{ text:{type:"string"} }, required:["text"] }, execute: async ({ text }, { signal }) => `Added: ${text}`, // returns a string annotations: { readOnlyHint:false, untrustedContentHint:false } // optional hints }, { signal: controller.signal, exposedTo: ["https://trusted.example"] }); controller.abort(); // ← unregister the tool (no remove() method)

Tool descriptor fields

FieldRole
nameStable id the agent calls (1–128 chars).
descriptionNatural language — the agent reads this to pick the tool. Write it well.
inputSchemaJSON Schema for the arguments; browser validates input against it.
executeasync (input, {signal}) => result. Your handler; returns a string (current Chrome).
titleOptional human-readable label.
annotationsreadOnlyHint, untrustedContentHint — safety signals.

Return-shape churn: current Chrome returns a plain string from execute; earlier drafts used {content:[{type:"text",text:…}]} (MCP-style).

Consumer API — discover & call

WebMCPMCP analogueDoes
getTools({fromOrigins})tools/listList registered tools as RegisteredTool records.
executeTool(name, input, {signal})tools/callRun a tool; returns its result.
toolchange eventlist-changed notificationFires when the registry changes.
// discover, then call const tools = await document.modelContext.getTools(); // [{name, description, inputSchema, origin, …}] const out = await document.modelContext.executeTool("add_todo", { text:"buy milk" }); // out === "Added: buy milk"

Tooling — the consumer stand-in

ToolUse
Model Context Tool Inspector (extension)Lists a page's tools, calls them by hand, validates JSON Schemas; NL prompts default to gemini-3-flash-preview.chrome
Gemini in ChromeThe production in-browser agent that consumes WebMCP tools.
Raw APIgetTools / executeTool in the DevTools console.

WebMCP vs MCP vs CDP

Where tools liveHostTransport
MCPRemote serverMCP client processJSON-RPC over HTTP/stdio
CDP— (agent scrapes/drives)External driverRaw WebSocket to debug port
WebMCPIn the page (same origin)The browserIn-process JS API
Trust

Tools are origin-scoped. exposedTo limits which origins may call a tool; the Permissions-Policy "tools" feature (default ['self']) governs whether a frame may register at all. Treat execute input as untrusted — an agent may be steered by injected content. Validate intent, not just schema shape.