Skip to content

fix: remove stdin listeners from lifecycle guard to prevent MCP -32000 errors#237

Open
ponythewhite wants to merge 1 commit intomksglu:mainfrom
ponythewhite:fix/lifecycle-stdin-conflict
Open

fix: remove stdin listeners from lifecycle guard to prevent MCP -32000 errors#237
ponythewhite wants to merge 1 commit intomksglu:mainfrom
ponythewhite:fix/lifecycle-stdin-conflict

Conversation

@ponythewhite
Copy link
Copy Markdown

@ponythewhite ponythewhite commented Apr 7, 2026

Summary

  • Removes process.stdin.resume() and end/close/error listeners from the lifecycle guard (src/lifecycle.ts)
  • These listeners conflict with MCP SDK's StdioServerTransport, which also reads from process.stdin via readline
  • Transient stdin events cause false-positive parent-death detection → immediate process.exit(0) → client receives MCP error -32000: Connection closed

Root Cause

The lifecycle guard (added in #103) registers stdin listeners to detect parent death. However, in an MCP stdio transport, StdioServerTransport is the rightful owner of process.stdin. Two consumers competing for the same stream causes:

  1. process.stdin.resume() puts stdin into flowing mode before the transport is ready, risking data loss during handshake
  2. end/close/error listeners fire on transient pipe events that don't indicate actual parent death, triggering immediate shutdown with no grace period

What's Preserved

Parent death detection remains robust via:

  • ppid polling (every 30s) — detects reparenting to init/systemd/launchd
  • SIGTERM/SIGINT/SIGHUP signal handlers — catch intentional shutdown

Test Plan

  • Verify MCP server starts and responds to tool calls normally
  • Verify server exits when parent Claude Code session ends (ppid check + signals)
  • Confirm no more spurious -32000: Connection closed errors during extended sessions
  • Run existing test suite if available

Fixes #236

🤖 Generated with Claude Code

…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) <[email protected]>
@mksglu
Copy link
Copy Markdown
Owner

mksglu commented Apr 7, 2026

CI is throw error. @ponythewhite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lifecycle guard stdin listeners cause spurious MCP -32000 Connection closed

2 participants