Testing
Test your tools by hand and watch the whole surface through debug console logs — no agent required
Test your agent surface before any agent is connected — the browser is the inspector. Every tool can be called by hand from the console, Chrome's DevTools shows the surface natively, and debug mode narrates everything the toolkit does.
Call tools by hand
Invoke any tool from the console and watch the app react
Chrome DevTools
The WebMCP panel lists tools and logs calls
Debug mode
Console flow logs for the whole surface
Testing resources
Verify live state updates when it should
Call tools by hand
Every registered tool is callable from the DevTools console:
const tools = await document.modelContext.getTools();
const t = tools.find(x => x.name === 'cart.add');
await document.modelContext.executeTool(t, JSON.stringify({ productId: 'sku_123' }));The real app should react — the cart drawer opens, the page navigates, the form submits. That's the whole point of the test: the agent will use exactly the same path, so if the app responds to your console call, it will respond to the agent.
Two wire-contract details when reading results by hand: getTools() returns each tool's inputSchema as a JSON string (parse before use), and executeTool resolves with a JSON string of the standard result envelope:
const text = JSON.parse(await document.modelContext.executeTool(t, JSON.stringify(args)))
.content?.[0]?.text;A good pass covers one tool per safety level you registered — a read, a reversible write, and (carefully) a destructiveHint tool — confirming for each that the returned content makes sense and the UI reacts.
Chrome DevTools
Chrome ships a dedicated WebMCP panel in DevTools: every registered tool is listed with its description and an invocation counter, every call is logged with its status, input, and output — and you can invoke tools manually with your own parameters, straight from the panel. This works because Edge MCP mirrors tools into the browser's native WebMCP registry.
Enabling the panel
The panel doesn't appear by default — WebMCP is an origin-trial feature (Chrome 149+), and for local development you enable it with flags:
- Open
chrome://flags/#enable-webmcp-testingand set WebMCP for testing to Enabled. - On the same page, search for WebMCP support in DevTools and set it to Enabled too.
- Relaunch Chrome.
- Open DevTools on your page → Application tab → WebMCP in the sidebar.
The flags are only needed for the DevTools panel. Edge MCP itself works without them in every browser — the polyfill provides document.modelContext regardless; the native mirror simply stays dormant until a native WebMCP surface exists.
The DevTools panel doesn't know about resources — they're a Napster extension. For those, use debug mode below.
Debug mode
Turn on the toolkit's flow logs and it narrates the entire surface with a colored [edge-mcp] prefix:
import { setDebug } from '@napster-corp/edge-mcp';
setDebug(true);Or at runtime, straight from the console — no rebuild needed:
globalThis.__EDGE_MCP_DEBUG__ = true;What you'll see, per event:
| Log line | When |
|---|---|
registered tool "…" / unregistered tool "…" | Tool lifecycle |
tool "…" called (locally | via native registry) — args: | Every invocation, with its arguments |
tool "…" responded: / tool "…" failed: | Every result or error |
registered resource "…" | Resource lifecycle |
resource "…" changed → | Every push sent to consumers, with the value |
resource "…" push suppressed (value unchanged) | A push dropped because the value matched the last one sent |
Logging is off by default, so the published integration stays quiet in production. Warnings about real problems (a failed native-registry mirror, a throwing resource getter) always print, debug on or off.
Testing resources
Resources only earn their place if they update on out-of-band changes — things the user does by hand. So test them that way:
- Enable debug mode.
- Use the site yourself: navigate, add something to the cart, type into the form — whatever your resources track.
- Watch for
resource "…" changed →— each user action that should update state should log exactly once. Several echoes per action means yoursubscribeis wired to too broad a signal; none means either the subscription isn't firing, or the value didn't actually change — check for apush suppressed (value unchanged)line to tell those two apart.
You can also read a resource's current value directly:
await document.modelContext.readResource('state://cart');