Skip to content

[feat]: add support for WebMCP tool invokation in iframes - #2878

Merged
seanmcguire12 merged 6 commits into
mainfrom
add-webmcp-support-in-iframes
Sep 3, 2026
Merged

[feat]: add support for WebMCP tool invokation in iframes#2878
seanmcguire12 merged 6 commits into
mainfrom
add-webmcp-support-in-iframes

Conversation

@seanmcguire12

@seanmcguire12 seanmcguire12 commented Sep 2, 2026

Copy link
Copy Markdown
Member

why

before this PR, WebMCP tools registered inside of iframes were unable to be discovered or invoked

what changed

  • changed WebMCP discovery to enable and collect tools from the page's main CDP session and every adopted OOPIF session
  • routed invocation, response handling, & cancellation through the CDP session that owns the tool's frame
  • stale tools are now rejected instead of falling back to the main frame, & only affected invocations are cleaned up when an OOPIF detaches
  • added extension coverage for cross-session discovery, invocation, cancellation, response correlation, frame detachment, disposal, & lifecycle races

test plan

  • Extension discovery tests cover combined main/OOPIF snapshots, child-session removals, stable session snapshots, next-call discovery after adoption, & listener cleanup after child enable failure.
  • Extension invocation tests cover child-session invocation, response, cancellation, wrong-session events, targeted detach cleanup, detach during command setup, page disposal, duplicate invocation IDs, unknown frames, & failed-command listener cleanup.
  • Browser integration coverage verifies distinct main/child CDP targets and sessions, successful iframe tool discovery and invocation, structured output, & stale-tool rejection after iframe removal.

Summary by cubic

WebMCP tools registered in out-of-process iframes (OOPIFs) are now discoverable and invokable; previously iframe tools were invisible and unusable. Invocation, response handling, and cancellation use the CDP session that owns the frame, while stale or detached frames fail instead of falling back to the main frame.

  • Discovery enables WebMCP on the main session and adopted OOPIF sessions, then combines their snapshots.
  • Detaching an OOPIF rejects only its pending invocations and removes its listeners.
  • Added extension and SDK integration coverage for cross-session lifecycle, cleanup, and iframe removal.

Written for commit 2a0744a. Summary will update on new commits.

Review in cubic

@changeset-bot

changeset-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a0744a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
@browserbasehq/stagehand-extension Patch
@browserbasehq/stagehand-go Patch
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-python Patch
@browserbasehq/stagehand-integrations Patch
@browserbasehq/stagehand-integrations-example-eve-facade Patch
@browserbasehq/stagehand-integrations-example-pi-facade Patch
@browserbasehq/stagehand-integrations-claude-agent-sdk Patch
@browserbasehq/stagehand-integrations-example-claude-code-facade Patch
@browserbasehq/stagehand-integrations-codex-sdk Patch
@browserbasehq/stagehand-integrations-example-codex-facade Patch
@browserbasehq/stagehand-integrations-cursor-sdk Patch
@browserbasehq/stagehand-integrations-deepagents-sdk Patch
@browserbasehq/stagehand-integrations-eve-sdk Patch
@browserbasehq/stagehand-integrations-fx-sdk Patch
@browserbasehq/stagehand-integrations-mastra-sdk Patch
@browserbasehq/stagehand-integrations-example-mastra-facade Patch
@browserbasehq/stagehand-integrations-pi-sdk Patch
@browserbasehq/stagehand-integrations-example-vercel-ai-facade Patch

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

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 6 files

Architecture diagram
sequenceDiagram
    participant Client as Stagehand Client
    participant Page as Extension Page Controller
    participant Registry as Frame and Session Registry
    participant Main as Main CDP Session
    participant OOPIF as Adopted OOPIF CDP Session
    participant Runtime as WebMCP Runtime in Page Frames

    Note over Client,Runtime: WebMCP tools are discovered and invoked across the page's main target and adopted OOPIF targets

    Client->>Page: tools()
    Page->>Registry: Snapshot owned CDP sessions and frame ownership
    Registry-->>Page: Main session and adopted OOPIF sessions

    par Discover main-frame tools
        Page->>Main: Subscribe to toolsAdded and toolsRemoved
        Page->>Main: WebMCP.enable
        Main->>Runtime: Enable WebMCP in main frame
        Runtime-->>Main: toolsAdded / toolsRemoved events
        Main-->>Page: Main-frame tool registrations
    and Discover OOPIF tools
        Page->>OOPIF: Subscribe to toolsAdded and toolsRemoved
        Page->>OOPIF: WebMCP.enable
        OOPIF->>Runtime: Enable WebMCP in iframe frame
        Runtime-->>OOPIF: toolsAdded / toolsRemoved events
        OOPIF-->>Page: OOPIF tool registrations
    end

    Page->>Page: Combine per-session snapshot and apply removals
    Page->>Main: Remove temporary discovery listeners
    Page->>OOPIF: Remove temporary discovery listeners
    Page-->>Client: Tools with name, description, and owning frameId

    Client->>Page: invokeWebMCPTool(frameId, toolName, input)
    Page->>Registry: Resolve session owning frameId
    Registry-->>Page: Main session or OOPIF session

    alt Frame belongs to main target
        Page->>Main: Subscribe to toolResponded
        Page->>Main: WebMCP.invokeTool(frameId, toolName, input)
        Main->>Runtime: Invoke tool in main frame
        Runtime-->>Main: invocationId
        Main-->>Page: invocationId
    else Frame belongs to adopted OOPIF
        Page->>OOPIF: Subscribe to toolResponded
        Page->>OOPIF: WebMCP.invokeTool(frameId, toolName, input)
        OOPIF->>Runtime: Invoke tool in iframe frame
        Runtime-->>OOPIF: invocationId
        OOPIF-->>Page: invocationId
    else Frame is unknown or detached
        Page-->>Client: Reject stale or unknown frame
    end

    Client->>Page: invocation.result() or waitForWebMCPInvocationResult(invocationId)
    alt Response arrives on owning session
        Runtime-->>Main: toolResponded(invocationId, status, output)
        Main-->>Page: Correlated response
        Page-->>Client: Structured tool result
    else Response arrives on wrong session
        Runtime-->>OOPIF: toolResponded with unrelated session
        OOPIF-->>Page: Ignore due to session ownership mismatch
    end

    opt Cancel pending invocation
        Client->>Page: cancelWebMCPInvocation(invocationId)
        Page->>Registry: Resolve invocation's owning session
        Registry-->>Page: Session recorded with invocation
        Page->>OOPIF: WebMCP.cancelInvocation(invocationId)
        OOPIF->>Runtime: Cancel iframe tool execution
        OOPIF-->>Page: Cancellation response or completion event
    end

    alt OOPIF detaches
        OOPIF-->>Page: Session detached
        Page->>Registry: Remove OOPIF session and frame subtree
        Page->>Page: Reject only invocations owned by detached session
        Page->>OOPIF: Remove response listener and pending state
        Page-->>Client: Detached-frame invocation errors
    else Page is disposed
        Client->>Page: dispose()
        Page->>Main: Reject pending invocations and remove listeners
        Page->>OOPIF: Reject pending invocations and remove listeners
    end
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/extension/understudy/page.ts

@akeimach akeimach left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

@seanmcguire12
seanmcguire12 force-pushed the add-webmcp-support-in-iframes branch from f72cd16 to 2a0744a Compare September 3, 2026 11:23
@seanmcguire12
seanmcguire12 merged commit 50146e4 into main Sep 3, 2026
55 checks passed
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.

3 participants