Skip to content

fix(mcp): spawn bundled MCP servers on pull_request events#1261

Open
MukundaKatta wants to merge 1 commit intoanthropics:mainfrom
MukundaKatta:fix/mcp-spawn-pull-request
Open

fix(mcp): spawn bundled MCP servers on pull_request events#1261
MukundaKatta wants to merge 1 commit intoanthropics:mainfrom
MukundaKatta:fix/mcp-spawn-pull-request

Conversation

@MukundaKatta
Copy link
Copy Markdown

Why

Closes #1245. On pull_request events with the action's bundled MCP servers, the spawned Claude CLI's session init reports mcp_servers: [] and mcp__github_comment__update_claude_comment (and friends) are unavailable, so the tracking comment never updates. The action's tag-mode plumbing is correct: it builds the JSON via prepareMcpConfig, escapes it into --mcp-config '{...}' inside claudeArgs, and parseClaudeArgsToExtraArgs keeps it in extraArgs["mcp-config"] — but the spawned binary doesn't end up registering those servers. Same shape reported in #1191 for an external (Notion) MCP server passed inline.

The cleanest fix is to bypass the brittle stringified-JSON CLI hop: route inline --mcp-config JSON to Options.mcpServers (the SDK's typed in-process registration path used by Anthropic's own SDK demos) and let only file-path values continue through the CLI flag.

What

base-action/src/parse-sdk-options.ts:

  • New splitMcpConfigs() returns { inlineServers, filePath } from accumulated --mcp-config values (replaces mergeMcpConfigs()).
  • After flag accumulation, lift parsed inline mcpServers onto sdkOptions.mcpServers. Drop extraArgs["mcp-config"] when the only values were inline JSON; keep it when the user also passed a file path.
  • Inline-JSON merge order is unchanged (later flags override earlier on key conflict), so user inline JSON still wins over action-prepended bundled servers.
  • File-path forwarding is unchanged: the CLI loads it and merges with whatever the SDK already registered.

base-action/test/parse-sdk-options.test.ts: rewrites the mcp-config block to assert the new routing — inline JSON lands on sdkOptions.mcpServers, file paths stay in extraArgs["mcp-config"], mixed inputs split cleanly. Adds a mcpServers === undefined case.

No changes to src/mcp/install-mcp-server.ts, src/modes/tag/index.ts, or src/modes/agent/index.ts — those keep building the same --mcp-config '{...}' string. The fix lives entirely in the parsing layer.

Tested

  • bun test base-action/test/parse-sdk-options.test.ts — 28 pass, 0 fail. New 8-test mcp-config routing block covers single inline, multi-inline merge, three-way merge, file-path-only, mixed inline+file, inline-with-other-flags, the bug-report scenario (action + user inline), and the no-mcp-config case.
  • Full repo bun test — 665/666 pass. The single failure is validate-env > Direct Anthropic API > should fail when ANTHROPIC_API_KEY is missing in my local shell because CLAUDE_CODE_OAUTH_TOKEN is set in env, unrelated to this change. CI will run with a clean env.

Manual repro for the original bug is the workflow in #1245 (pull_request event, default config, track_progress: true). With this change, the bundled github_comment/github_ci/github_file_ops servers appear in mcp_servers on session init and the tracking comment updates as expected.

The action prepends its bundled MCP servers (github_comment, github_ci,
github_inline_comment, github_file_ops, optional github) as a single
`--mcp-config '{...}'` flag inside claudeArgs. Earlier this stayed in
extraArgs["mcp-config"] for the SDK to forward to the spawned Claude
CLI subprocess. Multiple users have reported that the spawned CLI's
session init reports `mcp_servers: []` even though extraArgs is
correctly populated, so the bundled servers silently never register
and the action falls back to denying tools like
mcp__github_comment__update_claude_comment.

Lift inline JSON --mcp-config values onto sdkOptions.mcpServers — the
SDK's typed, in-process registration path used by Anthropic's own SDK
demos. File-path --mcp-config values stay in extraArgs so the CLI
loads and merges them alongside what the SDK already registered. User
inline JSON merges with action-prepended servers exactly like before,
with later flags winning on key conflict.

Closes anthropics#1245
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.

Bundled MCP servers silently fail to spawn on pull_request events (mcp_servers empty despite correct config build)

1 participant