Learn WebMCP
A website that talks to agents. Not the other way around.
WebMCP is a proposed web standard that lets a page declare structured tools an AI agent can call. Instead of an agent scraping your DOM and guessing what buttons do, your site tells the agent exactly what it can do — and the agent calls it like a function.
Kurio is built on WebMCP. Every search, cart add, and checkout on this site is exposed as a tool. The floating pill at the bottom-right always tells you whether your browser can see them — and how to enable it if not.
Connect your agent
What you need, and the three steps to shop Kurio hands-free.
Requirements
- ChatGPT's in-app browser — WebMCP works there today, no setup needed.
- Or Chrome 149+ with chrome://flags/#enable-webmcp-testing enabled (the WebMCP origin trial).
- Nothing to install on this site: tools are auto-discovered by the agent.
The flag ships behind Chrome's WebMCP origin trial, so it is off by default: chrome://flags/#enable-webmcp-testing → Enabled → relaunch. Nothing else to install, and Kurio never asks you to sign in.
- 1
Use a browser that speaks WebMCP
Open Kurio in ChatGPT's in-app browser, or in Chrome 149 or newer with chrome://flags/#enable-webmcp-testing set to Enabled and the browser restarted.
- 2
Open Kurio and check the pill
Visit https://webmcp-kurio.netlify.app and look at the floating WebMCP pill in the bottom-right corner. When it reads “tools live”, this page has registered its tools and your browser can see them.
- 3
Ask your agent to shop
Tools are auto-discovered — no extension or pasting required. Just ask: “find me a gift under $40 on this page and check out.” Paste the shopping prompt below if your agent needs a nudge.
Checking whether this browser exposes document.modelContext…
How WebMCP works
The 60-second version.
Without WebMCP
An agent loads your page, reads the DOM, infers which button is “Add to cart”, hopes it guessed right, simulates clicks, and prays the page state doesn't change mid-flight. It's brittle, slow, and a little spooky.
- 1. Scrape the HTML
- 2. Guess element purpose
- 3. Simulate clicks & typing
- 4. Hope nothing breaks
With WebMCP
Your page registers tools with named parameters and JSON Schemas. The agent discovers them, calls them with structured input, and gets a structured result back. The action still happens on your page — visibly — but with the reliability of an API.
- 1. Page declares a tool
- 2. Agent discovers & calls it
- 3. Tool runs on the page
- 4. Result returns to the agent
WebMCP is a progressive enhancement: agents that don't support it simply fall back to actuation. Read the full spec at developer.chrome.com/docs/ai/webmcp.
The agent's-eye view
What an agent sees when it visits Kurio.
An agent connected to this page can call document.modelContext.getTools() and gets back:
[
{
"name": "search_products",
"description": "Search the Kurio product catalog by keyword, category, or tag. Returns matching …",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "get_product",
"description": "Fetch full details for a single Kurio product by its numeric id or slug. Use thi…",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "list_categories",
"description": "List all product categories available in the Kurio store. Returns an array of ca…",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "add_to_cart",
"description": "Add a quantity of a product to the shopper's cart on the Kurio marketplace. The …",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "view_cart",
"description": "Return the current contents of the shopper's Kurio cart: line items, quantities,…",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "update_cart_quantity",
"description": "Set the quantity of a specific product already in the Kurio cart. Removes the li…",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "remove_from_cart",
"description": "Remove a product line entirely from the Kurio cart.…",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "clear_cart",
"description": "Empty the entire Kurio cart. Use when the shopper wants to start over.…",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "checkout",
"description": "Place a demo order on the Kurio marketplace using the current cart contents. Thi…",
"origin": "https://webmcp-kurio.netlify.app"
},
{
"name": "get_store_info",
"description": "Return a short description of the Kurio marketplace: what it sells, that it is W…",
"origin": "https://webmcp-kurio.netlify.app"
}
]Checking whether this browser exposes document.modelContext…
What Kurio exposes
Try the tools yourself. Each one is live on this page.
Tools (10)
search_products
Search the Kurio product catalog by keyword, category, or tag. Returns matching products with id, name, price (in cents), category, a one-line description, stock, and tags. Use this to help a shopper find items.
Input schema
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Free-text search across name, category, description, and tags. Pass an empty string to list everything."
},
"category": {
"type": "string",
"description": "Optional category filter (e.g. \"Home & Living\", \"Kitchen & Dining\", \"Office & Tech\", \"Apparel\", \"Toys & Games\")."
}
}
}Try it
// output will appear hereCalling add_to_cart here will actually add to the cart in the page header — it's the same tool an agent uses. Open the cart to see.
Two ways to expose a tool
Imperative (JavaScript) or Declarative (HTML).
Imperative API
Register a tool from JavaScript with a name, description, JSON Schema, and an execute function. Best for app logic, state, and anything not already a form.
// Register a WebMCP tool that an AI agent can call.
// Tools run visibly on your page, so users keep trust and brand stays intact.
await document.modelContext.registerTool({
name: 'add_to_cart',
description: 'Add a quantity of a product to the shopper\'s cart.',
inputSchema: {
type: 'object',
properties: {
productId: { type: 'number', description: 'The product id to add.' },
quantity: { type: 'number', description: 'How many to add. Defaults to 1.', minimum: 1 },
},
required: ['productId'],
},
execute: async ({ productId, quantity = 1 }) => {
addToCart(productId, quantity); // your existing cart code
return `Added ${quantity} × product ${productId}`;
},
annotations: { readOnlyHint: false },
});Declarative API
Add toolname and tooldescription to an HTML form. The browser builds the schema from your inputs. Kurio's checkout form uses this — see it live.
<!-- The Declarative API turns a normal HTML form into a WebMCP tool
just by adding two attributes. The browser builds the JSON schema. -->
<form toolname="checkout"
tooldescription="Place a simulated order using the current cart.">
<label for="name">Full name</label>
<input name="customerName" type="text" required
toolparamdescription="The shopper's full name.">
<label for="email">Email</label>
<input name="customerEmail" type="email" required>
<label for="addr">Shipping address</label>
<input name="shippingAddress" type="text" required>
<button type="submit">Place order</button>
</form>
<script>
// e.agentInvoked is true when an agent triggered the form.
form.addEventListener('submit', (e) => {
if (e.agentInvoked) e.respondWith(placeOrderAndConfirm(e.target));
});
</script>Two prompts, two jobs
One tells an agent how to shop Kurio. One tells your coding agent how to add WebMCP to your own site.
For shoppers
Shop on Kurio with your agent
Paste this into a WebMCP-capable agent session — ChatGPT's in-app browser, or Chrome 149+ with the flag on — while this site is open. Most agents discover the tools on their own; this prompt just spells out the buying flow. Check the requirements first.
You are a WebMCP-aware shopping assistant. The page you are on (Kurio) exposes WebMCP tools you can call directly via document.modelContext.
To discover what tools exist on the current page, run:
const tools = await document.modelContext.getTools();
Then call a tool with executeTool, e.g. to add a product to the cart:
const result = await document.modelContext.executeTool(tool, JSON.stringify({ productId: 1, quantity: 2 }));
For this site the available tools include: search_products, get_product, list_categories, add_to_cart, view_cart, update_cart_quantity, remove_from_cart, clear_cart, checkout, get_store_info.
Suggested flow to complete a purchase for the user:
1. Call get_store_info to learn what the store sells.
2. Call search_products with the user's request to find candidates.
3. Show the user a few options and confirm which they want.
4. Call add_to_cart for each chosen product.
5. Call view_cart to confirm the cart with the user.
6. When the user is ready, ask for their full name, email, and shipping address.
7. Call checkout with those details. The purchase is simulated — no real payment is taken.
8. Report the order number back to the user.
Always confirm the cart and the shipping details with the user before calling checkout. Never invent shipping details.For builders
Add WebMCP to your own site
Give this one to a coding agent — Claude Code, Cursor, Copilot — inside your own repository. It describes the same implementation Kurio runs: document.modelContext.registerTool with typed JSON Schema inputs, readOnlyHint annotations, feature detection, and the declarative form path.
Add WebMCP support to this website so AI agents can drive it through structured tools instead of scraping the DOM. WebMCP is a proposed web standard; the browser exposes it as document.modelContext.
Requirements:
1. Feature-detect first. WebMCP is a progressive enhancement, so nothing may break when it is missing:
const mc = typeof document !== 'undefined' ? (document as any).modelContext : null;
if (!mc) return; // no WebMCP in this browser — the site keeps working normally
Register from a client-side effect that runs after mount, guarded so it only runs once.
2. Register one tool per meaningful user action with document.modelContext.registerTool({ name, description, inputSchema, execute, annotations }). Use snake_case names (search_products, add_to_cart, checkout). Write descriptions for a model that cannot see the page: say what the tool does and when to use it.
3. inputSchema must be real JSON Schema — no free-text params:
inputSchema: {
type: 'object',
properties: {
productId: { type: 'number', description: 'The product id to add.' },
quantity: { type: 'number', description: 'How many to add. Defaults to 1.', minimum: 1 },
},
required: ['productId'],
}
Add enum / minimum / maximum where the domain has limits, and describe every property.
4. execute receives the parsed argument object and must resolve to a string. Return JSON.stringify(result, null, 2) for structured data so the agent can parse it. Catch errors inside execute and return a readable error string instead of throwing.
5. Set annotations.readOnlyHint: true on tools that only read (search, get, list, view) and false on tools that mutate state or submit anything (add to cart, update, remove, checkout). Agents use this to decide what is safe to call without confirmation.
6. Call the existing application code inside execute — the same functions the UI buttons call. Do not duplicate business logic, and do not expose admin, auth, or destructive actions as tools.
7. Make the effect visible. The action should happen in the UI where the user can watch it, so the page stays trustworthy.
8. If the action is already an HTML form, prefer the Declarative API instead of JavaScript: put toolname and tooldescription on the <form>, toolparamdescription on each input, and in the submit handler check event.agentInvoked and reply with event.respondWith(promiseOfResultString). The browser derives the schema from the inputs.
9. Do server-side validation anyway. A tool call is untrusted input exactly like a form post.
10. Finish by listing the tools you registered with their schemas, and tell me how to test: Chrome 149+ with chrome://flags/#enable-webmcp-testing enabled, or ChatGPT's in-app browser.
Reference: https://developer.chrome.com/docs/ai/webmcpWhat the builder prompt gets you
1. Pick the actions
Identify what an agent should do on your site: search, add to cart, submit a form, navigate. One tool per action.
2. Write the schemas
Typed JSON Schema with a description on every property. The agent reads these to decide when and how to call your tool.
3. Wire up execute()
Your execute function calls your existing code and returns a string. That string goes back to the agent as the tool result.
4. Test with an agent
Use the Model Context Tool Inspector extension to call your tools and inspect the output.
Ship it on Netlify
Agent runners, server functions, a managed database.
For builders
Deploy agent-shoppable sites in minutes.
Netlify hosts the server functions behind Kurio's checkout, the managed Postgres database that stores orders, and the agent runners that can drive a WebMCP-enabled page end-to-end. The same stack this demo runs on.