Skip to content

caveman-shrink never forwards SIGTERM/SIGINT to its spawned upstream server, orphaning it #742

Description

@AmirF194

What happen

caveman-shrink (the MCP proxy that wraps an upstream MCP server and compresses tool
descriptions) never forwards SIGTERM/SIGINT to the upstream process it spawned. If
something tears down the caveman-shrink process directly with a signal (an MCP host
ending a session, disabling a tool, reloading config) instead of killing a whole
process group, the wrapped upstream server is left running, reparented to PID 1,
indefinitely.

src/mcp-servers/caveman-shrink/index.js only registers handlers for the child's own
exit/error events:

const upstream = spawn(args[0], args.slice(1), getSpawnOptions());

upstream.on('error', err => { ... });
upstream.on('exit', (code, signal) => { ... });

There is no process.on('SIGTERM', ...) / process.on('SIGINT', ...) on the parent to
forward the signal (or kill the child) before exiting.

Expected

Sending SIGTERM to the caveman-shrink process should also stop the upstream child it
spawned, not leave it running orphaned.

Repro

# fake long-running upstream (never exits on its own)
cat > /tmp/fake-upstream.js <<'EOF'
process.stdin.resume();
setInterval(() => {}, 1000000);
EOF

node src/mcp-servers/caveman-shrink/index.js node /tmp/fake-upstream.js &
WRAPPER_PID=$!
sleep 1
kill -TERM $WRAPPER_PID
sleep 1
ps -o pid,ppid,stat,args

Verified today in a clean node:20-alpine container against current main
(0d95a81): the wrapper process becomes a zombie, and
the fake-upstream process is still alive with PPID 1 (reparented, orphaned), never
having received a signal.

Platform

  • Claude Code
  • Codex
  • Other: any MCP host wrapping a server via caveman-shrink (not agent-specific)

Version / install method

main @ 0d95a81d, ran the script directly from the repo (not through the packaged
installer).

Happy to send a PR (forward SIGTERM/SIGINT to the child, mirroring the existing
upstream.on('exit', ...) handling) if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions