OpenClaw MCP Subprocess Orphans on Rented Mac mini: Exit Hygiene & launchd Recovery (2026-05-19)
Teams running OpenClaw with Model Context Protocol (MCP) stdio servers on rented Mac mini M4 hosts in Hong Kong, Japan, Korea, Singapore, or the United States sometimes see RSS climb while traffic is idle, duplicate node binaries, or stuck tool calls after a gateway upgrade. This May 19, 2026 field note explains how those symptoms differ from JSON stalls, gives a five-column operator matrix, walks a nine-step launchd-safe cleanup, and links to deeper guides on parallel agent concurrency, stdio buffering, and gateway restart recovery.
What “MCP orphans” look like before swap thrash
Orphaned MCP children are not theoretical: upstream issue traffic describes long-lived CLI processes where each extra Node child can retain on the order of tens of megabytes of RSS while the parent gateway has already moved on. On a single-tenant mini that difference shows up quickly because there is no hypervisor hiding your mistake—you own the full page cache and the launchd job graph.
- Process list drift:
pgrep -lf mcporpgrep -lf modelcontextprotocolreturns more rows after an overnight soak than after a cold boot, even when no human touched SSH. - Tool latency stair-steps: first calls succeed, later calls queue behind pipes that never EOF because a zombie reader still holds stdin open.
- Gateway version skew: you upgraded the CLI while an older gateway still supervises children spawned from the previous semver—signals may not propagate the way you expect.
- False “model outage”: dashboards show healthy provider latency while local tools time out; always check local
forkpressure before blaming the LLM.
Why stdio MCP is prone to sticky child trees
Stdio MCP is attractive on Apple Silicon because it avoids exposing random TCP ports, but the transport inherits POSIX semantics: any process that keeps a pipe write-end open prevents EOF on the read side, and npx-style bootstrappers can spawn grandchildren that survive the death of the intermediate shell. When OpenClaw runs under a LaunchAgent, the environment is narrower than your laptop shell—missing HOME normalization or a mismatched PATH can cause a server binary to respawn in a tight loop, which looks like an attack on the CPU scheduler even though it is “just” automation.
Pair this with resource limits & ulimit: a default soft limit of 2560 file descriptors per process on many macOS workloads sounds generous until fifty concurrent tool calls multiply by three pipes each. Hitting the limit mid-call leaves descriptors half-open, which is a classic prerequisite for orphaned MCP siblings.
Operator response matrix (signal → action)
| Primary signal | First response (order matters) | Data you should capture | Rollback if wrong | Escalation owner |
|---|---|---|---|---|
| RSS climbs 200 MB in 20 minutes without new prompts | Snapshot ps -o pid,ppid,rss,command -p $(pgrep -f mcp) before touching anything | CSV of PPID chains + timestamps from JSONL | Restart gateway only after labeling parent PID | Platform SRE |
| Duplicate listeners on admin port (e.g., 18999) | Follow gateway recovery single-listener checklist | lsof -nP -iTCP:18999 -sTCP:LISTEN | bootout wrong plist label if two jobs fight | Automation lead |
| 429 storms from provider while local CPU is low | Lower concurrency per parallel agents guide | HTTP 429 counts per 5-minute bucket | Restore previous maxConcurrentTasks | FinOps + ML |
| Tool call hangs with flat RSS | Investigate buffering / PTY, not SIGKILL day | strace-equivalent logs (dtruss sample if policy allows) | Revert unbuffered experiment flags | Client engineer |
Nine-step clean runbook (SSH session on ProxyMac mini)
- Announce maintenance in your team channel—even a 90-second recycle breaks CI if unannounced.
- Export evidence: copy the last 500 lines of gateway log plus
launchctl print gui/$UIDfiltered to OpenClaw labels. - Freeze new jobs: pause schedulers or webhook ingress so you are not racing new MCP spawns mid-kill.
- Identify parents: map PPIDs; never
kill -9the launchd-managed gateway until children are classified. - TERM wave: send SIGTERM to known MCP leaves, wait 15 seconds, recount PIDs.
- KILL only labeled stragglers that still show the MCP argv you verified in step 4.
- Recycle gateway: use vendor-supported
launchctl kickstart -k/ bootout+bootstrap sequence documented for your plist label. - Smoke test: run a read-only tool (two invocations) and confirm RSS returns to baseline within 10 minutes.
- Postmortem hook: if orphans repeat weekly, open a tracking ticket referencing this article and attach the PPID CSV.
launchd-specific recycle discipline
LaunchAgents are not systemd: ThrottleInterval, KeepAlive, and SuccessfulExit interact with how aggressively macOS respawns your gateway. If you only bounce the Node binary but leave an old MCP stdio pair attached to a stale PTY, launchd happily supervises a “healthy” gateway while tools randomly attach to half-dead pipes. After any manual kill, always reconcile plist state with launchctl print and confirm the EffectiveUserID matches the account that owns ~/Library/LaunchAgents.
When you need interactive confirmation (Keychain, TCC) once per release, use VNC for that session, then return to headless SSH operations documented in help center—mixing GUI approvals with unattended launchd cycles is how half-configured MCP servers get spawned twice.
Prevention: concurrency, timeouts, and blast-radius caps
Orphan mitigation is cheaper before production:
- Cap parallel tool calls below the knee in your provider curve; reuse the queueing mental model from parallel OpenClaw.
- Hard timeouts per MCP server in configuration (vendor keys differ—treat 120 seconds as a starting ceiling for network-bound tools, 15 seconds for read-only file stats).
- One working directory per automation persona so
gitand package managers do not fight for locks across agents. - Separate disposable minis for experimental MCP servers vs production orchestration—ProxyMac regions (HK/JP/KR/SG/US) make that a purchasing decision, not a hardware procurement cycle.
FAQ
Why do MCP stdio servers stay alive after the OpenClaw gateway stops? Abrupt gateway exits, ignored SIGTERM propagation, or detached grandchildren launched by npx can leave MCP Node processes running. launchd may also respawn a gateway while older MCP children still hold pipes open, which prevents clean teardown until those descriptors close.
Is it safe to kill orphaned MCP PIDs on a production ProxyMac mini? Prefer SIGTERM first, capture logs, and confirm the PID maps to an MCP command line before SIGKILL. On shared automation hosts, snapshot open files with lsof so you do not terminate an unrelated developer session. After cleanup, restart the gateway via the vendor LaunchAgent flow and verify only one listener binds to the admin port.
How is this different from stdio line-buffering hangs? Buffering issues stall JSON-RPC while processes remain logically healthy. Orphan accumulation shows climbing RSS and extra Node binaries even when traffic is idle. Treat them as separate failure modes: buffering needs PTY or unbuffered flags; orphans need process supervision, concurrency caps, and gateway recycle discipline.
Why Mac mini on ProxyMac is the right place to contain MCP side effects
MCP multiplies operating-system surface area: every tool is another fork, another set of file descriptors, another chance to mishandle signals. Apple Silicon M4 gives enough single-threaded headroom to run multiple stdio servers without stealing laptop battery, macOS matches the stack your scripts assume, and choosing HK / JP / KR / SG / US placement keeps automation physically near the SaaS regions you already test against. ProxyMac’s rental model means you can stand up a sacrificial lab mini for aggressive MCP experiments, point stakeholders at the same pricing page you use for steady-state capacity, and recycle the machine when the process tree gets messy—without negotiating a capital purchase for what is fundamentally a software hygiene problem.
Isolate messy MCP on dedicated metal
Rent HK / JP / KR / SG / US Mac mini for OpenClaw + MCP labs