Skip to content

[Bug]: MCP page-registered WebMCP tools stay bound to a stale frame or tab when the tool list looks unchanged #42816

Description

@Abnoz01

Version

1.64.0-next (main @ 07f1a61), introduced with #42671

Steps to reproduce

Chromium with --enable-features=WebMCP (the chrome project of tests/mcp, config { browser: { launchOptions: { args: ['--enable-features=WebMCP'] } } }).

A. Tool registered in an iframe, page reloaded

/         -> <iframe src="/frame">
/frame    -> registers tool "add" via document.modelContext.registerTool(...)
  1. browser_navigate { url: "/" }
  2. webmcp_add {} → works, "Called WebMCP tool "add" in http://localhost/frame"
  3. browser_navigate { url: "/" } (same page again)
  4. webmcp_add {}

B. Two tabs registering the same tool

/one -> registers "whoami", returns "tab-one"
/two -> registers "whoami", returns "tab-two"
  1. browser_navigate { url: "/one" }
  2. browser_tabs { action: "new" }, browser_navigate { url: "/two" }
  3. browser_tabs { action: "select", index: 0 } (current tab is now /one)
  4. webmcp_whoami {}

Expected behavior

A. The call after the reload runs against the new frame and succeeds.
B. The tool runs in the selected tab and returns tab-one.

Actual behavior

A: ### Error
   browserBackend.callTool: Frame was detached

B: ### Result
   Called WebMCP tool "whoami" in http://localhost:PORT/two ... "text": "tab-two"

The tool is still listed after the reload but cannot be called, and in the two-tab case a page tool silently runs in the non-current tab, which is a wrong-target execution for consequential tools such as "place order" or "send message".

Additional context

Context.maybeNotifyWebMCPToolsChanged() (packages/playwright-core/src/tools/backend/context.ts) compares JSON.stringify(tools.map(t => t.schema)) against the previous signature and returns early when equal, keeping the old _webmcpTools. Each WebMCPToolDefinition.handle is a closure over the Tab and Frame captured when the listing was taken (webmcp.ts, toMcpToolDefinition). A reload recreates child frames, and switching between two tabs with identical tools produces an identical signature, so the stale closures are kept while the schema looks unchanged.

Suggested fix: always replace _webmcpTools with the fresh definitions and only gate the listChanged notification on the schema signature.

I intend to work on this and will send a PR.

Environment

- Operating System: macOS (Darwin 25.6.0)
- Node.js: 24.8.0
- Browser: Google Chrome with --enable-features=WebMCP
- Playwright: main @ 07f1a6154

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions