Skip to content

[STG-2405] fix: agent({ integrations }) with an MCP Client throws circular-structure JSON - #2278

Merged
shrey150 merged 1 commit into
mainfrom
shrey/fix-mcp-integrations-circular-json
Jun 25, 2026
Merged

[STG-2405] fix: agent({ integrations }) with an MCP Client throws circular-structure JSON#2278
shrey150 merged 1 commit into
mainfrom
shrey/fix-mcp-integrations-circular-json

Conversation

@shrey150

@shrey150 shrey150 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What & why

stagehand.agent({ integrations }) is unusable with a local/stdio MCP server. agent() logs its config as auxiliary metadata via JSON.stringify(options.integrations), but an MCP Client instance (what connectToMCPServer({ command, args }) returns) is a circular object — so the call throws TypeError: Converting circular structure to JSON before the agent ever runs.

This blocks the documented stdio-MCP path entirely (URL-string integrations are unaffected, since a string serializes fine).

The fix

packages/core/lib/v3/v3.ts — in the agent-creation log, serialize a safe descriptor instead of the raw array: keep URL strings, summarize Client instances as "[mcp client]". One site; it runs for all agent modes (dom/hybrid/cua). No public API change. Patch changeset added.

// before
value: JSON.stringify(options.integrations),
// after
value: JSON.stringify(
  options.integrations.map((i) => (typeof i === "string" ? i : "[mcp client]")),
),

E2E Test Matrix

Command / flow Observed output Confidence / sufficiency
Before fix (published 3.6.0): agent({ integrations: [connectToMCPServer({command:"npx", args:[…filesystem MCP…]})] }) run on live Browserbase TypeError: Converting circular structure to JSON … at V3.agent — crashes before the agent starts. Reproduced on a second MCP server (@modelcontextprotocol/server-everything) → not server-specific. Proves the bug and that it's general to any Client integration.
After fix (local build copied into a scratch project), same script on live Browserbase exit 0, no circular error; agent connected to the MCP server (Secure MCP Filesystem Server running on stdio) and invoked its tools (got a real tool response). Proves the fix unblocks agent({ integrations: [client] }) end-to-end.
pnpm build:esm (core) + grep built v3.js build exit 0; built output contains the safe descriptor, no JSON.stringify(options.integrations). Fix compiles and is present in the artifact under test.

Note: server-side ingestion is irrelevant here — this is a pure client-side serialization crash; the matrix exercises the exact throwing call path before and after.

Closes STG-2405.

🤖 Generated with Claude Code


Summary by cubic

Fixes a circular-JSON crash when creating an agent with MCP Client integrations (e.g., from connectToMCPServer). We now log a safe descriptor for integrations, so agent({ integrations: [client] }) works with local/stdio MCP servers across all modes. Addresses STG-2405.

Written for commit 01323a5. Summary will update on new commits.

Review in cubic

agent() logged the raw integrations array as auxiliary metadata via
JSON.stringify(options.integrations). A live MCP Client (from
connectToMCPServer, used for any local/stdio MCP server) is circular, so this
threw `TypeError: Converting circular structure to JSON` before the agent ran,
making agent({ integrations: [client] }) unusable. Log a safe descriptor
instead (URL strings kept, client instances summarized).

Verified live on Browserbase: before, agent({ integrations: [stdio client] })
crashed; after, the agent connects to the MCP server and invokes its tools.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 01323a5

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

This PR includes changesets to release 3 packages
Name Type
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-evals Patch
@browserbasehq/stagehand-server-v3 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.

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant User as User Code
    participant V3 as V3.agent()
    participant JSON as JSON.stringify
    participant Integrations as Integrations Array
    participant Log as Auxiliary Metadata Log

    User->>V3: agent({ integrations: [mcpClient] })
    V3->>V3: Prepare metadata object (includes integrations key)

    alt BEFORE FIX (circular crash)
        V3->>JSON: JSON.stringify(options.integrations)
        JSON->>Integrations: Attempt to serialize MCP Client
        Integrations-->>JSON: Circular reference
        JSON-->>V3: TypeError: Converting circular structure to JSON
        Note over V3: Agent never starts – throws
    else AFTER FIX (safe descriptor)
        V3->>V3: Map each integration: <br/>string? keep as-is, Client? → "[mcp client]"
        V3->>JSON: JSON.stringify(mappedIntegrations)
        JSON-->>V3: Safe string
        V3->>Log: Log metadata with safe integrations string
        Log-->>V3: OK
        V3-->>User: Agent created successfully
    end
Loading

Re-trigger cubic

@shrey150
shrey150 merged commit 022d68f into main Jun 25, 2026
453 of 454 checks passed
seanmcguire12 pushed a commit that referenced this pull request Jul 13, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @browserbasehq/stagehand@3.7.0

### Minor Changes

- [#2283](#2283)
[`871ca7e`](871ca7e)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add
`context.setDomainPolicy({ allowedDomains: ["allowed.domain"] })` which
allows users to define a set of domains that are accessible to stagehand

- [#2274](#2274)
[`f31980f`](f31980f)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add
`context.setDomainPolicy({blockedDomains: ["some.domain"]})` which
allows users to define a list of domains that will be blocked by
stagehand

### Patch Changes

- [#2305](#2305)
[`cd1daad`](cd1daad)
Thanks [@shrey150](https://github.com/shrey150)! - Remove the noisy AI
SDK "system message in messages" warning logged on every hybrid/DOM
`agent.execute()` call.

- [#2328](#2328)
[`d287ff4`](d287ff4)
Thanks [@miguelg719](https://github.com/miguelg719)! - Allow modelName
"auto" in the constructor and per-primitive model overrides when running
through the Stagehand API

- [#2294](#2294)
[`3938590`](3938590)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! -
automatically close popups that violate user defined domain policy

- [#2298](#2298)
[`892701a`](892701a)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Fix CUA
`keypress` actions to press key combinations as a single chord.

- [#2345](#2345)
[`21826c7`](21826c7)
Thanks [@monadoid](https://github.com/monadoid)! - Repair malformed
UTF-16 snapshot text before it reaches model prompts.

- [#2306](#2306)
[`8dcef1b`](8dcef1b)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Use the
screenshot provider's declared media type when sending CUA image
payloads. The `setScreenshotProvider` callback now returns
`ScreenshotProviderResult` (`{ base64, mediaType }`) instead of a bare
base64 string.

- [#2273](#2273)
[`93a23d3`](93a23d3)
Thanks [@miguelg719](https://github.com/miguelg719)! - Add support for
the new `google/gemini-3.5-flash` computer-use tools model

- [#2278](#2278)
[`022d68f`](022d68f)
Thanks [@shrey150](https://github.com/shrey150)! - Fix `TypeError:
Converting circular structure to JSON` when creating an agent with MCP
`integrations` that include a `Client` instance (e.g. a local/stdio
server from `connectToMCPServer`). The agent-creation log serialized the
raw `integrations` array, and a live MCP `Client` is circular. It now
logs a safe descriptor (URL strings kept, client instances summarized)
so `agent({ integrations: [client] })` works.

- [#2288](#2288)
[`bb5ffa6`](bb5ffa6)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - clean up
cdp session event handlers on target detach

## @browserbasehq/stagehand-evals@2.0.4

### Patch Changes

- Updated dependencies
\[[`cd1daad`](cd1daad),
[`d287ff4`](d287ff4),
[`3938590`](3938590),
[`892701a`](892701a),
[`21826c7`](21826c7),
[`8dcef1b`](8dcef1b),
[`93a23d3`](93a23d3),
[`871ca7e`](871ca7e),
[`022d68f`](022d68f),
[`bb5ffa6`](bb5ffa6),
[`f31980f`](f31980f)]:
    -   @browserbasehq/stagehand@3.7.0

## @browserbasehq/stagehand-server-v3@3.7.2

### Patch Changes

- Updated dependencies
\[[`cd1daad`](cd1daad),
[`d287ff4`](d287ff4),
[`3938590`](3938590),
[`892701a`](892701a),
[`21826c7`](21826c7),
[`8dcef1b`](8dcef1b),
[`93a23d3`](93a23d3),
[`871ca7e`](871ca7e),
[`022d68f`](022d68f),
[`bb5ffa6`](bb5ffa6),
[`f31980f`](f31980f)]:
    -   @browserbasehq/stagehand@3.7.0

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
felipeofdev-ai pushed a commit to felipeofdev-ai/stagehand that referenced this pull request Aug 4, 2026
…cular-structure JSON (browserbase#2278)

## What & why

`stagehand.agent({ integrations })` is unusable with a local/stdio MCP
server. `agent()` logs its config as auxiliary metadata via
`JSON.stringify(options.integrations)`, but an MCP `Client` instance
(what `connectToMCPServer({ command, args })` returns) is a **circular
object** — so the call throws **`TypeError: Converting circular
structure to JSON`** *before the agent ever runs*.

This blocks the documented stdio-MCP path entirely (URL-string
integrations are unaffected, since a string serializes fine).

## The fix

`packages/core/lib/v3/v3.ts` — in the agent-creation log, serialize a
**safe descriptor** instead of the raw array: keep URL strings,
summarize `Client` instances as `"[mcp client]"`. One site; it runs for
all agent modes (dom/hybrid/cua). No public API change. Patch changeset
added.

```ts
// before
value: JSON.stringify(options.integrations),
// after
value: JSON.stringify(
  options.integrations.map((i) => (typeof i === "string" ? i : "[mcp client]")),
),
```

## E2E Test Matrix

| Command / flow | Observed output | Confidence / sufficiency |
| --- | --- | --- |
| **Before fix** (published `3.6.0`): `agent({ integrations:
[connectToMCPServer({command:"npx", args:[…filesystem MCP…]})] })` run
on live Browserbase | `TypeError: Converting circular structure to JSON
… at V3.agent` — crashes **before** the agent starts. Reproduced on a
**second** MCP server (`@modelcontextprotocol/server-everything`) → not
server-specific. | Proves the bug and that it's general to any `Client`
integration. |
| **After fix** (local build copied into a scratch project), same script
on live Browserbase | exit 0, **no circular error**; agent connected to
the MCP server (`Secure MCP Filesystem Server running on stdio`) and
**invoked its tools** (got a real tool response). | Proves the fix
unblocks `agent({ integrations: [client] })` end-to-end. |
| `pnpm build:esm` (core) + grep built `v3.js` | build exit 0; built
output contains the safe descriptor, no
`JSON.stringify(options.integrations)`. | Fix compiles and is present in
the artifact under test. |

> Note: server-side ingestion is irrelevant here — this is a pure
client-side serialization crash; the matrix exercises the exact throwing
call path before and after.

Closes STG-2405.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes a circular-JSON crash when creating an agent with MCP `Client`
integrations (e.g., from `connectToMCPServer`). We now log a safe
descriptor for `integrations`, so `agent({ integrations: [client] })`
works with local/stdio MCP servers across all modes. Addresses STG-2405.

<sup>Written for commit 01323a5.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2278?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
felipeofdev-ai pushed a commit to felipeofdev-ai/stagehand that referenced this pull request Aug 4, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @browserbasehq/stagehand@3.7.0

### Minor Changes

- [browserbase#2283](browserbase#2283)
[`871ca7e`](browserbase@871ca7e)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add
`context.setDomainPolicy({ allowedDomains: ["allowed.domain"] })` which
allows users to define a set of domains that are accessible to stagehand

- [browserbase#2274](browserbase#2274)
[`f31980f`](browserbase@f31980f)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add
`context.setDomainPolicy({blockedDomains: ["some.domain"]})` which
allows users to define a list of domains that will be blocked by
stagehand

### Patch Changes

- [browserbase#2305](browserbase#2305)
[`cd1daad`](browserbase@cd1daad)
Thanks [@shrey150](https://github.com/shrey150)! - Remove the noisy AI
SDK "system message in messages" warning logged on every hybrid/DOM
`agent.execute()` call.

- [browserbase#2328](browserbase#2328)
[`d287ff4`](browserbase@d287ff4)
Thanks [@miguelg719](https://github.com/miguelg719)! - Allow modelName
"auto" in the constructor and per-primitive model overrides when running
through the Stagehand API

- [browserbase#2294](browserbase#2294)
[`3938590`](browserbase@3938590)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! -
automatically close popups that violate user defined domain policy

- [browserbase#2298](browserbase#2298)
[`892701a`](browserbase@892701a)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Fix CUA
`keypress` actions to press key combinations as a single chord.

- [browserbase#2345](browserbase#2345)
[`21826c7`](browserbase@21826c7)
Thanks [@monadoid](https://github.com/monadoid)! - Repair malformed
UTF-16 snapshot text before it reaches model prompts.

- [browserbase#2306](browserbase#2306)
[`8dcef1b`](browserbase@8dcef1b)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Use the
screenshot provider's declared media type when sending CUA image
payloads. The `setScreenshotProvider` callback now returns
`ScreenshotProviderResult` (`{ base64, mediaType }`) instead of a bare
base64 string.

- [browserbase#2273](browserbase#2273)
[`93a23d3`](browserbase@93a23d3)
Thanks [@miguelg719](https://github.com/miguelg719)! - Add support for
the new `google/gemini-3.5-flash` computer-use tools model

- [browserbase#2278](browserbase#2278)
[`022d68f`](browserbase@022d68f)
Thanks [@shrey150](https://github.com/shrey150)! - Fix `TypeError:
Converting circular structure to JSON` when creating an agent with MCP
`integrations` that include a `Client` instance (e.g. a local/stdio
server from `connectToMCPServer`). The agent-creation log serialized the
raw `integrations` array, and a live MCP `Client` is circular. It now
logs a safe descriptor (URL strings kept, client instances summarized)
so `agent({ integrations: [client] })` works.

- [browserbase#2288](browserbase#2288)
[`bb5ffa6`](browserbase@bb5ffa6)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - clean up
cdp session event handlers on target detach

## @browserbasehq/stagehand-evals@2.0.4

### Patch Changes

- Updated dependencies
\[[`cd1daad`](browserbase@cd1daad),
[`d287ff4`](browserbase@d287ff4),
[`3938590`](browserbase@3938590),
[`892701a`](browserbase@892701a),
[`21826c7`](browserbase@21826c7),
[`8dcef1b`](browserbase@8dcef1b),
[`93a23d3`](browserbase@93a23d3),
[`871ca7e`](browserbase@871ca7e),
[`022d68f`](browserbase@022d68f),
[`bb5ffa6`](browserbase@bb5ffa6),
[`f31980f`](browserbase@f31980f)]:
    -   @browserbasehq/stagehand@3.7.0

## @browserbasehq/stagehand-server-v3@3.7.2

### Patch Changes

- Updated dependencies
\[[`cd1daad`](browserbase@cd1daad),
[`d287ff4`](browserbase@d287ff4),
[`3938590`](browserbase@3938590),
[`892701a`](browserbase@892701a),
[`21826c7`](browserbase@21826c7),
[`8dcef1b`](browserbase@8dcef1b),
[`93a23d3`](browserbase@93a23d3),
[`871ca7e`](browserbase@871ca7e),
[`022d68f`](browserbase@022d68f),
[`bb5ffa6`](browserbase@bb5ffa6),
[`f31980f`](browserbase@f31980f)]:
    -   @browserbasehq/stagehand@3.7.0
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.

2 participants