Skip to content

fix(brainstormer): isolate the SDK session from the operator's global MCP config#448

Merged
hadamrd merged 1 commit into
trunkfrom
fix/brainstormer-mcp-isolation
Jun 10, 2026
Merged

fix(brainstormer): isolate the SDK session from the operator's global MCP config#448
hadamrd merged 1 commit into
trunkfrom
fix/brainstormer-mcp-isolation

Conversation

@hadamrd

@hadamrd hadamrd commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Bug

forge-loop brainstorm hung at SDK-session init ("Control request timeout: initialize") on any box where the operator's global Claude config registers MCP servers — or where the target repo's .claude config registers servers needing live backends (hit 100% on getadaptiq, whose adaptiq-tutor MCP needs the backend running).

Root cause

Brainstormer.run() called the SDK shim with only cwd/timeout_s/model. The MCP-isolation knobs the worker path has used since the early dogfood runs (strict_mcp_config, mcp_servers, load_timeout_ms — see settings.WorkerSettings) were never plumbed through the brainstormer, so its session enumerated the full global MCP config at init.

Fix

The brainstormer needs zero MCP servers — the backlog scan happens in-process before the session, and the session only reads the repo + emits the JSON report. So:

  • Brainstormer dataclass defaults: strict_mcp_config=True, mcp_servers={}, load_timeout_ms=180000 (mirrors worker defaults).
  • run() passes the knobs to sdk_fn.
  • Codex backend absorbs/ignores them (no MCP handshake in codex exec).

Tests

  • New regression test test_sdk_session_is_mcp_isolated_by_default (fails on trunk, passes here).
  • tests/test_brainstormer.py: 44 passed. tests/test_cli_brainstorm.py + SDK suites: green.
  • ⚠️ tests/test_critic_sdk.py has 5 pre-existing failures on trunk — verified identical on a clean origin/trunk worktree; untouched by this diff.
  • E2E: forge-loop brainstorm on getadaptiq (previously 100% init-timeout) — verification run in progress on the operator box.

🤖 Generated with Claude Code

… MCP config

The brainstormer never passed strict_mcp_config / mcp_servers /
load_timeout_ms to its SDK session, so the session enumerated every MCP
server in the operator's global Claude config — plus any servers the
TARGET repo's .claude config registers (which may need live backends) —
and died on "Control request timeout: initialize" before producing a
report. The worker path has defended against exactly this since the
early dogfood runs (see settings.WorkerSettings); the brainstormer was
left out.

The brainstormer needs ZERO MCP servers: the backlog scan happens
in-process before the session starts, and the session itself only reads
the repo and emits the JSON report. Default the Brainstormer dataclass
to strict isolation (strict_mcp_config=True, mcp_servers={},
load_timeout_ms=180000), pass the knobs through run() → sdk_fn, and
absorb them in the codex backend (no MCP handshake there).

Repro: `forge-loop brainstorm` on a repo whose .claude registers an
MCP server backed by a non-running service — times out at init 100%.

Note: tests/test_critic_sdk.py has 5 pre-existing failures on trunk
(verified on a clean origin/trunk worktree); untouched by this diff.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hadamrd hadamrd merged commit 4687daa into trunk Jun 10, 2026
2 checks passed
@hadamrd hadamrd deleted the fix/brainstormer-mcp-isolation branch June 10, 2026 12:40
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