WebMCP
Expose browser-side actions as structured tools that compatible agents can discover and call.
Overview#
WebMCP lets your website tell compatible browser agents what they can do. Instead of guessing which buttons to click, an agent discovers a named tool with a description, a typed input schema, and a JavaScript handler.
CopilotKit can publish an existing frontend tool to document.modelContext. The same handler then works for your CopilotKit agent and for WebMCP-aware browser agents.
WebMCP is experimental
WebMCP is a draft Community Group report, not a W3C Standard. Chrome offers
it through an origin trial beginning in Chrome 149, or through the
chrome://flags/#enable-webmcp-testing flag for local development. CopilotKit
safely does nothing when document.modelContext is unavailable. Check the
current Chrome setup instructions
before testing.
Setup with a coding agent#
Use this pre-built prompt to add WebMCP to your project. Your coding agent will adapt the implementation to your app and verify that a compatible browser can discover and call the tool.
Do I need an agent?#
You do not need a CopilotKit backend agent to handle a WebMCP call. A compatible browser agent calls the frontend tool handler directly on the page; in that path, the handler context has no agent.
Choose the smallest path that fits your app:
| What your app has today | What to do |
|---|---|
| A CopilotKit frontend tool for the action | Add webmcp: true, or add annotations with webmcp: { annotations: ... }. |
| CopilotKit, but no frontend tool for the action | Wrap the smallest suitable browser-side action in a frontend tool, then opt it into WebMCP. |
| A backend agent | Keep it. The tool can remain available to that agent, but WebMCP calls do not pass through it. |
| No backend agent | Use CopilotKitCore directly in browser code, or add the appropriate frontend integration. Do not create an agent only for WebMCP. |
React Native does not expose document.modelContext, so WebMCP registration is a no-op there. CopilotKit currently supports this WebMCP option in its browser integrations for React, Vue, Angular, and direct core usage.
How CopilotKit connects WebMCP#
- Your app registers a CopilotKit frontend tool with
webmcpenabled. - CopilotKit mirrors the tool's name, description, JSON Schema, annotations, and handler onto
document.modelContext. - A compatible browser agent discovers the tool and calls the same JavaScript handler while the page is open.
- CopilotKit unregisters the WebMCP tool when the frontend tool is removed or becomes unavailable.
The WebMCP call stays in the browser unless your handler deliberately calls an API. CopilotKit does not route that call through a Runtime or backend agent.
Add WebMCP manually#
Existing React frontend tool#
Add webmcp to the tool you already register. This code must run inside your existing CopilotKitProvider.
"use client";
import { useFrontendTool } from "@copilotkit/react-core/v2";
import { z } from "zod";
export function OrderSearch() {
useFrontendTool({
name: "searchOrders",
description: "Search the signed-in user's orders by status",
parameters: z.object({
status: z.enum(["open", "shipped", "delivered"]),
}),
handler: async ({ status }) => {
const orders = await searchOrders(status);
return JSON.stringify(orders);
},
webmcp: {
annotations: {
readOnlyHint: true,
},
},
});
return null;
}Use the equivalent option with useFrontendTool for Vue or registerFrontendTool for Angular. The React API is documented in useFrontendTool.
WebMCP only, with no agent#
For browser code that does not use a framework provider, register the frontend tool directly with the core. Keep the core instance alive for as long as the tool should remain available.
import { CopilotKitCore } from "@copilotkit/core";
import { z } from "zod";
export const copilotkit = new CopilotKitCore({
tools: [
{
name: "searchOrders",
description: "Search the signed-in user's orders by status",
parameters: z.object({
status: z.enum(["open", "shipped", "delivered"]),
}),
handler: async ({ status }) => {
const orders = await searchOrders(status);
return JSON.stringify(orders);
},
webmcp: {
annotations: {
readOnlyHint: true,
},
},
},
],
});This path does not configure a Runtime or an agent. It only registers browser-side tools through CopilotKit's core lifecycle.
Design tools agents can use reliably#
- Give every WebMCP tool a non-empty, specific
description. CopilotKit skips WebMCP registration when it is missing. - Keep each tool focused on one action and give every parameter a useful description.
- Use
readOnlyHint: trueonly when the handler cannot change state. - Use
untrustedContentHint: truewhen results may contain user-generated or external content. - Return concise, structured results that tell the caller what happened.
- Set the frontend tool to unavailable when the action cannot currently run; CopilotKit removes it from WebMCP until it is available again.
Annotations are hints for browser agents, not security controls. Enforce authentication, authorization, validation, rate limits, and required user confirmation inside the handler or the API it calls. See Chrome's WebMCP tool security guidance.
Agent scope does not scope WebMCP
agentId limits which CopilotKit agent receives a frontend tool. WebMCP tools
are page-level, so agentId does not restrict browser-agent access. If
multiple opted-in tools share a name across agent IDs, CopilotKit exposes the
first one and logs a warning.
Test the complete path#
- Open Chrome 149 or newer and enable the WebMCP origin trial or local testing flag.
- Load the app in an origin-isolated document. The
toolspermissions policy defaults toself; cross-origin iframes also needallow="tools". - Confirm that
document.modelContextexists. - Use Chrome's Model Context Tool Inspector to confirm the tool name and schema, call it with representative inputs, and inspect its result.
- Ask the inspector's agent to complete the user task in natural language. Verify that it chooses the right tool and that authentication and confirmation boundaries still hold.
If the tool does not appear, check the browser setup first, then verify that the tool has a description, webmcp is enabled, and the frontend tool is currently available.