Skip to content

fix(transport): terminate MCP server process groups on shutdown#869

Open
anishesg wants to merge 1 commit intoanthropics:mainfrom
anishesg:fix/ph-issue-291
Open

fix(transport): terminate MCP server process groups on shutdown#869
anishesg wants to merge 1 commit intoanthropics:mainfrom
anishesg:fix/ph-issue-291

Conversation

@anishesg
Copy link
Copy Markdown

Summary

When the SDK spawns an MCP server process such as chrome-devtools-mcp (via npx), the CLI becomes the direct child but the MCP server and any grandchildren it opens (e.g. a Chrome browser) form a deeper process tree. On shutdown the SDK only terminated the CLI process, leaving those grandchildren as orphans.

Motivation/Context

The root cause is two-fold: the spawned CLI process was not isolated into its own process group, so there was no reliable handle on the full descendant tree; and the close() shutdown path only called terminate()/kill() on the single CLI process rather than the whole group. With npx as the launcher this is especially visible because npx itself exits quickly after handing off to the real server, making signal propagation to grandchildren impossible without process-group targeting.

Changes

  • src/claude_agent_sdk/_internal/transport/subprocess_cli.py
    • Added import signal and import sys.
    • Pass start_new_session=True to anyio.open_process() on non-Windows platforms. This calls setsid() in the child, making the CLI the leader of a new process group that all of its descendants (MCP servers, browsers, etc.) inherit.
    • Added _terminate_process_group() helper: sends SIGTERM to the whole process group via os.killpg() on POSIX, falls back to process.terminate() on Windows.
    • Added _kill_process_group() helper: sends SIGKILL to the whole process group via os.killpg() on POSIX, falls back to process.kill() on Windows.
    • Updated close() to call the new helpers in the graceful-shutdown timeout path instead of calling terminate()/kill() on just the CLI process.
  • fix(transport): terminate MCP server process groups on shutdown to prevent orphaned child processes (e.g. browsers opened by chrome-devtools-mcp)

Fixes #291

## Summary

Signed-off-by: anish k <ak8686@princeton.edu>
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.

The sdk should clean up mcp servers it launches on exit

1 participant