[BUG] Concurrent subagents with byte-identical inline mcpServers configs share one MCP server process/session, breaking per-subagent isolation

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 1 comment Β· opened Aug 6, 2026

πŸ€– Generated with Claude Code

Summary

Concurrent subagents whose agent definitions declare byte-identical inline mcpServers configs are deduplicated onto one shared stdio server process and one MCP session, instead of each subagent getting its own connection. The dedup keys on config content, not on the spawning subagent β€” two different agent types with identical configs still share one server.

This contradicts the shipped behavior described in #4476, where inline frontmatter servers are "Connected only when that subagent starts / Disconnected and cleaned up when the subagent finishes" β€” the example there is literally Playwright scoped to a browser-tester agent, which is exactly the case that breaks.

Environment

  • Claude Code 2.1.220 and 2.1.223 (native binary), macOS (darwin 25.5.0)
  • Reproduced headless (-p) and interactive

Reproduction

  1. Create two agent definitions expa.md / expb.md in .claude/agents/, identical except for name, both declaring the same inline stdio MCP server (any server; a trivial logging server that records its PID and every JSON-RPC line makes the sharing visible):
---
name: expa
description: Experiment agent A
model: sonnet
mcpServers:
  - logserver:
      type: stdio
      command: /path/to/logsrv.js
---
  1. In one session, spawn both agents concurrently via the Agent tool; have each call an MCP tool 5 times.

Observed

One server process serves both agents (two independent runs):

run 1: startup pids: [73844]  calls per pid: {73844: 10}   # 5 from each agent, one initialize handshake
run 2: startups: [(74517, ...)]  call pids: {74517}  ncalls: 10

Calls from both agents interleave on the single session:

21:03:03.286Z expa-1
21:03:04.331Z expb-1
21:03:05.868Z expa-2
21:03:06.949Z expb-2
...

Expected

Each subagent gets its own server process and MCP session, per the #4476 design ("connected when the subagent starts, disconnected when it finishes").

Real-world impact

With @playwright/mcp as the inline server, all concurrent subagents land in one browser context and one contested tab list β€” every browser_navigate retargets the shared tab and parallel agents clobber each other, --isolated notwithstanding (its isolation boundary is the MCP session, which is the thing that got collapsed). This is microsoft/playwright-mcp#893, which the Playwright maintainers punted back to Claude Code ("Claude is responsible for agents, subagents"), and the downstream cross-client bleed is microsoft/playwright-mcp#1631.

Workaround (and evidence for the keying)

Making each agent definition's server config byte-distinct β€” a per-agent server name plus a dummy argv difference β€” restores one process per concurrent agent (verified at 5Γ— concurrency: five agents, five processes, no cross-visibility). Normalizing the configs back to identical silently reintroduces the shared session, so the dedup key is demonstrably the config content.

Related

  • #4476 β€” the shipped spec this contradicts
  • #49372, #74635, #75207 β€” same content-keyed-dedup defect class at other boundaries (HTTP URL, serverInfo name/version)
  • #28126 β€” the opposite behavior on Windows (per-subagent duplicate servers), suggesting the platforms diverge here

View original on GitHub β†—

This issue has 1 comment on GitHub. Read the full discussion on GitHub β†—