CHROME | ||
WebMCP Early Preview | Authors | |
Contact | ||
Updated | Apr 24, 2026 | |
WebMCP is a proposed web standard that exposes structured tools for AI agents on existing websites. This would replace "screen-scraping" with robust, high-performance page interaction and knowledge retrieval. WebMCP provides JavaScript and annotates HTML form elements so that agentic browsers know exactly how to interact with page features to support a user's experience.
By exposing APIs to the browser agent, WebMCP significantly improves the performance and reliability of AI agent actuation.
The following are some examples of how WebMCP could be applied to your website:
WebMCP bridges the gap between web applications and AI agents by providing a contract for interaction. Rather than the agent guessing the purpose of a button or the structure of a form, the website can explicitly publish its interface. This contract defines:
Our goal for the WebMCP early preview is to understand the following topics:
We are seeking your feedback to shape our understanding.
WebMCP is available behind a flag in Chrome 146. Learn more about Chrome flags.
To use WebMCP, you need:
Install the Model Context Tool Inspector Extension to see how WebMCP works in the live demo. The extension lets you inspect registered functions, execute them manually or test them with an agent.
The extension acts as a monitoring interface for the navigator.modelContext API, with the experimental navigator.modelContextTesting API. It provides a list of all registered tools within the active tab.
One of the goals for this extension is to offer you a way to bypass the non-deterministic nature of an AI agent for initial testing.
The extension includes Gemini API support to simulate real-world agent interactions.
Note: This is separate from the Gemini in Chrome features.
Explore the WebMCP capabilities with our hosted travel demo:
https://googlechromelabs.github.io/webmcp-tools/demos/react-flightsearch/
What happened: The Model Context Tool Inspector Extension pulled the tools registered with registerTool or providedContext, with their name, description and arguments. This is useful to debug your implementation and identify if the correct functions are available at a given UI state.
{
"origin": "LON",
"destination": "NYC",
"tripType": "round-trip",
"outboundDate": "2026-06-10",
"inboundDate": "2026-06-17",
"passengers": 2
}
NOTE: The demo application only supports the LON => NYC flight segment with round-trips. Using different parameters triggers the function, but won’t show results in the page. |
What happened: The Model Context Tool Inspector Extension executed a tool by calling it directly, using the arguments provided. This is useful to test your function’s implementation, without relying on a large language model to translate natural language input into the function arguments.
Search flights from LON to NYC leaving next Monday and returning after a week for 2 passengers.
NOTE: The demo application only supports the LON => NYC flight segment with round-trips. Using different parameters triggers the function, but won’t show results in the page. |
What happened: The extension prompted Gemini 2.5 Flash with your input, alongside the function definitions using the Function Calling functionality. The model told the extension which function to call and parameters, and the extension called the function.
Examples of demos covering both imperative and declarative implementations are available:
You can also review and explore the demo source code on GitHub.
There are two APIs:
Use the Imperative API to define tools, using standard JavaScript.
Imperative tools can be registered and unregistered dynamically with registerTool. Use this method to add a single tool to the existing set without removing others. Unregistering the tool can be done by using the AbortSignal passed as an optional parameter.
Set untrustedContentHint to true if the tool processes data from external or unverified sources to indicate that the tool's output contains data that is untrusted, from the perspective of the author registering the tool.
const addTodoTool = {
name: "addTodo",
description: "Add a new item to the todo list",
inputSchema: {
type: "object",
properties: { text: { type: "string" } },
},
execute: ({ text }) => {
// You should handle the persistence logic here (omitted for demo)
return `Added todo: ${text}`;
},
annotations: { readOnlyHint: false, untrustedContentHint: true },
};
const controller = new AbortController();
navigator.modelContext.registerTool(addTodoTool, { signal: controller.signal });
// Unregister the tool later...
controller.abort();
Use the Declarative API to automatically transform standard HTML forms into WebMCP tools by adding specific annotations. These annotations define the tool's name and purpose through the toolname and tooldescription HTML attributes on the <form> element, while the form fields act as the parameters for the tool. The browser then translates these elements into a structured representation that an AI agent can interpret and use, similar to how imperative tools are handled.
When an AI agent calls a tool by its registered name through the toolname HTML form attribute, the browser automatically brings the associated form into focus and populates its fields. By default, the form remains visible to the user, who must manually click the <form>’s Submit button to proceed, unless the toolautosubmit HTML form attribute is set. The results of the tool invocation are either displayed in the current document, or if the submission triggers a navigation change, in the triggered document.
Form-associated elements support the toolparamdescription attribute, which provides an optional way to define a property description within the json-schema. In its absence, the browser uses the textContent of the associated <label> HTML element but skips descendants that are labelable or, if no label exists, the aria-description. However, if you need to attach a toolparamdescription to a group of related elements, such as a set of <input type="radio"> buttons, you must place the attribute on the nearest parent <fieldset> element so that it applies to the parameter group as a whole.
<form toolname="my_tool" tooldescription="A simple declarative tool" action="/submit">
<label for="text">text label</label>
<input type=text name=text>
<select name="select" required toolparamdescription="A nice description">
<option value="Option 1">This is option 1</option>
<option value="Option 2">This is option 2</option>
<option value="Option 3">This is option 3</option>
</select>
<button type=submit>Submit</button>
</form>
The HTML code above results in the following tool name, description and input schema computed internally by the browser for the declarative tool.
[
{
"name": "my_tool",
"description": "A simple declarative tool",
"inputSchema": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "text label"
},
"select": {
"type": "string",
"anyOf": [
{
"const": "Option 1",
"title": "This is option 1"
},
{
"const": "Option 2",
"title": "This is option 2"
},
{
"const": "Option 3",
"title": "This is option 3"
}
],
"enum": [
"Option 1",
"Option 2",
"Option 3"
],
"description": "A nice description"
}
},
"required": [
"select"
]
}
}
]
The SubmitEvent interface introduces a new agentInvoked boolean attribute. This attribute is set to true whenever a form is triggered by an AI agent, to adapt your web app's behavior specifically for agent-based interactions.
Additionally, the SubmitEvent now also includes the respondWith(Promise<any>) method which lets you pass a promise to the browser that you resolve with the form’s results data. The resulting value is then serialized and returned to the model as the tool's output. To use it, you must first call preventDefault() to stop the browser's standard form submission.
<form toolautosubmit
toolname="search_tool"
tooldescription="Search the web" action="/search">
<input type=text name=query>
</form>
<script>
document.querySelector("form").addEventListener("submit", (e) => {
e.preventDefault();
if (!myFormIsValid()) {
if (e.agentInvoked) { e.respondWith(myFormValidationErrors) };
return;
}
if (e.agentInvoked) { e.respondWith("Search is done!"); }
});
</script>
The browser signals that an AI agent executed a tool via the "toolactivated" event, which fires on the window once form fields are pre-filled. Conversely, if a user cancels the agentic operation or the reset() method is invoked on the HTML form, a "toolcancel" event is triggered. Both of these events are non-cancelable and provide a toolName attribute for identification.
window.addEventListener('toolactivated', ({ toolName }) => {
console.log(`the tool "${toolName}" execution was activated.`);
// TODO: Update UI or validate form if needed.
});
window.addEventListener('toolcancel', ({ toolName }) => {
console.log(`the tool "${toolName}" execution was cancelled.`);
// TODO: Let the user know. Update UI.
});
When an AI agent successfully invokes a tool, focuses the associated form, and auto-populates its fields, the browser triggers specific CSS pseudo-classes for visual feedback:
Both are deactivated when the form submits, the AI agent cancels the action, or the user resets the form.
The following placeholder styles are applied by default in Chrome.
form:tool-form-active {
outline: light-dark(blue, cyan) dashed 1px;
outline-offset: -1px;
}
input:tool-submit-active {
outline: light-dark(red, pink) dashed 1px;
outline-offset: -1px;
}
A well-structured tool declaration should be self-explanatory, so developers understand how it works and can use it immediately, without having to look at the outputs and retry. Here are some best practices that make this possible:
Goal: Ensure clarity of scope and intended use.
Goal: Minimize cognitive computing for the model.
Goal: Turn failures into corrections.
Goal: Create non-overlapping, composable tools.
The Model Context Protocol (MCP) enables AI Agents to connect to applications with a server-side protocol. Developers who want to give agents access to their tools need to deploy them on their own server.
WebMCP is a protocol inspired by MCP that allows developers to provide tools to in-browser AI agents. WebMCP helps developers implement client-side functions or use a declarative API in their existing web application, so agents are better equipped to interact with the application.
WebMCP is a proposed web standard. Our goal is to build APIs that any browser with agentic capabilities can implement and benefit from. The early preview is only in Chrome.
You can follow along this process on GitHub.
DATE | CHANGES |
Apr 24, 2026 | - Added readOnlyHint and untrustedContentHint annotations (source) |
Mar 27, 2026 | - Added registerTool() method signal option and removed unregisterTool() (source) - Updated input groups (radio, etc) toolparamdescription using nearest <fieldset> (source) - Switched from oneOf to anyOf in the computed input schema example. (source) |
Mar 12, 2026 | - Removed toolparamtitle attribute - Added demo |
Mar 6, 2026 | - Removed provideContext and clearContext methods |
Feb 10, 2026 | - Declarative API tweaks |
Feb 9, 2026 | - Initial version |