# What Is WebMCP? How My Website Gives AI Agents Tools

> Source: <https://tej.as/blog/what-is-webmcp/>
> Published: 2026-10-02 07:50:41+00:00

# What Is WebMCP? How My Website Gives AI Agents Tools

So, **WebMCP is a proposed web standard that lets a web page hand an AI agent using your browser a set of tools, each with a name, a description, a [JSON Schema](https://json-schema.org/) for its input and a function to run, so the agent calls the function instead of screenshotting and clicking its way around the page.** Since 1 October 2026 every page on this site does it, with 4 tools, and this post is about what they are, how I built them and what WebMCP is actually good for.

This morning I gave an AI agent that knew nothing about me except those 4 tools one question: “Where is Tejas speaking this month, and what would a workshop for my team cost?” It made 2 tool calls, `get-speaking-schedule` for the dates of October and `get-booking-info` for workshops, and came back with all 4 of my October conferences (ticket links included!) and every workshop price, straight from the data my pages show. No scraping, no guessing, no squinting at a screenshot of a pricing table. Wild.

[Sarah Drasner](https://sarah.dev), who leads AI and the web ecosystem for [Chrome](https://www.google.com/chrome/) at [Google](https://about.google/), put the before and after better than I can in [a post on 16 September](https://x.com/sarah_edo/status/2100224152841912686):

Agent: *screenshots the page* Agent: *scrolls* Agent: *screenshots again* Agent: *clicks the wrong button* Agent: *screenshots again* Page with WebMCP: hi, here are the 4 things you can do here, with descriptions

My website is literally that page now lol. 4 things, with descriptions.

**TL;DR**

- WebMCP lets a page register tools that an AI agent using the browser can call: a name, a description, an input schema and a function.
- It’s a draft web standard, and Chrome runs it as an origin trial from Chrome 149.
- This site registers 4 read-only tools: search everything I’ve published, list my talks, read my speaking schedule, and get my fees and how to book me.
- Each tool’s contract lives in one file: the browser registers it, the server checks every call against the same schema, and the two can’t drift apart.
- A tool should hand a mistake back as a sentence and never throw, because a rejected call reaches the model as a bare `UnknownError` .
- It’s good for anything people already do on your page that an agent could do with one function call: search, filter, book, check out.

## What is WebMCP?

**WebMCP is a proposed web standard that lets a web page offer an AI agent using the browser a set of tools to call.** The spec is [a draft report](https://webmachinelearning.github.io/webmcp/) from the [Web Machine Learning Community Group](https://www.w3.org/community/webmachinelearning/) at the [World Wide Web Consortium (W3C)](https://www.w3.org/), and its abstract is one sentence: “The WebMCP API enables web applications to provide JavaScript-based tools to AI agents.” The agent is whatever the browser hands those tools to, and the [explainer from Chrome’s team](https://googlechromelabs.github.io/webmcp-tools/demos/explainer/) puts it this way: “A WebMCP-aware extension (or, eventually, the browser itself) collects registered tools and presents them to the user’s agent.” So it can be an extension like [the side panel Sarah built](https://x.com/sarah_edo/status/2102025642862600634), the browser’s own assistant one day, or a program driving the browser from outside, like the demo at the top of this post, which reads the tools through [Chrome DevTools](https://developer.chrome.com/docs/devtools). What it doesn’t have to do anymore is steer the page by clicking around: it calls the functions.

WebMCP is named after the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/), which I’ve explained on stage a bunch of times, and the way I put it [at How to Web](https://tej.as/talks/how-to-web-2025) is still how I think about it: it’s “just passing functions over the network… There’s a lot of people who will use big words to confuse and gatekeep you. Don’t listen to them. It’s all functions.”

WebMCP is the same idea, with one change that makes it a whole different thing: the functions live in the web page you already have open. The 3 ways an agent can use a website, side by side:

|  | WebMCP | An MCP server | Screenshots and clicks | 
|---|---|---|---|
| Where the tools are | In the web page itself | On a server somebody runs, which you connect to your AI app | Nowhere: the agent reads pixels and the page’s markup and guesses | 
| What the site has to build | A few functions in the site it already has | A second product next to the site | Nothing | 
| What breaks it | A tool whose contract changes | The server going down | A redesign, a popup, a slow load | 
| On tej.as | 4 tools since 1 October | Never built | How agents saw my site until 30 September | 

## Which browsers support WebMCP?

**Chrome, as an [origin trial](https://developer.chrome.com/docs/web-platform/origin-trials) from Chrome 149** ([Chrome’s WebMCP docs](https://developer.chrome.com/docs/ai/webmcp)). An origin trial is Chrome letting a site switch a feature on early for its own visitors, with a token that only works on that site’s origin (think, its domain). My token goes in a `<meta http-equiv="origin-trial">` tag on every page and expires on 30 March 2027, so anybody visiting in Chrome gets the tools without flipping a flag. On `localhost` the token doesn’t match, so while I’m building I turn it on with `chrome://flags/#enable-webmcp-testing` instead.

It’s a proposed standard, and it moves. When Chrome 149 shipped it, the API lived on `navigator.modelContext`, and later releases moved it to `document.modelContext`, which is where the spec has it now, so my code looks in both.

## The 4 tools on tej.as

Every tool answers from the same module the pages read, so an agent quotes the sentence a visitor sees and never a copy of it that’s gone stale.

| Tool | What an agent asks it | Where the answer comes from | 
|---|---|---|
| `search-content` | What has Tejas said about [React Server Components](https://react.dev/reference/rsc/server-components) ? | The search index behind the Ask boxes: my talk transcripts, the [ConTejas Code](https://tej.as/podcast) podcast,[Fluent React](https://tej.as/react) and this blog, with video links that open at the second the passage starts | 
| `list-talks` | Which talks has he given on AI? | My talk list, with the full transcript on this site where one exists | 
| `get-speaking-schedule` | Where is he speaking next? | The calendar behind [/calendar](https://tej.as/calendar) | 
| `get-booking-info` | What does a keynote or a workshop cost? | The fees and terms on [/speaking](https://tej.as/speaking) and[/workshops](https://tej.as/workshops) | 

All 4 only read. Nothing here sends, books or submits anything on anyone’s behalf, and the spec has a hint for the day something does: `consequentialHint`, which Sarah [announced in September](https://x.com/sarah_edo/status/2097318090979610803) and which [Chrome’s guidance](https://developer.chrome.com/docs/ai/webmcp/secure-tools) says to set for high stakes actions like “booking travel or transferring money”, so the agent asks the person first.

## How I built it

The whole thing is about 780 lines of TypeScript in 5 files, plus a component and an API route, and none of it holds data of its own: every answer comes from a module the pages already use.

### 1. One file holds every tool’s contract

A tool is a name, a title for people, a description for the model, a JSON Schema for the input and some hints. Here’s `search-content`, trimmed:

```
// src/util/webmcp/tools.ts (trimmed)
{
  name: "search-content",
  title: "Search talks, podcast, book and blog",
  description:
    "Search everything Tejas Kumar has published: his conference talk transcripts, the ConTejas Code podcast, his O'Reilly book Fluent React and his blog. Returns the closest passages, each with a link...",
  inputSchema: {
    type: "object",
    properties: {
      query: { type: "string", minLength: 1, maxLength: 300, description: 'What to look for, in plain words, such as "agent harnesses" or "React Server Components".' },
      source: { type: "string", enum: ["all", "talks", "podcast", "book", "blog"], default: "all", description: "..." },
      limit: { type: "integer", minimum: 1, maximum: 8, default: 4, description: "..." },
    },
    required: ["query"],
  },
  annotations: { readOnlyHint: true },
}
```

Notice the description says “Tejas Kumar” and “his”, not “I” and “my”. Everything else on this site is first person, but a model reads a tool description with no page around it, and a “my talks” out of context has nobody attached to the “my”.

### 2. The browser registers them, and only if it can

``` php
<!-- src/components/WebMCP.astro (trimmed) -->
<script>
  const context = document.modelContext ?? navigator.modelContext;
  if (context && typeof context.registerTool === "function") {
    import("../util/webmcp/register").then(({ register }) => register(context));
  }
</script>
```

A browser without WebMCP pays for one property lookup and nothing else, because the code that registers the tools only downloads after the feature test passes. Each tool’s `execute` then sends its input to `/api/webmcp/<tool>` on my server, because the search index and the calendar live there, and shipping them to every page would make every page heavier for every visitor, agent or not.

### 3. The server checks every call against the same schema

The API route imports the very same `tools.ts` and validates the input against the schema the agent was shown before it runs anything, so what the agent is told and what the server enforces can’t drift apart.

A model is a sloppy caller though, so the validator forgives the mistakes that only have one obvious meaning and refuses the rest:

- an integer sent as a string (`"5"` ) is read as the integer,
- an enum value in the wrong case (`"React"` ) is read as its listed form,
- strings are trimmed, and an empty string counts as not sent,
- properties the schema doesn’t name are dropped instead of refused.

### 4. Hand back a mistake, never throw it

This one’s the most useful thing in this post if you’re building your own tools. If a tool’s `execute` rejects, the model gets a bare `UnknownError` and no idea what went wrong. So every tool on this site returns its mistakes as a plain object with a sentence in it:

``` js
// src/util/webmcp/register.ts (trimmed)
const body = await response.json().catch(() => null);
if (body && body.ok === true) return body.result;
/* A mistake goes back to the model as a sentence it can correct, not as a
   rejected promise, which the browser would flatten into UnknownError. */
return { error: body?.error || `tej.as answered ${response.status}. Try again in a moment.` };
```

A model can fix `"source" must be one of all, talks, podcast, book, blog, and got "videos".` on its very next call, and it can’t do anything with `UnknownError`.

### 5. Stay inside Chrome’s budgets

[Chrome’s guidance](https://developer.chrome.com/docs/ai/webmcp/secure-tools) gives every tool a budget: 30 characters for a name, 500 for a description, 150 for each parameter’s description and about 1,500 for what a tool returns. A test in this repo fails if a name or a description goes over, and it runs every tool against the real data to measure the output. That’s why a search result is a passage of about 220 characters around the sentence that shares the most words with your query, and not the first 220 characters of a chunk, which on a podcast segment is usually the tail of the previous answer.

### 6. Count whether anybody uses it

Every page reports a `WebMCP Ready` event when it registers the tools, and every call reports a `WebMCP Tool` event with the tool’s name, whether it worked and how long it took. That’s how I’ll know whether any agent in the wild actually calls these, or whether I built a really nice door nobody knocks on.

## What is WebMCP good for?

**WebMCP is good for anything people already do on your page that an agent could do with one function call instead of a dozen clicks.** Sarah showed it on [her own app](https://x.com/sarah_edo/status/2099489118182863280): “I can batch process, change themes and dark mode, check on higher level goals that I’m keeping track of. All of this functionality exists already!”

- **Answering from your own data.** My fees, my calendar and my talks were already on my pages. The tools just let an agent read them without guessing, which is the whole demo at the top of this post.
- **Checking out.** On 28 September[Shopify opened checkout to agents in the browser](https://techcrunch.com/2026/09/28/shopify-opens-checkout-to-browser-based-ai-agents/) with WebMCP tools called`get_checkout` ,`update_checkout` and`complete_checkout` , which places the order after the buyer authorizes it.
- **Your app’s features, from a side panel.** Sarah built[a Chrome extension](https://x.com/sarah_edo/status/2102025642862600634) that drives any site’s WebMCP tools with[Jev](https://www.typesafe.ai/) from[TypeSafe](https://www.typesafe.ai/) : as you type, it picks the page’s tool, fills in the arguments and tells you how sure it is. I use Jev on this site to decide whether the Ask boxes can answer a question at all, so seeing it pick tools was a fun little crossover.

## How to try it on tej.as

In a recent Chrome, open any page here, then open the console in DevTools and run `document.modelContext.getTools()`: you’ll see the same 4 tools an agent sees. Sarah’s extension will drive them for you if you’d rather click than type.

## What I still don’t know

I don’t know yet whether any agent will call these. The tools went live on 1 October, Chrome only offers them through an origin trial, and so far the only agent I’ve watched call them is my own demo. The `WebMCP Tool` events will tell me, and I’ll write down what they say.

I also don’t know where the line is between a tool and a page. A tool that answers “what does a workshop cost” is great, but if the agent answers everything, nobody sees the page the answer came from, and I don’t know yet what that does to a personal website.

## Takeaways

- WebMCP lets a page hand an AI agent real tools: a name, a description, an input schema and a function, in the page the visitor already has open.
- Chrome runs it as an origin trial from Chrome 149, and the spec is still a draft that has already moved once.
- Write each tool’s contract once, register it in the browser and check every call against it on the server.
- Return mistakes as sentences, because a thrown error reaches the model as a bare `UnknownError` .
- Stay inside Chrome’s budgets, and mark anything that books or pays with `consequentialHint` .
- Start with what your page already does.

If you want your team to build agents that call tools like these and don’t fall over, [I teach a workshop on reliable AI agents in production](https://tej.as/workshops#ai-agents).
If you’d like me to talk about AI and the web at your event, [here’s how to book me](https://tej.as/speaking).
If this made WebMCP click for you, please share it with someone whose agent is still screenshotting things.

ok bye

## Questions

### What is WebMCP?

WebMCP is a proposed web standard that lets a web page hand an AI agent using the browser a set of tools, each with a name, a description, a JSON Schema for its input and a function to run, so the agent calls the function instead of reading screenshots and clicking around. The spec is a draft from the World Wide Web Consortium's (W3C) Web Machine Learning Community Group, and Chrome runs it as an origin trial from Chrome 149.

### What is the difference between WebMCP and MCP?

The Model Context Protocol (MCP) connects an AI app to a server that somebody runs somewhere else, while WebMCP lets the web page you already have open offer tools to an agent working through your browser. A WebMCP tool lives in the page itself, so there is no extra server to run and nothing for the visitor to install or connect.

### How do I add WebMCP to my website?

Call `document.modelContext.registerTool()` with a name, a description, an input schema and an `execute` function, in a browser that supports WebMCP. On my site each `execute` sends its input to an API route that checks it against the same schema and answers from the same data the pages show.

### Which browsers support WebMCP?

Chrome supports WebMCP as an origin trial from Chrome 149, so a site that registers for the trial gets it for ordinary Chrome visitors, and you can turn it on for any site you're building with `chrome://flags/#enable-webmcp-testing`. It's still a proposed standard, and the API has already moved once, from `navigator` to `document`.

### What is WebMCP good for?

WebMCP is good for anything a person already does on a page that an agent could do with one function call instead of a dozen clicks: searching, filtering, checking a schedule, booking, checking out. Shopify uses it for checkout tools that place an order after the buyer authorizes it, and I use it so an agent can search everything I've published and read my speaking schedule and prices.

Written by me, Tejas Kumar, an AI Engineer at IBM based in Berlin. Read [everything else I have written](https://tej.as/blog), or go to [Fluent React, my O'Reilly book on how React works inside](https://tej.as/react), [the talks I give at conferences](https://tej.as/speaking), and [ConTejas Code, my podcast](https://tej.as/podcast).
