Environment: @swmansion/argent 0.11.0, Node v24.12.0 (nvm), macOS 26.5, Apple Silicon
Bug
When the argent mcp process that first spawns tool-server.cjs exits (e.g. its MCP client is a short-lived headless run that finishes), the tool-server does not exit. It re-parents to launchd (ppid 1) and runs indefinitely. There appears to be no parent-death detection (stdin EOF / ppid watchdog) and no idle timeout.
Repro (verified)
- Ensure no
tool-server.cjs start process is running:
ps -Ao pid,ppid,command | grep '[t]ool-server.cjs' → empty.
- In a directory whose
.mcp.json registers argent as a stdio server:
{"mcpServers":{"argent":{"type":"stdio","command":"argent","args":["mcp"]}}}
- Run any short-lived MCP client from that directory, e.g.:
echo "say hi" | claude -p --model haiku --output-format text
- After the client exits:
ps -Ao pid,ppid,command | grep '[t]ool-server.cjs' shows a tool-server with ppid 1 that never exits.
Why it's intermittent
If a tool-server already exists, a new argent mcp reuses it and exits cleanly — no leak. Only the client that first spawns the tool-server orphans it.
Additionally, spawn is not mutually exclusive: multiple argent mcp processes starting concurrently each spawn their own tool-server (we observed 4 simultaneous spawns within the same second after killing the existing one). Combined with the missing cleanup, automation that repeatedly launches short-lived MCP clients accumulates orphans over time.
Real-world impact
An automation daemon on my machine invoked headless claude -p ~2×/minute in a project with argent configured. Within hours: 123 orphaned tool-servers and, with simulators in use, 330 concurrent simctl/CoreSimulator processes, load average 445, memory exhausted — the machine was barely usable (~30% system CPU from simctl spawning alone).
With no simulator booted an orphan idles cheaply (it just never exits); the simctl storm occurs when simulators are in use.
Suggested fixes
- tool-server exits when its last client disconnects (stdin/IPC EOF), and/or watches
process.ppid and exits when re-parented to 1, and/or an idle TTL;
argent mcp reaps the tool-server it spawned on shutdown;
- serialize tool-server spawn (lockfile / port probe) so concurrent clients can't each create one.
Any one of the first group would cap the damage; spawn serialization would make the leak self-limiting even if cleanup fails.
Workaround for anyone hitting this: kill orphans with
for pid in $(ps -Ao pid,ppid,command | awk '/argent\/dist\/tool-server/ && $2 == 1 {print $1}'); do kill $pid; done
and pass --strict-mcp-config --mcp-config '{"mcpServers":{}}' to headless claude -p runs that don't need tools.
Environment:
@swmansion/argent0.11.0, Node v24.12.0 (nvm), macOS 26.5, Apple SiliconBug
When the
argent mcpprocess that first spawnstool-server.cjsexits (e.g. its MCP client is a short-lived headless run that finishes), the tool-server does not exit. It re-parents to launchd (ppid 1) and runs indefinitely. There appears to be no parent-death detection (stdin EOF / ppid watchdog) and no idle timeout.Repro (verified)
tool-server.cjs startprocess is running:ps -Ao pid,ppid,command | grep '[t]ool-server.cjs'→ empty..mcp.jsonregisters argent as a stdio server:{"mcpServers":{"argent":{"type":"stdio","command":"argent","args":["mcp"]}}}echo "say hi" | claude -p --model haiku --output-format textps -Ao pid,ppid,command | grep '[t]ool-server.cjs'shows a tool-server with ppid 1 that never exits.Why it's intermittent
If a tool-server already exists, a new
argent mcpreuses it and exits cleanly — no leak. Only the client that first spawns the tool-server orphans it.Additionally, spawn is not mutually exclusive: multiple
argent mcpprocesses starting concurrently each spawn their own tool-server (we observed 4 simultaneous spawns within the same second after killing the existing one). Combined with the missing cleanup, automation that repeatedly launches short-lived MCP clients accumulates orphans over time.Real-world impact
An automation daemon on my machine invoked headless
claude -p~2×/minute in a project with argent configured. Within hours: 123 orphaned tool-servers and, with simulators in use, 330 concurrentsimctl/CoreSimulator processes, load average 445, memory exhausted — the machine was barely usable (~30% system CPU from simctl spawning alone).With no simulator booted an orphan idles cheaply (it just never exits); the simctl storm occurs when simulators are in use.
Suggested fixes
process.ppidand exits when re-parented to 1, and/or an idle TTL;argent mcpreaps the tool-server it spawned on shutdown;Any one of the first group would cap the damage; spawn serialization would make the leak self-limiting even if cleanup fails.
Workaround for anyone hitting this: kill orphans with
for pid in $(ps -Ao pid,ppid,command | awk '/argent\/dist\/tool-server/ && $2 == 1 {print $1}'); do kill $pid; doneand pass
--strict-mcp-config --mcp-config '{"mcpServers":{}}'to headlessclaude -pruns that don't need tools.