Published: May 18, 2026
| Explainer | Web | Extensions | Chrome Status | Intent |
|---|---|---|---|---|
| GitHub | View | Intent to Experiment |
You can use the WebMCP Imperative API to define many types of tools with standard JavaScript. Your tools can execute different functions, such as form input, site navigation, and state management.
Before using this API, read about example use cases.
Provide model context
Use the modelContext interface to register tools. Tool registration requires a name, description, and input schema with relevant properties,
Use registertool to add a single tool to the model context.
WebMCPza Maker
navigator.modelContext.registerTool({
name: 'toggle_layer',
description: 'Control pizza layers (sauce, cheese). Use "add", "remove", or "toggle".',
inputSchema: {
type: 'object',
properties: {
layer: { type: 'string', enum: ['sauce-layer', 'cheese-layer'] },
action: { type: 'string', enum: ['add', 'remove', 'toggle'] },
},
required: ['layer'],
},
execute: ({ layer, action }) => {
toggleLayer(layer, action);
return `Performed ${action || 'toggle'} on layer: ${layer}`;
},
});
Get order status
navigator.modelContext.registerTool({
name: 'get_order_status',
description: 'Search orders in a given timeframe. Returns order number, shipping status and location',
inputSchema: {
"type": "object",
"properties": {
"timeframe": { "type": "string", "oneOf": [
{ "type": "string", "const": "today", "title": "Today" },
{ "type": "string", "const": "yesterday", "title": "Yesterday" },
{ "type": "string", "const": "last_7_days", "title": "Last 7 Days" },
{ "type": "string", "const": "last_30_days", "title": "Last 30 Days" },
{ "type": "string", "const": "last_6_months", "title": "Last 6 Months" }],
"enum": [ "today", "yesterday", "last_7_days", "last_30_days", "last_6_months" ],
"description": "Timeframe for the order lookup." }
},
"required": [ "timeframe" ]
},
execute: ({ timeframe }) => {
// Add your API or database logic here to fetch and return the order data as a string.
},
});
You can remove a tool with AbortSignal, when passed as an optional parameter.
const addTodoTool = {
name: "addTodo",
description: "Add a new item to the to-do list",
inputSchema: {
type: "object",
properties: { text: { type: "string" } },
},
execute: ({ text }) => {
// You should handle the persistence logic here (omitted for demo)
return `Added to-do: ${text}`;
},
annotations: {
readOnlyHint: false,
untrustedContentHint: true
},
};
const controller = new AbortController();
navigator.modelContext.registerTool(addTodoTool, { signal: controller.signal });
// Unregister the tool later...
controller.abort();
Discover tools
To see available tools, use navigator.modelContext.getTools(). This
asynchronous method returns a list of tools that the calling document is
authorized to access based on its origin.
const [tool] = await navigator.modelContext.getTools();
console.log(tool);
// {
// annotations: { readOnlyHint: false, untrustedContentHint: true },
// description: "Add a new item to the to-do list",
// inputSchema: '{"type":"object","properties":{"text":{"type":"string"}}}',
// name: "addTodo",
// origin: "https://example.com",
// window: Window {window: Window, self: Window, ...},
// }
Execute tool
To manually execute a tool discovered in getTools(), call
navigator.modelContext.executeTool() with input arguments as a valid JSON
string. This asynchronous method returns the result of the tool execution,
or null when a navigation is triggered.
const result = await navigator.modelContext.executeTool(tool, '{"text": "Buy milk"}');
console.log(result);
// 'Added to-do: Buy milk'
You can cancel a pending tool execution with AbortSignal, when passed as an
optional parameter.
const controller = new AbortController();
navigator.modelContext.executeTool(tool, '{"text": "Buy milk"}', {
signal: controller.signal,
});
// Cancel tool execution later...
controller.abort();
Events
Frames can listen for the toolchange event on navigator.modelContext to be
notified when the list of available tools has changed.
navigator.modelContext.addEventListener("toolchange", (event) => {
// Tools have changed.
});
Cross-origin iframes
WebMCP supports cross-origin iframes that use both permission policies and explicit origin gating.
Permissions policy
Tool registration is disabled by default in cross-origin iframes. A page must
delegate access using the tools
Permissions Policy:
<iframe src="https://example.com" allow="tools"></iframe>
Origin exposure
Tools are unavailable to cross-origin documents by default. You can use the
exposedTo array within registerTool to list specific origins allowed to view
and execute a tool. This array only supports origins with the HTTPS protocol.
navigator.modelContext.registerTool({
name: 'my_shared_tool',
description: 'Shared across origins',
// ...
}, {
exposedTo: ['https://trusted.com', 'https://partner.org']
});
Engage and share feedback
WebMCP is under active discussion and subject to change in the future. If you try this API and have feedback, we'd love to hear it.
- Read the WebMCP explainer, raise questions and participate in discussion.
- Read WebMCP best practices.
- Review the implementation for Chrome on Chrome Status.
- Join the early preview program for an early look at new APIs and access to our mailing list.
- If you have feedback on Chrome's implementation, file a Chromium bug.