Skip to content

feat: scaffold Stagehand code-mode MCP host - #2597

Open
shrey150 wants to merge 5 commits into
v4-spikefrom
shrey/stg-2765-codemode-package
Open

feat: scaffold Stagehand code-mode MCP host#2597
shrey150 wants to merge 5 commits into
v4-spikefrom
shrey/stg-2765-codemode-package

Conversation

@shrey150

@shrey150 shrey150 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Why

The code-mode product work spans three distinct review domains: process hosting, browser code execution, and agent guidance. This bottom PR isolates the package and Model Context Protocol (MCP) host so its build, transport, and shutdown behavior can be reviewed without the execution engine or prompt content.

Stack

  1. This PR: private package, MCP stdio host, lifecycle, repository build/test wiring
  2. feat: add Stagehand code execution tool #2619: Stagehand executor, local and Browserbase configuration, schemas, queueing, and code_execute registration
  3. feat: add Stagehand code-mode guidance #2620: SKILL.md, REFERENCE.md, generated exports, package assets, and guidance loading checks
  4. #2626 — Vercel AI SDK MCP example and smoke flows
  5. #2627 — Mastra MCP example and smoke flows
  6. #2628 — CrewAI MCP example and smoke flows
  7. #2629 — LangChain Deep Agents MCP example and smoke flows

Each PR is intended to build, test, and make a truthful claim independently.

What changed

  • adds the private @browserbasehq/stagehand-integrations workspace package
  • adds a compiled stdio entrypoint backed by the MCP SDK
  • negotiates MCP server metadata without advertising capabilities that do not exist yet
  • bounds concurrent shutdown cleanup to five seconds
  • preserves conventional process exit codes for SIGINT and SIGTERM
  • wires the package into workspace, Turbo, Vitest, and CI discovery

Intentionally not included

  • no MCP tools
  • no browser or model configuration
  • no Stagehand executor
  • no skill or reference content
  • no published package surface; the package remains private

E2E Test Matrix

Command / flow Observed output Confidence / sufficiency
pnpm --filter @browserbasehq/stagehand-integrations typecheck && pnpm --filter @browserbasehq/stagehand-integrations build && pnpm --filter @browserbasehq/stagehand-integrations test:unit Package typecheck and build passed; 3 test files and 9 tests passed. Covers host construction, bounded cleanup, compiled stdio startup, end-of-file shutdown, and signal exit codes. It intentionally does not prove a tool or browser session.
Manual MCP client connected to the compiled stdio entrypoint {"initialized":true,"toolsCapability":null,"readyMessage":true} Proves the built artifact starts as a child process, negotiates MCP, emits its readiness message, and truthfully advertises no tools.
pnpm exec turbo run test:unit --filter=@browserbasehq/stagehand-integrations 2/2 Turbo tasks passed; package build plus 9/9 tests passed. Proves the repository task graph builds the package before compiled-child tests.
pnpm check 9/9 repository tasks passed. Supports repository-wide formatting, lint, and type compatibility for this layer.

Changeset

None. This introduces a private workspace package and does not publish a release.

@changeset-bot

changeset-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 9449d79

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a 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.

6 issues found and verified against the latest diff

Confidence score: 3/5

  • In packages/integrations/src/codemode/executor.ts, the native executor path appears non-interruptible once execution starts because abort is only checked pre-run and both execute/close share this.queue; a hung snippet can block shutdown and tie up the worker indefinitely—add in-flight cancellation checks and ensure close can preempt or bypass a blocked execution path.
  • In packages/integrations/src/codemode/executor.ts, the 256 KB result cap is enforced only after full JSON.stringify, so very large snippet outputs can still cause memory spikes before truncation, with potential OOM/instability under hostile or accidental large returns—enforce limits during serialization/streaming or short-circuit oversized structures before full stringification.
  • Across packages/integrations/src/codemode/tool-contract.ts, packages/integrations/src/codemode/executor.ts, packages/integrations/scripts/generate-codemode-content.mjs, and packages/integrations/src/codemode/snippet.ts, key new contract/executor/escaping/binding behaviors lack registered focused tests, increasing regression risk for public codemode behavior and CI blind spots—add and register targeted tests for queueing/cancellation, schema/result formatting, content escaping with --check, and executeStagehandSnippet validation paths.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/integrations/src/codemode/tool-contract.ts">

<violation number="1" location="packages/integrations/src/codemode/tool-contract.ts:24">
P3: Current CI cannot exercise this new public contract because the package has no registered tests. Add focused schema and result-formatting tests, then register a package test task.

(Based on your team's feedback about unit tests for new behavior.) .</violation>
</file>

<file name="packages/integrations/src/codemode/executor.ts">

<violation number="1" location="packages/integrations/src/codemode/executor.ts:25">
P3: This new executor has no committed focused tests for queueing, lazy lifecycle, error cleanup, or serialization edge cases, leaving its public native/MCP behavior unguarded. Add executor-level tests covering a normal persistent call and key failure/close paths.

(Based on your team's feedback about unit tests for new behavior.) .</violation>

<violation number="2" location="packages/integrations/src/codemode/executor.ts:84">
P2: For the native (non-MCP) executor path, a non-terminating snippet can never be interrupted: the AbortSignal is only checked once before the code starts, and `execute`/`close` both serialize through `this.queue`. A snippet that loops forever leaves the in-flight call unresolved, so `close()` (which waits on the queue) never resolves and the persistent browser/process leaks on shutdown. Consider passing the signal through to the snippet so an abort can terminate the run, or otherwise bound execution time.</violation>

<violation number="3" location="packages/integrations/src/codemode/executor.ts:188">
P2: The size guard only kicks in after `JSON.stringify` has fully built the result string in memory, so a snippet that returns a very large value still consumes unbounded memory before the 256 KB truncation is applied. This undermines MAX_RESULT_BYTES as a safety/memory bound in an agent-facing code executor that has no sandbox. Truncating incrementally (e.g., streaming serialization) or imposing a forced/capped serialization would keep memory usage proportional to the configured limit.</violation>
</file>

<file name="packages/integrations/scripts/generate-codemode-content.mjs">

<violation number="1" location="packages/integrations/scripts/generate-codemode-content.mjs:28">
P3: Generated-content escaping and stale-file validation have no automated coverage; add focused tests for special characters plus current and stale `--check` output.

(Based on your team's feedback about unit tests for new behavior.)</violation>
</file>

<file name="packages/integrations/src/codemode/snippet.ts">

<violation number="1" location="packages/integrations/src/codemode/snippet.ts:11">
P3: Regression coverage is absent for `executeStagehandSnippet`, including binding validation and injected dependency behavior. Add focused unit tests for normal execution, reserved/invalid names, and optional `stagehand`.

(Based on your team's feedback about adding unit tests for new behavior.) .</violation>
</file>

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

Re-trigger cubic

Comment thread packages/integrations/src/codemode/stdio-server.ts Outdated
Comment thread packages/integrations/src/codemode/executor.ts Outdated
Comment thread packages/integrations/README.md Outdated
Comment thread packages/integrations/src/codemode/executor.ts Outdated
Comment thread packages/integrations/README.md Outdated
Comment thread packages/integrations/src/codemode/tool-contract.ts Outdated
Comment thread packages/integrations/src/codemode/executor.ts Outdated
Comment thread packages/integrations/scripts/generate-codemode-content.mjs Outdated
Comment thread packages/integrations/src/codemode/snippet.ts Outdated
Comment thread packages/integrations/src/codemode/mcp-server.ts Outdated
@shriyatheunicorn
shriyatheunicorn force-pushed the shrey/stg-2765-codemode-package branch from dab19ae to 171765f Compare August 5, 2026 07:14

@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 9 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread packages/integrations/src/codemode/tool-contract.ts Outdated
Comment thread packages/integrations/src/codemode/executor.ts Outdated
Comment thread packages/integrations/src/codemode/executor.ts Outdated
Comment thread packages/integrations/src/codemode/executor.ts Outdated

@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 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread packages/integrations/src/codemode/executor.ts Outdated
@shrey150
shrey150 marked this pull request as draft August 5, 2026 19:57
@shrey150
shrey150 force-pushed the shrey/stg-2765-codemode-package branch from 8517905 to 2cfa7b0 Compare August 6, 2026 08:34
@shrey150 shrey150 changed the title feat: add shared Stagehand code-mode integrations feat: scaffold Stagehand code-mode MCP host Aug 6, 2026
@shrey150
shrey150 marked this pull request as ready for review August 6, 2026 08:57

@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 15 files

Architecture diagram
sequenceDiagram
    participant MCP_Client as MCP Client
    participant StdioTransport as Stdio Transport
    participant ServerEntry as stdio-server.ts
    participant McpHost as McpServer Instance
    participant Shutdown as closeCodeModeStdio()

    Note over MCP_Client,Shutdown: NEW: Stagehand code-mode MCP host startup and lifecycle

    MCP_Client->>StdioTransport: spawn process (node dist/codemode/stdio-server.mjs)
    StdioTransport->>ServerEntry: stdin/stdout/stderr connected

    ServerEntry->>ServerEntry: createCodeModeMcpHost()
    ServerEntry->>McpHost: NEW: McpServer("stagehand-codemode", "4.0.0")
    McpHost-->>ServerEntry: ready

    ServerEntry->>ServerEntry: connectCodeModeStdio(server)
    ServerEntry->>McpHost: connect(new StdioServerTransport())
    McpHost-->>ServerEntry: connected

    ServerEntry->>StdioTransport: stderr: "Stagehand code-mode MCP host listening on stdio"

    Note over StdioTransport,McpHost: MCP initialization handshake

    MCP_Client->>StdioTransport: initialize request
    StdioTransport->>McpHost: forward initialize
    McpHost-->>StdioTransport: capabilities (no tools)
    StdioTransport-->>MCP_Client: capabilities

    Note over MCP_Client,Shutdown: Shutdown scenarios

    alt stdin EOF (normal shutdown)
        ServerEntry->>ServerEntry: stdin "end" event
        ServerEntry->>McpHost: close()
        ServerEntry->>Shutdown: closeCodeModeStdio([server])
        Shutdown->>McpHost: close()
        alt cleanup completes within 5s
            McpHost-->>Shutdown: resolved
            Shutdown-->>ServerEntry: true
            ServerEntry->>ServerEntry: process.exit(0)
        else cleanup timeout
            Shutdown->>Shutdown: setTimeout(5000)
            Shutdown-->>ServerEntry: false
            ServerEntry->>StdioTransport: stderr: "Failed to close..."
            ServerEntry->>ServerEntry: process.exit(1)
        end
    else SIGINT (Ctrl+C)
        ServerEntry->>ServerEntry: signal handler
        ServerEntry->>McpHost: close()
        ServerEntry->>Shutdown: closeCodeModeStdio([server])
        Shutdown-->>ServerEntry: result
        ServerEntry->>ServerEntry: process.exit(130)
    else SIGTERM
        ServerEntry->>ServerEntry: signal handler
        ServerEntry->>McpHost: close()
        ServerEntry->>Shutdown: closeCodeModeStdio([server])
        Shutdown-->>ServerEntry: result
        ServerEntry->>ServerEntry: process.exit(143)
    end
Loading

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

Re-trigger cubic

Comment thread packages/integrations/src/codemode/stdio-server.ts Outdated
Comment thread .github/workflows/ci.yml
Comment thread packages/integrations/src/codemode/stdio-lifecycle.ts Outdated
Comment thread turbo.json Outdated
Comment thread packages/integrations/tests/stdio-server.test.ts Outdated
Comment thread packages/integrations/package.json
@shrey150 shrey150 closed this Aug 6, 2026
@shrey150 shrey150 reopened this Aug 6, 2026

@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.

1 issue found across 6 files (changes from recent commits).

Confidence score: 5/5

  • In packages/integrations/tests/stdio-server.test.ts, waitForOutput can leave its timeout/listener active when the stream ends/errors early or when client.connect throws before await ready, which can cause dangling async work and flaky/hanging test runs—ensure cleanup runs on all exit paths (match, error, end, and thrown connect) via finally/shared teardown.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/integrations/tests/stdio-server.test.ts">

<violation number="1" location="packages/integrations/tests/stdio-server.test.ts:50">
P3: waitForOutput only clears its timer/listener when the expected string is matched; if the stream errors or ends first, or if client.connect throws before await ready (ready is created outside the try), the 10s timeout and data listener linger and can produce a late unhandled rejection. Consider rejecting promptly on stream error/end/close and creating the promise inside the try so an early connect failure doesn't leave a dangling timer.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread packages/integrations/tests/stdio-server.test.ts Outdated
Comment thread .github/workflows/ci.yml
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.

1 participant