Testing WebMCP Tools
WebMCP is a proposed browser API that lets a website expose its own actions as structured, callable tools to in-browser AI agents.
Instead of an agent guessing where to click, your site registers tools with navigator.modelContext.registerTool(), each with a name, a description and a JSON Schema for its input.
If your website ships WebMCP tools, you need to verify they keep working: that every tool is registered, that its input schema is valid, and that calling it returns the result you expect. This page shows how to run those checks on real browsers in the TestingBot cloud with Selenium, Playwright and Puppeteer.
WebMCP is different from the TestingBot MCP Server. The TestingBot MCP Server is a tool you install locally to let AI assistants (Claude, Cursor, VS Code) drive your TestingBot account through the REST API. WebMCP is a browser feature your own website implements so AI agents can call your site's actions. This page is about testing the latter.
Why test your WebMCP tools
WebMCP tools are part of your public interface, just like a form or an API endpoint. They break in the same ways:
- Registration: a deploy removes or renames a tool, so the agent no longer finds it.
- Schema: an input schema becomes invalid or stops matching what the tool actually accepts.
-
Behavior: the tool registers fine but its
execute()callback returns the wrong result, throws, or silently changes shape. - Cross-browser: a tool works in one Chrome version but not another, or only when the page reaches a certain state.
Running these checks on real browsers in CI catches regressions before your users' AI agents do.
Prerequisites
- A TestingBot account with your key and secret.
- A website that registers WebMCP tools through
navigator.modelContext. - Google Chrome 149 or higher (WebMCP is currently a Chromium-only origin trial).
- The WebMCP testing surface enabled, so your test can list and invoke tools without a live AI agent. This exposes
navigator.modelContextTestingwithgetTools()andexecuteTool().
WebMCP is experimental and runs behind Chrome feature flags during the origin trial.
Launch Chrome 149 or higher with --enable-features=WebMCPTesting,DevToolsWebMCPSupport, which exposes navigator.modelContextTesting so your tests can list and invoke tools without a live agent.
See the Chrome WebMCP documentation for details. If you would like WebMCP enabled on the TestingBot grid for your account, contact support.
Testing WebMCP tools
The pattern is the same in every framework: launch Chrome 149 or higher with the WebMCP testing flag, navigate to your page, then call
navigator.modelContextTesting.getTools() to read the registered tools and
navigator.modelContextTesting.executeTool(name, input) to invoke one and inspect its result.
from selenium import webdriver
options = webdriver.ChromeOptions()
options.browser_version = "latest" # Chrome 149 or higher
# Enable the WebMCP testing surface (navigator.modelContextTesting) and the DevTools WebMCP domain
options.add_argument("--enable-features=WebMCPTesting,DevToolsWebMCPSupport")
options.set_capability("platformName", "WINDOWS")
options.set_capability("tb:options", {
"key": "YOUR_KEY",
"secret": "YOUR_SECRET",
"name": "WebMCP tool test",
})
driver = webdriver.Remote(
command_executor="https://hub.testingbot.com/wd/hub",
options=options,
)
try:
driver.get("https://your-site.com")
if not driver.execute_script("return 'modelContextTesting' in navigator"):
raise RuntimeError("WebMCP testing surface is not available in this browser")
# 1. List the tools your site registered with navigator.modelContext
tools = driver.execute_async_script("""
const done = arguments[arguments.length - 1];
navigator.modelContextTesting.getTools().then(done);
""")
names = [t["name"] for t in tools]
assert "searchProducts" in names, names
# 2. Invoke a tool and check the structured result
result = driver.execute_async_script("""
const [name, input, done] = arguments;
navigator.modelContextTesting.executeTool(name, input).then(done);
""", "searchProducts", {"query": "shoes"})
assert result["total"] > 0
finally:
driver.quit()
const { Builder } = require('selenium-webdriver')
const chrome = require('selenium-webdriver/chrome')
const options = new chrome.Options()
options.setBrowserVersion('latest') // Chrome 149 or higher
// Enable the WebMCP testing surface and the DevTools WebMCP domain (Chrome 149+)
options.addArguments('--enable-features=WebMCPTesting,DevToolsWebMCPSupport')
options.set('tb:options', {
key: 'YOUR_KEY',
secret: 'YOUR_SECRET',
name: 'WebMCP tool test'
})
;(async () => {
const driver = await new Builder()
.usingServer('https://hub.testingbot.com/wd/hub')
.forBrowser('chrome')
.setChromeOptions(options)
.build()
try {
await driver.get('https://your-site.com')
// 1. List the registered tools
const tools = await driver.executeAsyncScript(`
const done = arguments[arguments.length - 1];
navigator.modelContextTesting.getTools().then(done);
`)
console.log(tools.map(t => t.name))
// 2. Invoke a tool and check its result
const result = await driver.executeAsyncScript(`
const [name, input, done] = arguments;
navigator.modelContextTesting.executeTool(name, input).then(done);
`, 'searchProducts', { query: 'shoes' })
console.log(result)
} finally {
await driver.quit()
}
})()
const playwright = require('playwright')
const capabilities = {
'tb:options': {
key: 'YOUR_KEY',
secret: 'YOUR_SECRET',
name: 'WebMCP tool test'
},
browserName: 'chrome',
browserVersion: 'latest', // Chrome 149 or higher
// Enable the WebMCP testing surface and the DevTools WebMCP domain (Chrome 149+)
'goog:chromeOptions': { args: ['--enable-features=WebMCPTesting,DevToolsWebMCPSupport'] }
}
;(async () => {
const browser = await playwright.chromium.connect(
`wss://cloud.testingbot.com/playwright?capabilities=${encodeURIComponent(JSON.stringify(capabilities))}`
)
const page = await browser.newPage()
await page.goto('https://your-site.com')
// 1. List the registered tools
const tools = await page.evaluate(() => navigator.modelContextTesting.getTools())
console.log(tools.map(t => t.name))
// 2. Invoke a tool and check its result
const result = await page.evaluate(
([name, input]) => navigator.modelContextTesting.executeTool(name, input),
['searchProducts', { query: 'shoes' }]
)
console.log(result)
await browser.close()
})()
// Puppeteer 25.1.0 or higher ships a native page.webmcp API
const puppeteer = require('puppeteer-core')
const capabilities = {
'tb:options': {
key: 'YOUR_KEY',
secret: 'YOUR_SECRET',
name: 'WebMCP tool test'
},
browserName: 'chrome',
browserVersion: 'latest', // Chrome 149 or higher
// Enable the WebMCP testing surface and the DevTools WebMCP domain
'goog:chromeOptions': { args: ['--enable-features=WebMCPTesting,DevToolsWebMCPSupport'] }
}
;(async () => {
const browser = await puppeteer.connect({
browserWSEndpoint: `wss://cloud.testingbot.com/puppeteer?capabilities=${encodeURIComponent(JSON.stringify(capabilities))}`
})
const page = await browser.newPage()
await page.goto('https://your-site.com')
// 1. List the tools your site registered with navigator.modelContext
const tools = page.webmcp.tools()
console.log(tools.map(t => t.name))
// 2. Invoke a tool and check its structured result
const tool = tools.find(t => t.name === 'searchProducts')
if (tool) {
const result = await tool.execute({ query: 'shoes' })
if (result.status === 'Completed') {
console.log(result.output)
}
}
await browser.close()
})()
Older Puppeteer versions, and Selenium and Playwright, do not have a native WebMCP API. There you can reach the same tools by evaluating navigator.modelContextTesting.getTools() and executeTool() in the page, as shown in the other tabs.
After the run, mark the test as passed or failed in your TestingBot dashboard the same way you do for any other test, either from your test script or through the REST API.
What to assert
A useful WebMCP test suite checks more than "the page loaded". Good assertions include:
-
Tool presence: every tool you expect is listed by
getTools(), with the right name and description. -
Schema correctness: each tool's
inputSchemadeclares the parameters you intend, including required fields and enums. -
Happy path:
executeTool()with valid input returns the expected structured result. - Error handling: invalid input is rejected cleanly rather than throwing an unhandled error.
- State changes: write tools (for example "add to cart") actually change the page state, and read-only tools do not.
Browser support and caveats
WebMCP is an early, evolving standard. It is a W3C Community Group draft, not yet on the standards track, and is currently implemented only in Chromium-based browsers behind an origin trial (Chrome 149 and higher). The API has changed several times, so treat any integration as experimental and isolate your WebMCP test helpers so you can update them when the API moves.
- WebMCP is Chromium-only today. Firefox and Safari have not committed to it.
- The exact flag and API names can change between Chrome releases during the origin trial.
- Your site must enable WebMCP (through its origin-trial token or flag) for
navigator.modelContextto be available.
FAQ
They are unrelated. WebMCP is a browser API your website implements so in-browser AI agents can call your site's actions. The TestingBot MCP Server is a separate tool you install locally so AI assistants can manage your TestingBot account through the REST API. This page covers testing the WebMCP tools your own site exposes.
WebMCP is currently available only in Chromium-based browsers (Chrome 149 and higher) as an origin trial. Firefox and Safari have not committed to it yet. You can run your tests on Chrome in the TestingBot cloud today.
No. The WebMCP testing surface (navigator.modelContextTesting) lets your test list and invoke tools directly, so you can assert on the results in regular Selenium, Playwright or Puppeteer tests without involving a live AI model.
Not yet. WebMCP is an early standard in an origin trial and the API is still changing. It is a good time to experiment and to start testing your tools, but keep your WebMCP test helpers isolated so they are easy to update as the standard evolves.