[BUG] MCP servers not properly terminated when Claude Code exits, causing orphaned processes
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other:
- Claude CLI version: 1.0.18 (Claude Code)
- Operating System: macOS Darwin 24.5.0
- Terminal: Terminal/zsh
Bug Description
Claude Code does not properly clean up MCP server processes when exiting, leading to orphaned processes that continue consuming system resources indefinitely. These processes accumulate over multiple sessions and are not cleaned up even when MCP servers are removed from configuration.
Steps to Reproduce
- Configure one or more MCP servers using
claude mcp add <name> <command> - Start Claude Code and use it normally (any session that might initialize MCP servers)
- Exit Claude Code normally
- Check running processes with
ps aux | grep mcp - Observe orphaned MCP server processes still running
- Optional: Try
claude mcp remove <name>- processes still persist
Expected Behavior
MCP server processes should be gracefully terminated when Claude Code exits. All spawned MCP server processes should be cleaned up, leaving no orphaned processes consuming system resources.
Actual Behavior
MCP server processes remain running as orphaned processes after Claude Code exits. These processes:
- Continue consuming system resources (CPU, memory)
- Accumulate over time with each Claude Code session
- Are not cleaned up even when running
claude mcp remove <server-name> - Persist across system restarts in some cases
Additional Context
Evidence from testing:
- Found 40+ orphaned MCP server processes from previous Claude Code sessions
- Processes dating back several days (some running since Monday/Tuesday)
- Process types include:
- Docker containers:
docker run -i --rm mcp/time,mcp/github,mcp/memory, etc. - Python processes:
chroma-mcp,cli-mcp-server - Node.js processes:
context7-mcp
- Docker containers:
Example orphaned processes (sanitized): user 90260 0.0 0.0 411858096 12272 s001 S+ 11:19AM 0:00.56 docker run -i --rm mcp/time user 88027 0.0 0.0 411869888 12224 ?? S 11:18AM 0:00.53 docker run -i --rm mcp/time user 54415 0.0 0.0 411896512 4576 ?? S Tue12PM 0:02.82 docker run -i --rm mcp/time user 90680 0.0 0.0 411871728 10912 ?? S Mon11AM 0:04.81 docker run -i --rm mcp/time user 54413 0.0 0.0 411889136 4080 ?? S Tue12PM 0:02.74 docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN=*** mcp/github user 54418 0.0 0.0 411896816 4128 ?? S Tue12PM 0:02.85 docker run --rm -i --mount type=bind,src=/Users/user/Projects/workspace,dst=/projects/workspace mcp/git
Impact:
- Resource leak with long-running orphaned processes
- Potential system performance degradation over time
- User confusion when debugging MCP server issues
- Accumulating Docker containers consuming disk space
Potential root cause: The MCP protocol specification includes a graceful shutdown phase, but Claude Code appears to not properly invoke cleanup handlers during application exit to terminate spawned MCP server child processes.
We have a fix on the way!
This should be fixed in 1.0.21. Thanks for reporting @noomz!
I am on version 1.0.27 and seem to have this same issue. I have dozens of node processes. I am on the developer beta of macOS, is that an issue?
I can confirm this issue still exists on Claude Code v1.0.31 with a custom MCP server. Additional context: The same custom MCP server is properly cleaned up when used with GitHub Copilot (process terminates correctly when stopping the server), which indicates that:
My MCP server correctly handles SIGINT termination signals The issue is specific to Claude Code's MCP process management, not a general MCP server problem
This suggests Claude Code is not sending the proper termination signals to MCP server child processes on exit, while other MCP clients (like GitHub Copilot) handle this correctly. Environment:
Claude Code version: v1.0.31 MCP Server: Custom server (properly handles SIGINT as verified with GitHub Copilot) Platform: macOS 15.5
The bug persists across multiple versions (original report was v1.0.18), indicating this hasn't been resolved yet.
Same with v1.0.35. MCP server is a docker container that is persisted until I shut it down and delete it. A new container is instantiated with each call to claude command.
Thanks, we'll look into this again.
Hi all, please update to 1.0.38 and let me know if the issue persists. This should be much more robust now.
Checking in here. Is this working for everyone? @CoreyWinkelmannPP @mstllc @noomz
@ashwin-ant working for me on macOS 26 and Claude Code 1.0.43. Love CC, keep up the great work!
@ashwin-ant This is happening for me on 1.0.51. My MCP server handles SIGINT fine if I launch it directly with npx, but not when I use the same npx command in .mcp.json with claude code. It does work if I configure the mcp server to launch directly from node_modules/.bin/the-bin instead of via npx / pnpm dlx.
As far as I can tell, claude is sending two back-to-back SIGINT signals, then waits 90ms, and then sends two back-to-back SIGTERM signals. For some reason when running through a wrapper like npx it seems like this isn't enough time and my actual MCP server doesn't get the SIGINT signal.
Actually, even running the binary directly via the binary in node_modules doesn't work when claude is run in --print mode. I can't get claude to kill my MCP server process at all when run in --print mode.
@ashwin-ant I did some digging, it looks like when run in --print mode, claude code isn't sending SIGINT or SIGTERM to my MCP server, it's just closing the stdin stream which leaves the MCP server running if there were any other active handlers
@sbking nice catch on --print mode! We have a fix on the way. Are you seeing this in interactive mode too still?
Still seeing this in interactive mode on latest version 1.0.73 (Windows)
Still seeing this happening in 1.0.84
Still seeing this happening in 1.0.85
Still seeing this on v2.0.29