[BUG] Windows local-agent-mode: agent session processes + MCP fleets not reaped on session end (accumulate across launches)
Summary
On Windows, Claude Desktop's local-agent-mode does not tear down an agent session's process tree when the session ends. Each launched session leaves its claude.exe (embedded Claude Code) and its entire MCP server fleet running. They accumulate one full fleet per launch until manually killed.
This is distinct from the existing reports in two ways:
- It is the local-agent-mode orchestration inside the desktop app, not the bare CLI (#33947) or Task subagents (#66280).
- The session
claude.exeprocess itself survives — it stays parented to the live Claude Desktop app, it is not orphaned/re-parented (no PPID=1 equivalent). So the orchestrator is failing to end the session process at all, which is upstream of the MCP-orphan problem others have described.
Related: #33947 (macOS, canonical, CLOSED), #66280 (macOS Task subagents, OPEN), #38228 (Windows uv/uvx, closed as dup of #33947).
Environment
- Embedded Claude Code: 2.1.170 (
AppData\Roaming\Claude\claude-code\2.1.170\claude.exe) - Host: Claude Desktop app 1.12603.1.0, local-agent-mode
- OS: Windows 11 Pro 10.0.26200
- MCP servers (per session): a python3 stdio server,
headroom,serena(viauvx → uv → serena.exe → pythonlanguage servers), pluscontext7/playwright/memory(eachcmd → npx → node)
Observed behavior
Over ~24h, 7 agent sessions were launched. Each spawned a full MCP fleet; none were reaped on session end. Snapshot before cleanup:
- 7 ×
headroom mcp serve - 7 × serena instances — their dashboards bound to incrementing ports 24282, 24283, 24284 … 24288 (one per live instance), which is itself a clean fingerprint of the leak
- the per-session
node/pythonMCP fleets - ~21 serena/headroom/uvx processes + dozens of node/python; several GB RAM
- All 6 stale
claude.exesession roots were still alive, each parented to the single live Claude Desktop app (explorer-launched). Only the newest session was actually in use.
Each session's claude.exe is launched by the desktop app with an inline --mcp-config {…} and --plugin-dir …\local-agent-mode-sessions\<uuid>\… (the local-agent-mode marker). The direct children of a live session process:
python3 <stdio mcp server>
cmd → npx @upstash/context7-mcp
cmd → npx @playwright/mcp@latest
headroom mcp serve
uvx → serena start-mcp-server --project-from-cwd --context claude-code
cmd → npx @modelcontextprotocol/server-memory
Reproduction
- Windows + Claude Desktop with local-agent-mode and several MCP servers configured (include a
uvx-launched one such as serena). - Start an agent session, use it, then close / move on. Start a fresh session next time.
- Repeat across a day.
- Observe the fleet grow one generation per launch:
``powershell`
Get-CimInstance Win32_Process -Filter "Name='headroom.exe'" |
ForEach-Object { "$($_.ProcessId) <- parent $($_.ParentProcessId)" }
Get-NetTCPConnection -State Listen | Where-Object { $_.LocalPort -ge 24282 -and $_.LocalPort -le 24292 }
claude.exe` session roots remain alive under the Desktop app PID.
Serena dashboard ports increment (24282, 24283, …) and old
Expected behavior
When a local-agent-mode session ends, the orchestrator should terminate that session's claude.exe and its entire MCP subprocess tree.
Root-cause notes (Windows-specific)
- Windows has no
PR_SET_PDEATHSIG; children are not auto-killed when a parent exits. Reliable teardown needs a Job Object withJOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, or explicit recursive PID tracking + tree-kill. - The MCP launch chains are 3–4 levels deep (
uvx → uv → serena.exe → python;cmd → npx → node). A cleanup that only signals/kills the direct child orphans the deep workers — so per-session job-object containment (ortaskkill /T) is required, not just closing stdin on the immediate child. - Critically, here even the top-level session
claude.exeis never signaled, so this is upstream of the MCP-orphan issue: the orchestrator isn't ending the session process at all.
Workaround
Manually tree-kill stale session roots while keeping the newest: find every claude.exe that is a parent of a headroom/serena process, then taskkill /PID <root> /T /F. This dropped the host from ~21 to 3 of these processes with no impact on the live session.
---
Filed from a Windows Claude Code session after diagnosing the leak on the user's machine.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗