DEV Community

Cover image for 13,352 Websites Already Let AI Agents Use Their Forms. Here's How WebMCP Works (With Code)
Hannan Shoukat for 8Bit Enterprise

Posted on AI-assisted

13,352 Websites Already Let AI Agents Use Their Forms. Here's How WebMCP Works (With Code)

AI agents that browse the web on someone's behalf have a hard job. They look at a page, guess which box is the email field, guess which button submits, and hope nothing moved.

WebMCP is Chrome's answer to that. Instead of guessing, an agent can ask the page: what can you do? The page answers with a list of tools, each with a name, a description and a schema for its inputs.

It's still experimental, but it's already in use on more sites than I expected.

How many sites already use it

Browser Use ran a crawl to find out. According to their WebMCP directory, they loaded 322,714 pages in Chrome and found 13,352 sites exposing 45,763 distinct tools. The scan finished on October 19, 2026.

A few things stood out:

  • Shopping leads, with 6,107 sites, ahead of business software and developer tools.
  • Shopify accounts for about 5,190 of them, adding tools like add-to-cart and catalog search across many stores at once.
  • Adoption is still small at the top: 1,270 of the top 100,000 sites they could load, about 1.7%, had WebMCP tools.

So if you run a store on Shopify, your site may already be talking to agents. For everyone else, it's early, which is the best time to learn it.

The status, honestly

WebMCP is an active origin trial. Chrome's WebMCP guidance says local testing needs Chromium 146.0.7672.0 or later with the chrome://flags/#enable-webmcp-testing flag turned on, and that the API is experimental and may change.

Don't rebuild anything around it yet. But adding it to a form is cheap, and that's where to start.

The easy start: two attributes on a form

The declarative API turns an ordinary HTML form into a tool. Add toolname and tooldescription to the <form>, and optionally describe individual fields with toolparamdescription.

This is close to the example in Chrome's declarative API docs:

<form toolname="newsletter_signup"
      tooldescription="Subscribes the user to the weekly newsletter"
      action="/subscribe" method="post">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" required
         toolparamdescription="The user's email address">
  <button type="submit">Sign up</button>
</form>
Enter fullscreen mode Exit fullscreen mode

A few details from the docs worth knowing:

  • Both attributes are required. Remove either one and the tool is unregistered.
  • Labels count. Without toolparamdescription, the browser describes a field using its <label> text.
  • The user still submits by default. The agent can fill the form, but a person clicks the button, unless you add toolautosubmit.

Know when an agent sent the form

The submit event gets an agentInvoked flag, so you can treat agent submissions differently. You can also send a result straight back to the agent:

form.addEventListener('submit', (e) => {
  if (e.agentInvoked) {
    e.preventDefault();
    e.respondWith(
      fetch(form.action, { method: 'POST', body: new FormData(form) })
        .then((res) => (res.ok ? 'Subscribed.' : 'Subscription failed.'))
    );
  }
});
Enter fullscreen mode Exit fullscreen mode

Whatever the promise resolves to is returned to the model as the tool's output.

For app-like pages: register a tool in JavaScript

When an action isn't a simple form, use the imperative API. Chrome's imperative API docs show it living on document.modelContext:

const controller = new AbortController();

await document.modelContext.registerTool({
  name: 'check_order_status',
  description: 'Returns the shipping status for an order number.',
  inputSchema: {
    type: 'object',
    properties: { orderNumber: { type: 'string' } },
    required: ['orderNumber'],
  },
  execute: async ({ orderNumber }) => {
    const res = await fetch(`/api/orders/${encodeURIComponent(orderNumber)}`);
    const order = await res.json();
    return `Order ${orderNumber} is ${order.status}.`;
  },
}, { signal: controller.signal });

// later, to remove the tool:
controller.abort();
Enter fullscreen mode Exit fullscreen mode

The order-status endpoint is my example. The registerTool shape and the AbortSignal cleanup come from the docs.

The safety settings that matter

This is the part I'd read twice. Chrome's docs include several guards:

Setting What it does
consequentialHint: true Marks a high-impact action, so agents and browsers can ask the user to confirm
untrustedContentHint: true Flags output that came from untrusted sources, such as user reviews, to help against prompt injection
allow="tools" on an iframe Required before a cross-origin iframe can register tools
exposedTo Tools are hidden from other origins unless you list them here

Chrome's guidance also says not to auto-submit tools for destructive or irreversible actions, such as deleting data, unless the person has to confirm manually.

My rule of thumb: newsletter signups and searches are fine to expose. Anything involving money, accounts or deletion should keep a human in the loop.

How to test and debug it

Two Chrome tools help here:

  • DevTools: open Application, then WebMCP. It lists the tools on the current tab and logs each time an agent calls one, with inputs and outputs. See Debug WebMCP tools.
  • Lighthouse: it now has an audit that flags <form> elements missing toolname or tooldescription. Chrome's docs say it's informational for now and won't produce warnings.

Should you add it now?

For a contact form, newsletter or site search, yes. It's a couple of attributes, and it costs nothing if the agent never shows up.

For checkout, payments or account actions, I'd wait. The API is an origin trial, the details are still changing, and those are exactly the actions where a mistake costs real money.

Has anyone added WebMCP to a production site yet? I'd like to know whether agents are actually calling your tools, or if they're mostly sitting idle so far.

Top comments (0)