Skip to content

fix(mcp): rebind page-registered WebMCP tools when the tab or frame changes - #42821

Open
AbNoZ&v02 (Abnoz01) wants to merge 3 commits into
microsoft:mainfrom
Abnoz01:fix-42816
Open

AbNoZ&v02 (Abnoz01) wants to merge 3 commits into
microsoft:mainfrom
Abnoz01:fix-42816

Conversation

@Abnoz01

Copy link
Copy Markdown
Contributor

Summary

  • maybeNotifyWebMCPToolsChanged kept the previous tool definitions whenever the schema signature was unchanged. Each definition's handler is a closure over the tab and frame it was listed from, so after a reload an iframe tool failed with "Frame was detached", and with two tabs exposing the same tools the call ran in the previous tab.
  • Always take the fresh definitions and only gate the listChanged notification on the schema signature. Add tests for both cases.

Fixes #42816

…hanges

The dynamic tool list was only replaced when the tool schemas changed, so
handlers stayed bound to a detached frame after a reload, or to the
previous tab when two tabs exposed the same tools.

Fixes microsoft#42816
const tools = this._currentTab?.webmcpTools()?.tools.map(tool => tool.mcpTool) ?? [];
// Handlers are bound to the tab and frame they were listed from, so always take
// the fresh ones. Only the listChanged notification depends on the schemas.
this._webmcpTools = tools;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A cleaner variant is to drop Context._webmcpTools and have currentWebMCPTools() read from _currentTab?.webmcpTools().

Dmitry Gozman (@dgozman) what do you think?

Comment thread tests/mcp/webmcp-dynamic.spec.ts Outdated
});
});

test('a tool with the same name in two tabs runs in the current tab', async ({ startClient, server, mcpBrowser }) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just one test above is sufficient, drop this


maybeNotifyWebMCPToolsChanged() {
const tools = this._currentTab?.webmcpTools()?.tools.map(tool => tool.mcpTool) ?? [];
// Handlers are bound to the tab and frame they were listed from, so always take

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shorten the comment or drop it entirely: "// Handlers are bound to a tab and frame, always take the fresh ones."


maybeNotifyWebMCPToolsChanged() {
const tools = this._currentTab?.webmcpTools()?.tools.map(tool => tool.mcpTool) ?? [];
// Handlers are bound to the tab and frame they were listed from, so always take

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shorten the comment or drop it entirely: "// Handlers are bound to a tab and frame, always take the fresh ones."

@github-actions

This comment has been minimized.

Address review: drop the cached tool list on Context, keep only the
schema signature for listChanged notifications, drop the redundant
two-tab test and skip the iframe test on Firefox, which does not list
tools registered in iframes.
@Abnoz01

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up addressing the comments:

  • Went with the cleaner variant: dropped Context._webmcpTools, currentWebMCPTools() now reads from _currentTab?.webmcpTools(), and only the schema signature is kept for the listChanged notification.
  • Shortened the comment.
  • Dropped the second (two-tab) test.
  • The Firefox failures were on the iframe test: Firefox does not list tools registered in iframes (Tool "webmcp_add" not found before the reload), so the test is now skipped there. The remaining Windows Firefox failure is the cli-session idle-timeout test, which is unrelated.

@github-actions

This comment has been minimized.

@dgozman

Copy link
Copy Markdown
Collaborator

AbNoZ&v02 (@Abnoz01) [chrome] › mcp/cli-webmcp.spec.ts:162 › webmcp-call disambiguates duplicate tool names by frame is failing, which seems related. Could you please take a look?

@Abnoz01

Copy link
Copy Markdown
Contributor Author

Took a look. webmcp-call resolves the tool through listWebMCPTools(tab), which evaluates every frame fresh and drops a frame that rejects or hits the 5s timeout; it never reads the Context list this PR changes. The log shows the iframe contributed no tools, so the call fell through to the main frame.

The same test failed the same way on #42818 (injected regex change only), and the CI results db shows all three iframe tests in cli-webmcp.spec.ts failing on main and on #42787, #42789, #42832 and #42845 over the last few days, always on Linux/macOS Chrome with "Found 1 WebMCP tool(s)" / main-frame-only results. So it looks like a pre-existing race in collecting the iframe's tools rather than something from this change.

I merged main into the branch to get a fresh run. Happy to send a separate PR that waits for the iframe's tools to show up before asserting, if that helps.

@github-actions

Copy link
Copy Markdown
Contributor

Test results for "MCP"

1 failed
❌ [firefox] › mcp/cli-core.spec.ts:43 › click button @mcp-windows-latest-firefox

8698 passed, 1480 skipped


Merge workflow run.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

3 participants