Imperative API

Alexandra Klepper
Alexandra Klepper
François Beaufort
François Beaufort

Published: May 18, 2026

Explainer Web Extensions Chrome Status Intent
GitHub Developer trial Developer trial Developer trial Developer trial 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.