/kill-stale-mcp
npx-launched MCP servers leak. The launch chain is npm exec <server>@... → server → (sometimes) a telemetry watchdog. When a session ends uncleanly, the termination signal stops at the npm exec wrapper — npx does not forward it to its children — so the whole group keeps running. Every dead session leaves one group behind (~100–250 MB each).
This skill kills the stale groups and keeps the live ones.
Staleness test: a live group's npm exec wrapper is parented to a running host process (Claude Code, an IDE extension host). When the host dies, the orphaned processes are re-parented to PID 1 (launchd on macOS, init/systemd on Linux). PPID 1 → stale. PPID = a live host → in use, keep.
Steps
List every MCP-related process with its parent PID:
ps -eo pid,ppid,lstart,command | grep -i mcp | grep -v grepClassify each process:
- Not ours — never touch: anything owned by an IDE or app rather than launched via npx (e.g. Cursor
mcp-process, GitLens/GitKrakengk mcp, Electron app helpers). Only handle processes whose command containsnpm execor a~/.npm/_npx/path, plus their direct children. - Stale: an npx-launched process with
PPID 1; or a watchdog whose--parent-pid=<N>is dead (check withkill -0 <N>). - Live: the wrapper's PPID is a running session process. Keep the whole group.
- Not ours — never touch: anything owned by an IDE or app rather than launched via npx (e.g. Cursor
Kill the stale PIDs explicitly (never
pkill -f mcp— that would take down live sessions' servers and IDE-owned processes):kill <stale pids...>Re-run the listing from step 1. Killing a wrapper re-parents its children to PID 1, so they now show up as stale themselves — repeat step 3 until no npx-launched process with PPID 1 remains.
Report: how many groups were killed (with spawn times) and which live groups were kept.
Notes
- Live servers respawn on demand the next time a session uses them — this skill removes leaked instances, it does not disable any MCP.
- Root cause is npx signal handling. If one server leaks constantly, launch it directly by its bin path in the MCP config instead of via
npx.