AI agents can write distributed systems from scratch and refactor large codebases. But ask one to fill out a form in a web application, and it takes a screenshot, stares at it, and starts guessing which rectangle is an input field. What if a web page could simply tell the agent what it can do? That's the idea behind WebMCP.
What is WebMCP?
WebMCP is a proposed web standard that lets sites expose their actions as MCP tools, instead of forcing agents to reverse-engineer the interface on their own. The site declares its capabilities, the browser controls access, and the agent calls tools directly.
How WebMCP works
The standard adds a browser API navigator.modelContext with two methods: registerTool() to register a tool and unregisterTool() to remove it.
When an AI agent connects to the browser, it receives the list of registered tools, sees their descriptions and schemas, and can call them just like regular MCP tools.
The browser collects all registered tools and exposes them to the connected AI agent. The agent receives the tool names, descriptions, and input schemas. When the agent decides to perform an action, it calls the corresponding tool, and the page executes the function defined in execute.
In practice, the lifecycle looks like this:
- The page loads and registers tools.
- The browser exposes those tools to the AI agent.
- The agent chooses a tool and sends input parameters.
- The page executes the tool and returns the result.
Tools come in two types:
- Global — always available, regardless of the current page. For example, navigation between application sections.
- Contextual — tied to a specific page and appear when the user navigates to it. For example, searching patients on the Patient page.
Each tool is described by four fields:
| Field | Description |
|---|---|
| name | Unique identifier |
| description | Natural language description so the agent understands when to use the tool |
| inputSchema | JSON Schema of input parameters |
| execute | Function that runs when the tool is called |
The following example exposes a form field as a tool so an agent can fill it programmatically.
navigator.modelContext.registerTool({
name: "fill_name",
description: "Fill the name field on the form",
inputSchema: {
type: "object",
properties: {
value: { type: "string", description: "Name to fill in" }
},
required: ["value"]
},
execute: async (args) => {
document.querySelector("#name-input").value = args.value;
return {
content: [{ type: "text", text: `Name set to: ${args.value}` }]
};
}
});
Demo: Aidbox UI + AI Agent
How we integrated WebMCP into Aidbox UI
Polyfill
WebMCP is a young standard. Native support is only available in Chrome 146+ and only behind a flag. To avoid depending on that, we use @mcp-b/global — a polyfill that makes navigator.modelContext available in any browser.
Global entry point
When the application loads, it registers a list_pages tool that returns a map of all pages with descriptions of the tools available on each one. This is the starting point for the agent — it understands where it can navigate and what it can do there.
const pages = [
{
name: "resources_list",
description: "List of resources for a specific type",
path: "/resource/{resourceType}",
tools: [
"instances_get_search() - Get current FHIR search query string",
"instances_search(query) - Set FHIR search query and execute",
"instances_get_results() - Get displayed table data with pagination",
"instances_get_page() - Get current pagination state",
"instances_get_selected() - Get IDs of selected resources",
"instances_select(ids, selected?) - Select/deselect resources by ID",
"instances_delete_selected() - Delete selected resources",
"instances_export_selected() - Export selected as FHIR Bundle",
"instances_change_page(page) - Navigate to a specific page",
"instances_change_page_size(pageSize: 10|20|30|50|100) - Change page size",
"instances_navigate_to_resource(id) - Navigate to edit a resource",
"instances_open_create_page() - Navigate to create a new resource",
],
},
// ...
];
Page tools
Each page registers its own tools on mount and removes them on unmount. The agent always sees only the actions available right now.
navigator.modelContext.registerTool({
name: "instances_search",
description: "Set the FHIR search query and execute.",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "FHIR search query params",
},
},
required: ["query"],
},
execute: async (args) => {
actionsRef.current.instancesSearch(args.query);
return { content: [{ type: "text", text: `Search query set to: ${args.query}` }] };
},
});
Aidbox UI is open source. You can explore the WebMCP integration in the src/webmcp/ directory.
Key design decision: UI actions, not API wrappers
We could have made WebMCP tools wrappers around the Aidbox REST API. The agent sends a request, gets JSON back, works with it. But we took a different path.
Our tools perform actions in the UI. When the agent calls instances_search, the query appears in the search bar, the table updates, pagination recalculates. The user sees everything happening in real time.
This is a fundamental distinction. The agent and the user work in the same context. The user can watch the agent's actions, intervene at any moment, and continue working manually. It's not a black box — it's a shared workspace.
Try it yourself
You can try WebMCP in Aidbox UI right now.
- Create a free sandbox at aidbox.app
- Install chrome-devtools-mcp:
claude mcp add chrome-devtools -- npx @anthropic-ai/chrome-devtools-mcp@latest
- Open Aidbox UI (new version) in Chrome
- Ask Claude to open a page and use WebMCP
If you are experimenting with WebMCP or building AI-agent integrations around Aidbox, join the discussion in our community.






