Skip to content
TestWebMCP

Guides

How to add WebMCP to your site

Register a tool with document.modelContext.registerTool(), or add toolname and tooldescription attributes to a form you already have. Test it in Chrome with the WebMCP flag on, then join the origin trial so Chrome turns it on for your visitors. A first read-only tool takes about twenty lines.

Updated

1. Pick one thing your site already does

Start with something that only reads: a product search, an order lookup, a store finder, a docs search. It's safe for an agent to call, and there's nothing to undo if it sends odd input. Add actions that change things, like adding to a basket, once the first tool works.

Give each tool one job. Two tools, search_products and get_product, are easier for an agent to use than one products tool with a mode setting.

2a. Register it in JavaScript

A JavaScript tool is a function on your page. It can call your existing API client, read the page's state and return what the agent needs.

function registerTools() {
  const mc = document.modelContext;
  if (!mc) return; // not Chrome, not HTTPS, or WebMCP is off

  mc.registerTool({
    name: "search_products",
    description:
      "Search the product catalogue. Use when the user wants to find or compare products. " +
      "Returns up to 10 matches with name, price and link.",
    inputSchema: {
      type: "object",
      properties: {
        query: { type: "string", description: "What to search for", example: "running shoes" },
        max_price: { type: "number", description: "Highest price to include, in USD" }
      },
      required: ["query"]
    },
    annotations: { readOnlyHint: true },
    async execute({ query, max_price }) {
      try {
        const results = await api.search({ query, maxPrice: max_price, limit: 10 });
        return { content: [{ type: "text", text: JSON.stringify(results) }] };
      } catch (err) {
        return { isError: true, content: [{ type: "text", text: `Search unavailable: ${err.message}` }] };
      }
    }
  });
}

if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", registerTools, { once: true });
} else {
  registerTools();
}

A few things in that example matter:

  • It uses document.modelContext. Older examples use navigator.modelContext, which Chrome doesn't have, so agents never see tools registered there.
  • The description says when to use the tool and what it returns. The agent reads it to decide whether the tool fits the task.
  • Every input has a type and a description. Use enums for fixed choices, and values a person could read, like "express" for a shipping option.
  • readOnlyHint: true tells agents the tool changes nothing. Leave it off, or set it to false, for anything that does.
  • Errors are returned as a result with isError: true and a message the agent can act on. If execute throws, Chrome only reports "invocation failed".
  • The tool is registered as soon as the page loads, and data is fetched inside execute. Agents look for tools soon after load.

In a single-page app, register a tool when the view that uses it appears and unregister it when the view goes away, so the list matches what the page can do. Register each name once, because Chrome refuses a duplicate.

2b. Or annotate a form

If the action is already an HTML form, you can make it a tool with two attributes and no JavaScript. The form's fields become the tool's inputs.

<form toolname="search_products"
      tooldescription="Search the product catalogue. Use when the user wants to find a product."
      action="/search" method="get">
  <input name="query" type="text" required>
  <button type="submit">Search</button>
</form>

Give every input a name, and use required, type and pattern to describe what it accepts. Add toolautosubmit only where it is safe for the form to submit without the person pressing the button.

3. Test it in Chrome

  1. Open chrome://flags/#enable-webmcp-testing, set it to Enabled and relaunch Chrome.
  2. Load your page over HTTPS. WebMCP doesn't exist on plain HTTP pages, but localhost counts as secure, so local development works.
  3. In the DevTools console, await document.modelContext.getTools() lists what the page registered. Chrome's Model Context Tool Inspector extension shows the same list and lets you call each tool.
  4. Once the page is public, scan it with Test WebMCP. The scan does the same checks, calls your read-only tools with inputs built from their schemas and marks any that fail. If a property has an example, the scan uses that value as the input.

4. Turn it on for visitors

The flag only changes your own browser. For WebMCP to work for your visitors, join the WebMCP origin trial (open from Chrome 149) at developer.chrome.com/origintrials, register your domain and add the token to every page that registers tools:

<meta http-equiv="origin-trial" content="YOUR_TOKEN">

You can also send it as a response header, Origin-Trial: YOUR_TOKEN. The token only works on your domain and expires, so note when to renew it.

A checklist before you ship

  • Tools are registered on document.modelContext, within a few seconds of load.
  • Each tool has a specific name, a description that says when to use it, and a schema with described properties.
  • Read-only tools set readOnlyHint: true, and no other tool does.
  • Calling each read-only tool returns a real result, and errors come back as readable messages.
  • Results are short, with only what the agent needs.
  • The page is on HTTPS with a valid certificate and carries an origin trial token.
  • Your Content Security Policy doesn't block the script that registers the tools.

Test WebMCP checks each of these. See how it works for the full rubric, or why tools aren't detected if the scan finds nothing.