MCP servers fail with EAGAIN when spawning inside Docker containers
Bug Description
Claude Code fails to spawn MCP servers inside Docker containers with EAGAIN (spawn error), even though identical spawn operations work fine from regular Node.js processes in the same container.
Environment
- Claude Code: v2.1.91
- Host: Ubuntu 24.04, 125GB RAM, 20 CPU
- Docker container: Ubuntu 24.04,
--security-opt seccomp=unconfined, no memory limit,--pids-limit 65536,--ulimit nproc=514055 - Node.js: v20.20.2
- Container has
/.dockerenvfile (Docker detection marker)
Steps to Reproduce
- Create a Docker container with SSH access
- Install Claude Code via npm
- Configure 3 MCP servers in
~/.claude.json - Run
claude --debug - Check
/mcp— the 3rd (and sometimes 2nd) MCP server fails with EAGAIN
Debug Log Output
2026-04-03T14:23:50.033Z [DEBUG] MCP server "gdrive": Starting connection with timeout of 30000ms
2026-04-03T14:23:50.036Z [ERROR] spawn /home/karolina/.npm-global/bin/mcp-google-drive EAGAIN
2026-04-03T14:23:50.036Z [ERROR] spawn ripgrep EAGAIN (multiple times)
All 3 MCP servers + ripgrep + git + statusline spawn at the same time (~0.08 sec window), causing EAGAIN.
Comparison: Host vs Docker
On host (same machine, same user), Claude Code spawns MCP servers in batches with ~1 second gaps:
14:27:37.119 clickup — Starting
14:27:37.127 gmail-anda — Starting
14:27:37.235 gmail-456 — Starting (batch 1: 4 servers)
14:27:37.241 docmost — Starting
... waits for connections ...
14:27:38.160 gmail-zentrolink — Starting
14:27:38.191 gdrive — Starting (batch 2: 4 more servers)
14:27:38.232 imap — Starting
Result: 10 out of 11 servers connect (including 73GB VSZ process!), 0 EAGAIN.
In Docker container, ALL servers start simultaneously:
14:23:50.033 clickup — Starting
14:23:50.034 docmost — Starting (all 3 in 0.08 sec)
14:23:50.037 gdrive — EAGAIN
Key Finding: NOT a resource issue
We verified that spawning from a regular Node.js process inside the same container works perfectly:
// This works fine in the container — 5 concurrent spawns, 11GB VSZ process:
node --max-old-space-size=11264 -e "
const arrays = [];
for (let i = 0; i < 1000; i++) arrays.push(Buffer.alloc(10*1024*1024));
// VSZ: 11GB, same as Claude Code
for (let i = 0; i < 5; i++) spawn('sleep', ['2']); // All 5 succeed
"
We also verified:
- All
/proc/sys/kernel/*parameters are identical between host and container overcommit_memory=1on host- Removing memory limits, raising PIDs to 65536, nproc to 514055 — EAGAIN persists
seccomp=unconfined— EAGAIN persists
Likely Cause
Claude Code appears to detect Docker environment (via /.dockerenv) and uses a different (non-batched) MCP startup strategy compared to running on a host. The non-batched strategy causes too many concurrent posix_spawn/clone3 calls from the same process, resulting in EAGAIN.
Workaround
Wrapping MCP servers in bash scripts with sleep 3 delays:
#!/bin/bash
sleep 3
exec /path/to/mcp-server
This staggers the actual Node.js process spawns past Claude Code's startup burst.
Expected Behavior
Claude Code should use the same batched/sequential MCP startup strategy in Docker containers as it does on the host, or implement retry logic for EAGAIN errors during MCP server initialization.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗