MCP servers fail with EAGAIN when spawning inside Docker containers

Resolved 💬 3 comments Opened Apr 3, 2026 by zentrolink-ivanzhukov Closed May 13, 2026

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 /.dockerenv file (Docker detection marker)

Steps to Reproduce

  1. Create a Docker container with SSH access
  2. Install Claude Code via npm
  3. Configure 3 MCP servers in ~/.claude.json
  4. Run claude --debug
  5. 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=1 on 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.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗