fix(transport): terminate MCP server process groups on shutdown#869
Open
anishesg wants to merge 1 commit intoanthropics:mainfrom
Open
fix(transport): terminate MCP server process groups on shutdown#869anishesg wants to merge 1 commit intoanthropics:mainfrom
anishesg wants to merge 1 commit intoanthropics:mainfrom
Conversation
## Summary Signed-off-by: anish k <ak8686@princeton.edu>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When the SDK spawns an MCP server process such as
chrome-devtools-mcp(vianpx), 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 calledterminate()/kill()on the single CLI process rather than the whole group. Withnpxas the launcher this is especially visible becausenpxitself 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.pyimport signalandimport sys.start_new_session=Truetoanyio.open_process()on non-Windows platforms. This callssetsid()in the child, making the CLI the leader of a new process group that all of its descendants (MCP servers, browsers, etc.) inherit._terminate_process_group()helper: sendsSIGTERMto the whole process group viaos.killpg()on POSIX, falls back toprocess.terminate()on Windows._kill_process_group()helper: sendsSIGKILLto the whole process group viaos.killpg()on POSIX, falls back toprocess.kill()on Windows.close()to call the new helpers in the graceful-shutdown timeout path instead of callingterminate()/kill()on just the CLI process.Fixes #291