fix: remove stdin listeners from lifecycle guard to prevent MCP -32000 errors#237
fix: remove stdin listeners from lifecycle guard to prevent MCP -32000 errors#237ponythewhite wants to merge 1 commit intomksglu:mainfrom
Conversation
…0 errors The lifecycle guard's process.stdin.resume() and end/close/error listeners conflict with MCP SDK's StdioServerTransport, which also reads from stdin via readline. Transient stdin events trigger false-positive parent-death detection, causing immediate process.exit(0) and "MCP error -32000: Connection closed" on the client side. Parent death is still reliably detected via ppid polling (every 30s) and OS signal handlers (SIGTERM/SIGINT/SIGHUP). Fixes mksglu#236 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
CI is throw error. @ponythewhite |
…rors The lifecycle guard registered end/close/error listeners on process.stdin and called process.stdin.resume(). This conflicted with StdioServerTransport, which owns the same stream via readline. Transient pipe events triggered gracefulShutdown() → process.exit(0), so the MCP client logged "MCP error -32000: Connection closed" multiple times per hour during normal sessions. Remove the stdin-based shutdown path entirely. ppid polling every 30s plus SIGTERM/SIGINT/SIGHUP handlers still guarantee the orphan protection added in mksglu#103. Update tests/lifecycle.test.ts so the integration test asserts the new contract: stdin close must NOT shut the guard down. The previous positive assertion is what made PR mksglu#237 fail CI on Ubuntu/macOS. Supersedes mksglu#237. Closes mksglu#236. Co-authored-by: ponythewhite <ponythewhite@users.noreply.github.com> Co-authored-by: Ercan Ermis <eposta@ercanermis.com>
|
Opened a replacement PR that keeps this diff verbatim and also updates |
…rors (#236) The lifecycle guard registered end/close/error listeners on process.stdin and called process.stdin.resume(). This conflicted with StdioServerTransport, which owns the same stream via readline. Transient pipe events triggered gracefulShutdown() → process.exit(0), so the MCP client logged "MCP error -32000: Connection closed" multiple times per hour during normal sessions. Remove the stdin-based shutdown path entirely. ppid polling every 30s plus SIGTERM/SIGINT/SIGHUP handlers still guarantee the orphan protection added in #103. Update tests/lifecycle.test.ts so the integration test asserts the new contract: stdin close must NOT shut the guard down. The previous positive assertion is what made PR #237 fail CI on Ubuntu/macOS. Supersedes #237. Closes #236. Co-authored-by: ponythewhite <ponythewhite@users.noreply.github.com>
…rors (#236) Cherry-pick from main (bfbf654). Original PR #255 by contributor, superseding #237 by @ponythewhite. Removes process.stdin.resume() and end/close/error listeners from lifecycle guard. These conflicted with StdioServerTransport causing false-positive parent-death detection and -32000 errors. ppid polling + OS signals remain as orphan detection mechanisms. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hey @ponythewhite — thank you for this! You nailed the root cause: stdin listeners in the lifecycle guard conflict with MCP SDK's StdioServerTransport, causing spurious -32000 errors. We shipped the same fix on
The lifecycle guard now uses only ppid polling + OS signals (SIGTERM/SIGINT/SIGHUP), exactly as you proposed.
Closing since this is already on |
Summary
process.stdin.resume()andend/close/errorlisteners from the lifecycle guard (src/lifecycle.ts)StdioServerTransport, which also reads fromprocess.stdinviareadlineprocess.exit(0)→ client receivesMCP error -32000: Connection closedRoot Cause
The lifecycle guard (added in #103) registers stdin listeners to detect parent death. However, in an MCP stdio transport,
StdioServerTransportis the rightful owner ofprocess.stdin. Two consumers competing for the same stream causes:process.stdin.resume()puts stdin into flowing mode before the transport is ready, risking data loss during handshakeend/close/errorlisteners fire on transient pipe events that don't indicate actual parent death, triggering immediate shutdown with no grace periodWhat's Preserved
Parent death detection remains robust via:
Test Plan
-32000: Connection closederrors during extended sessionsFixes #236
🤖 Generated with Claude Code