anthropics / anthropics/claude-agent-sdk-typescript

query(): MCP server processes remain as zombies after session ends

Aperta
#219 0 commenti 0 reazioni 1 assegnatario Rivendicata da @ashwin-ant Vedi su GitHub
bug enhancement
Lingua principale
Shell
Stelle
1.8k
Fork
226
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

## Bug Report

### Description

When using the Agent SDK's `query()` to orchestrate multiple sequential sessions (relay pattern), MCP server processes spawned internally by each session often survive after the session ends. This creates zombie processes that accumulate over time.

### The core problem

There is no way for an external orchestrator to determine which MCP process belongs to which session. `query()` spawns MCP servers internally, but does not:

1. Expose the spawned MCP process PIDs to the caller
2. Guarantee cleanup of MCP processes when the session ends (including timeout/error cases)
3. Provide any session-scoped tagging/grouping mechanism for spawned child processes

### Reproduction steps

1. Create a TypeScript orchestrator that calls `query()` in a loop (relay pattern)
2. Each session uses MCP servers configured in `.claude/mcp.json`
3. After each session ends (success, timeout, or error), check for remaining MCP processes
4. Observe that MCP server processes (`node.exe` for MCP Memory, `python.exe` for MCP RAG, etc.) accumulate with each session

### Workaround attempted

We use `wmic` (Windows) to snapshot all MCP-related PIDs before/after each session and kill the diff. This works for **single-mission** orchestration only. It fundamentally breaks for **concurrent missions** because:

- Before/after PID diffs cannot distinguish which mission owns which MCP process
- PID reuse (rare but real on Windows) can cause incorrect kills of unrelated processes

Since the SDK spawns MCP servers internally with no external tagging, there is no reliable way to associate MCP processes with their parent session from outside.

### Impact

After 5-10 relay sessions, dozens of zombie `node.exe` (MCP Memory server) and `python.exe` (MCP RAG server) processes accumulate, consuming memory and potentially causing port conflicts.

### Proposed solutions

Any of these would resolve the issue:

1. **`query()` guarantees MCP cleanup** on session end (including timeout/error/max_turns cases)
2. **`query()` returns spawned child PIDs** in the result message, so the orchestrator can clean them up
3. **Session-scoped process group** (e.g., Windows Job Object or Unix process group) so all child processes can be killed as a unit
4. **Option to pass existing MCP server connections** to `query()` instead of spawning new ones per session (also saves startup time)

### Environment

- **OS**: Windows 11
- **SDK**: `@anthropic-ai/claude-agent-sdk`
- **Language**: TypeScript
- **Pattern**: Relay orchestrator using `query()` in a loop with `maxTurns` per session
- **MCP servers**: Node.js (MCP Memory) + Python (MCP RAG)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.