WebMCP How-To

WebMCP Imperative API: A Beginner’s Guide to registerTool()

The JavaScript side of WebMCP gives developers full control over the tools agents can call. Here's how registerTool() works, with simple examples and safety tips.

WebMCP imperative API illustration: four tool buttons between large green curly braces representing JavaScript code

WebMCP imperative API: the short answer

The WebMCP imperative API lets a web page register tools for AI agents with JavaScript, using document.modelContext.registerTool(). Each tool has a name, a description, an input schema and an execute function that runs your own page code. Optional hints mark tools as read-only or consequential, so agents and browsers can ask the person before acting. As of September 2026 it is experimental and used by Chrome’s trial and ChatGPT’s site tools.

The WebMCP imperative API is the main way developers expose a website’s actions to AI agents. Unlike the declarative approach, which works on plain HTML forms, it uses JavaScript. As a result, it gives you far more control over what a tool does, when it exists and what it returns.

This guide explains the API step by step for developers and curious site owners. It uses short, simple examples based on Chrome’s imperative API documentation, the WebMCP explainer and the draft spec, all checked in September 2026. Because WebMCP is still a draft, names and details can change. If you want the big picture first, read what is WebMCP.

Why use the WebMCP imperative API?

The declarative API is great for a single form. However, many useful actions don’t fit that shape. For example, adding a topping to a pizza, filtering a list of flights or reading the items in a basket all involve page logic rather than one form.

The WebMCP imperative API handles those cases instead. You write a small JavaScript function for each tool, and the browser offers it to supporting agents. In addition, it is currently the only approach ChatGPT’s site tools support. OpenAI’s developer notes say to “use JavaScript to register tools in the top-level page,” and that declarative HTML tools aren’t supported yet.

Before you start: the WebMCP imperative API name

If you read older tutorials, you may see navigator.modelContext. That was the name in early previews, as VentureBeat reported in February 2026. However, Chrome’s current docs, updated September 21, 2026, uses document.modelContext. The explainer on GitHub uses the same name. So use document.modelContext for new code, and check for it before calling it:

if (document.modelContext) {
  // register tools here
}

That simple check also keeps your page working in browsers without WebMCP support.

The parts of a WebMCP tool

According to the draft spec and Chrome’s docs, a tool setup has these parts:

FieldRequired?What it does
nameYesA unique ID, such as add-todo
titleNoA human-readable label
descriptionYesPlain-language explanation of what the tool does
inputSchemaNoA JSON Schema listing the inputs the tool needs
annotationsNoHints such as read-only or consequential
executeYesThe function that does the work and returns a result

The spec allows names of 1 to 128 characters, using letters, numbers, hyphens, underscores and dots. That said, Chrome’s security guidance suggests keeping names under 30 characters.

Step 1: Register a tool with the imperative API

Here is a short example, adapted from the WebMCP explainer. It lets an agent add an item to a to-do list:

await document.modelContext.registerTool({
  name: "add-todo",
  description: "Add a new item to the user's todo list",
  inputSchema: {
    type: "object",
    properties: {
      text: { type: "string", description: "The todo item text" }
    },
    required: ["text"]
  },
  async execute({ text }) {
    await addTodoItem(text);
    return `Added todo item: "${text}"`;
  }
});

Notice that execute calls your existing function, addTodoItem. That is the point of the WebMCP imperative API. You reuse the code your page already has, and the change appears on screen as normal.

Step 2: Write a description agents understand

The description is what the AI reads to decide whether to use your tool. So, above all, it deserves care. Chrome’s best practices offer clear advice:

  • Use precise verbs. create-event is better than start-event-creation-process.
  • Be positive. “This tool can create a calendar event” works better than “Don’t use this tool for weather.”
  • Accept raw input. Let the tool handle dates and conversions, rather than asking the AI to do maths.
  • Use words, not codes. Accept “Express” rather than a shipping ID such as 1.

Chrome’s security guidance also suggests limits: descriptions under 500 characters, parameter descriptions under 150 characters, and outputs under about 1,500 characters.

Step 3: Add WebMCP imperative API annotations

Next, annotations are optional hints about what a tool does. The draft spec and Chrome’s docs list four:

AnnotationUse it when
readOnlyHintThe tool only reads data and changes nothing
consequentialHintThe tool has real-world effects, such as a booking or payment
untrustedContentHintThe output includes user-generated or outside content
debuggingThe tool is meant for developers (Chrome 156 and later)

Chrome says consequentialHint lets “the agent or browser” request user confirmation before running the tool. Similarly, untrustedContentHint warns the agent that the output needs extra caution, which helps against prompt injection. For example:

annotations: { readOnlyHint: true }

ChatGPT’s developer notes say it honours readOnlyHint. Its site tools panel even groups tools into read and write, such as “3 read, 7 write tools.”

Step 4: Remove tools when they no longer apply

Also, tools should match what the page can do right now. For example, a “checkout” tool makes little sense on an empty basket. The WebMCP imperative API handles this with an AbortController:

const controller = new AbortController();
await document.modelContext.registerTool(tool, { signal: controller.signal });
// later, when the tool no longer applies:
controller.abort();

Chrome notes that from Chrome 153, aborting unregisters the tool without breaking a call that is already running. Also, the explainer describes a toolchange event that tells agents when tools are added, removed or updated.

Step 5: Limit who can see your tools

By default, however, tools belong to your page. The explainer and Chrome’s docs describe an exposedTo option, which shares a tool only with specific trusted origins. Chrome’s advice is direct: “Only expose your tools to origins that you trust.”

In addition, Chrome’s rules apply at page level. WebMCP only works in origin-isolated documents. A “tools” permissions policy controls it, and cross-origin iframes need allow="tools". Note that ChatGPT’s site tools don’t discover tools inside iframes at all.

Step 6: Handle errors gracefully

Agents make mistakes. Similarly, networks fail. Chrome’s guidance says tools should “fail gracefully and enable recovery.” In practice, that means returning a clear message instead of throwing a vague error.

For example, if a date is missing, return “Please provide a check-in date in YYYY-MM-DD format.” If a rate limit is hit, say so and suggest the person finish the task by hand. Chrome also recommends strict validation in code but loose validation in the schema, so the tool can return a helpful message rather than a hard failure.

A worked example: a small restaurant

To make this concrete, imagine a small restaurant website with an online booking page. The page already has code that checks free tables and saves a booking. With the WebMCP imperative API, the owner could offer two tools.

The first tool, check-availability, would take a date, a time and a party size. It would only read data, so it gets readOnlyHint. As a result, an agent can call it freely to find a free slot.

The second tool, book-table, would take the same details plus a name. However, it creates a real booking, so it gets consequentialHint. That way, the agent or browser can ask the diner to confirm before anything is saved.

In practice, a diner might say, “Find me a table for four on Friday evening.” The agent checks availability, suggests 7.30pm, and then asks the diner to confirm the booking. Meanwhile, the page shows the booking form updating on screen, so the diner can see what is happening. Chrome’s Le Petit Bistro demo shows a similar idea using the declarative approach.

Step 7: Test the tool

Finally, once your tool is registered, test it in three ways:

  1. By hand. Enable chrome://flags/#enable-webmcp-testing and install Google’s Model Context Tool Inspector extension. You can then see your tools and run them manually.
  2. In code. Chrome’s evaluation guide suggests calling document.modelContext.executeTool(...) directly to test a single tool.
  3. With an agent. The inspector can run tools with Gemini. Also, test in ChatGPT’s desktop browser if your audience uses it.

Chrome’s Pizza Maker demo is a good reference for the WebMCP imperative API. Our WebMCP best practices guide covers testing and evaluation in more depth.

WebMCP imperative API or declarative API?

QuestionImperative APIDeclarative API
Needs JavaScript?YesNo, for the basics
Best forComplex actions, app-like pagesSimple forms
ChatGPT site tools supportYesNot yet
Mozilla’s preferencePreferredLess favoured
Control over resultsFullLimited

For most real sites, the WebMCP imperative API is the safer bet today. However, the WebMCP declarative API is still worth adding to simple forms, since browsers without support simply ignore the attributes.

Key takeaways

  • The WebMCP imperative API registers tools with document.modelContext.registerTool(); older articles may show navigator.modelContext.
  • Each tool needs a name, a description and an execute function; an input schema and annotations are optional but helpful.
  • Annotations such as readOnlyHint and consequentialHint help agents and browsers decide when to ask the person first.
  • Use an AbortController to remove tools that no longer apply, and exposedTo to limit which origins can see them.
  • It is the approach ChatGPT’s site tools support, but the whole standard remains experimental as of September 2026.

WebMCP imperative API: FAQs

Is it navigator.modelContext or document.modelContext?

Current Chrome documentation, updated September 2026, and the WebMCP explainer use document.modelContext. Early 2026 previews used navigator.modelContext, so older tutorials may be out of date.

What should a WebMCP tool return?

Chrome’s docs shows tools returning text. Keep results short and clear; Chrome suggests keeping outputs under about 1,500 characters.

How do I make an agent ask before running my tool?

Mark the tool with consequentialHint. Chrome says this lets the agent or browser request user confirmation before execution.

Does ChatGPT support the WebMCP imperative API?

Yes. ChatGPT’s site tools, in its desktop app’s built-in browser, use JavaScript-registered tools in the top-level page.

Sources