← Back to microsoft/playwright
microsoft / playwright · Issue No. 42816
1.64.0-next (main @ 07f1a6154), introduced with #42671
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(...)
browser_navigate { url: "/" }webmcp_add {} → works, "Called WebMCP tool "add" in http://localhost/frame"browser_navigate { url: "/" } (same page again)webmcp_add {}B. Two tabs registering the same tool
/one -> registers "whoami", returns "tab-one"
/two -> registers "whoami", returns "tab-two"
browser_navigate { url: "/one" }browser_tabs { action: "new" }, browser_navigate { url: "/two" }browser_tabs { action: "select", index: 0 } (current tab is now /one)webmcp_whoami {}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.
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".
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.
- Operating System: macOS (Darwin 25.6.0)
- Node.js: 24.8.0
- Browser: Google Chrome with --enable-features=WebMCP
- Playwright: main @ 07f1a6154
Relay reads this issue against the repository's contribution signals: the files it is likely to touch, how the maintainers triage work this size, and what the first contribution would exercise.
The full analysis for this issue is still being assembled. Until then, the description above and the thread on GitHub are the most reliable context.