[feat]: add WebMCP tools added/removed event hooks - #2916
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
🦋 Changeset detectedLatest commit: ed74093 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
All reported issues were addressed across 42 files
Architecture diagram
sequenceDiagram
participant App as TypeScript / Python / Go Client
participant SDK as Page SDK Wrapper
participant RPC as JSON-RPC Client
participant SW as Extension Service Worker
participant Runtime as Stagehand Runtime
participant Page as Page State Manager
participant Main as Main CDP Session
participant OOPIF as Child / OOPIF CDP Sessions
participant Browser as Chrome WebMCP Domain
Note over App,Browser: WebMCP tool discovery, shared page state, and typed page event delivery
App->>SDK: page.onToolsAdded or page.onToolsRemoved
SDK->>RPC: Register page.on with event toolsadded or toolsremoved
RPC->>SW: JSON-RPC request page.on
SW->>Runtime: Forward page.on with pageId, subscriptionId, and event
Runtime->>Page: Changed, asynchronously subscribe to shared WebMCP tool state
Page->>Page: Ensure tracking is initialized for all owned sessions
Page->>Main: Enable WebMCP once and attach toolsAdded and toolsRemoved listeners
Page->>OOPIF: Enable WebMCP for current and future child sessions
Main-->>Page: Initial toolsAdded discovery events
OOPIF-->>Page: Initial child-frame discovery events
Page->>Page: Store tools by frame and session in page-owned registry
Page-->>Runtime: Registration ready, future-only listener active
Runtime-->>SW: page.on registration result
SW-->>RPC: JSON-RPC response
RPC-->>SDK: Subscription handle
SDK-->>App: Subscription for unsubscribe or Close
alt Tool is registered in the page or a frame
Browser-->>Main: WebMCP toolsAdded
Main-->>Page: Tool descriptor with frame identity
Browser-->>OOPIF: WebMCP toolsAdded
OOPIF-->>Page: Child-frame tool descriptor
Page->>Page: Update registry and notify matching subscribers
Page->>Runtime: Typed toolsadded payload with sessionId and targetId
Runtime->>SW: Emit page.event notification
SW->>RPC: JSON-RPC page.event
RPC->>SDK: Decode typed PageToolsAddedNotification
SDK->>App: Callback with callable WebMCPTool wrappers
App->>RPC: Optional page.webmcp_invoke_tool
RPC->>SW: Forward tool invocation
SW->>Runtime: Invoke against owning frame and session
Runtime->>Main: WebMCP.invokeTool or route to OOPIF
else Tool is removed, document navigates, or frame detaches
Browser-->>Main: WebMCP toolsRemoved
Main-->>Page: Tool identity
Page->>Page: Remove tool from registry
Page->>Page: Invalidate tools for navigated or detached frame
Page->>Runtime: Typed toolsremoved payload with tool identities
Runtime->>SW: Emit page.event notification
SW->>RPC: JSON-RPC page.event
RPC->>SDK: Decode typed PageToolsRemovedNotification
SDK->>App: Callback with name and frame identity values
end
App->>SDK: page.tools
SDK->>RPC: Request current WebMCP tools
RPC->>SW: JSON-RPC page.tools
SW->>Runtime: Query page
Runtime->>Page: Read shared registry
Page-->>Runtime: Current tools without re-enabling WebMCP
Runtime-->>SW: Tool snapshot
SW-->>RPC: JSON-RPC response
RPC-->>SDK: Tool descriptors
SDK-->>App: Callable tool objects
opt Unsubscribe or disposal
App->>SDK: unsubscribe or Close
SDK->>RPC: page.off with subscriptionId
RPC->>SW: JSON-RPC request page.off
SW->>Runtime: Abort pending setup and detach subscriber
Runtime->>Page: Remove subscriber only
Page->>Page: Keep registry tracking alive
Page->>Main: Cleanup listeners when page is disposed
Page->>OOPIF: Cleanup listeners on frame detach or page disposal
end
alt Subscription setup fails or disconnects during setup
Page-->>Runtime: Registration error or cancellation
Runtime->>Runtime: Abort controller and release subscription reservation
Runtime->>Page: Dispose partially created listener
Runtime-->>SW: JSON-RPC error
SW-->>RPC: Registration failure
RPC-->>SDK: Reject subscription
end
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
Hey @seanmcguire12, could you take a look at this PR when you have a chance? I have a follow up change that adds support for WebMCP's |
There was a problem hiding this comment.
All reported issues were addressed across 8 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
@antonvishal if you don't mind rebasing #2917 after this one lands that would be ideal! cheers |
Sounds good! I’ll rebase #2917 once this one lands. Cheers! |
why
users need a way to subscribe to events that fire when webmcp tools were added or removed from a page
note:
this PR ended up a lot larger than just adding two hooks because
WebMCP.enablecauses Chrome to emittoolsAddedevents for tools that already exist (docs here).ie, the
WebMCP.toolsAddedevent would fire every time someone calledpage.tools(). therefore, we needed to manage some state, and essentially keep a registry of tools that have been added/removed.with the changes from this PR,
page.tools()reads that registry instead of enabling WebMCP again. a lot of the code here is related to state synchronization, because the registry now needs to be kept in sync across navigation and iframe detachment etc..what changed
onToolsAdded()/onToolsRemoved()in TypeScript,on_tools_added()/on_tools_removed()in Python, andOnToolsAdded()/OnToolsRemoved()in Gounsubscribe()/Close(ctx)page.eventnotifications alongside the existing rawpage.cdp_eventpath, with shared protocol schemas and generated SDK modelspage.tools()and the hooks use the same state without repeatedly enabling WebMCP or replaying discovery results to listenerstest plan
Summary by cubic
Adds WebMCP tool add/remove event hooks so users can subscribe when tools appear or disappear on a page. Previously only console events were available; the new
onToolsAdded()/onToolsRemoved()(TypeScript),on_tools_added()/on_tools_removed()(Python), andOnToolsAdded()/OnToolsRemoved()(Go) hooks deliver typed payloads over a newpage.eventnotification alongside the existing rawpage.cdp_eventpath.New Features
WebMCPToolobjects; removed hooks deliver tool identities.page.tools()and the hooks stay consistent without repeatedly enabling WebMCP or replaying results.Written for commit ed74093. Summary will update on new commits.