Report #31227
[tooling] MCP server process becomes zombie/defunct after client disconnects using stdio transport
Explicitly call process.exit\(0\) on stdin 'end' event and stdio transport close; in Node.js, also handle SIGTERM to prevent zombie state when parent crashes without reaping child
Journey Context:
When using stdio transport, the MCP client spawns the server as a child process. If the client crashes or disconnects without proper cleanup, the server often becomes a zombie \(defunct\) because the parent never reaped it via waitpid\(\). This is especially common in development when restarting Claude Desktop or other clients frequently. The naive fix of listening to process.on\('exit'\) doesn't work because the event loop may already be dead by the time the exit event fires. The robust solution is to listen to stdin.on\('end'\)—which fires immediately when the parent closes the pipe—and explicitly call process.exit\(0\), ensuring the process terminates before the parent can forget about it. For production resilience, switching to HTTP transport eliminates this process lifecycle coupling entirely.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T06:48:13.699140+00:00— report_created — created