-
Notifications
You must be signed in to change notification settings - Fork 59
Description
Description
The MCP server wrapper's signal handling is incomplete, causing mcp-server.js processes to become orphaned when Claude sessions end through terminal closure, crashes, or SIGKILL.
Observed Behavior
After normal usage, multiple orphaned episodic-memory processes accumulate:
$ ps aux | grep episodic-memory
user 87483 node .../episodic-memory/1.0.15/dist/mcp-server.js
user 87466 node .../episodic-memory/1.0.15/cli/mcp-server-wrapper.js
user 8516 node .../episodic-memory/1.0.15/dist/mcp-server.js
user 8515 node .../episodic-memory/1.0.15/cli/mcp-server-wrapper.js
user 7064 node .../episodic-memory/1.0.15/dist/mcp-server.js
user 7062 node .../episodic-memory/1.0.15/cli/mcp-server-wrapper.js
# ... accumulates over timeEach Claude session spawns a new pair of processes. Old ones don't terminate.
Root Cause
In cli/mcp-server-wrapper.js (lines 84-86), only SIGTERM and SIGINT are handled:
process.on('SIGTERM', () => child.kill('SIGTERM'));
process.on('SIGINT', () => child.kill('SIGINT'));What's missing:
-
No SIGHUP handler - When terminal windows are closed, the shell sends SIGHUP, not SIGTERM. This signal is ignored.
-
No stdin close detection - MCP servers communicate via stdio. When the parent Claude process dies unexpectedly, stdin closes, but neither the wrapper nor the server detects this.
-
No parent process monitoring - If Claude is killed with
kill -9, no signal is sent to children. They become orphaned with no way to know their parent died.
Failure scenarios:
| Scenario | Signal sent | Result |
|---|---|---|
| Close terminal tab/window | SIGHUP | Ignored → orphan |
| Claude crashes | None | No cleanup → orphan |
kill -9 Claude |
None | No cleanup → orphan |
Normal /exit |
SIGTERM | Works correctly ✓ |
Proposed Fix
Add to cli/mcp-server-wrapper.js after line 86:
// Handle terminal hangup (closing terminal window)
process.on('SIGHUP', () => child.kill('SIGHUP'));
// Detect parent process death via stdin close
process.stdin.on('end', () => {
child.kill();
process.exit(0);
});And optionally add to src/mcp-server.ts as a fallback:
// Detect parent death if wrapper fails to forward
process.stdin.on('end', () => process.exit(0));Environment
- episodic-memory: 1.0.15
- Claude Code: 2.1.22
- OS: macOS (Darwin 25.2.0)
- Node.js: v24.11.1
Workaround
Users can periodically clean up orphaned processes:
pkill -f "episodic-memory"The current session will respawn its server when needed.
Impact
Over time, orphaned processes consume memory and system resources. Users may notice system slowdown without understanding the cause.