[BUG] Windows: MCP child processes orphan on session exit — suggest JobObject + KILL_ON_JOB_CLOSE

Resolved 💬 3 comments Opened May 10, 2026 by wzyxdwll Closed May 13, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

On Windows, MCP child processes (and codex/gemini plugin CLI subprocesses) survive Claude Code main process exit indefinitely. Over 4 days of normal use I accumulated 55 orphan node.exe processes
consuming ~2 GB RAM:

  • 24× playwright MCP server
  • 18× context7 MCP server
  • 11× codex.js app-serve (codex@openai-codex plugin)
  • gemini-cli (gemini@google-gemini plugin)

POSIX users do not see this because SIGHUP propagation handles child cleanup by default. Windows has no equivalent default — children are fully detached from parent lifecycle unless the parent explicitly opts
in via JobObject + JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE. Claude Code currently does not.

Some long-stuck orphans (33h+ in my case) enter an "uninterruptible IPC syscall" state where even Stop-Process -Force and taskkill /F return Access denied. The only workaround is wmic process where
"ProcessId=N" delete
(different kernel API path) or full reboot.

What Should Happen?

When the Claude Code main process exits (clean exit, Ctrl+C, window close, or crash), all MCP server children and plugin CLI subprocesses should terminate atomically with it — same lifecycle parity
Linux/macOS users get for free via SIGHUP propagation.

After closing a session, Get-Process node should return zero Claude-Code-spawned residue.

Error Messages/Logs

PS> Get-CimInstance Win32_Process -Filter "Name='node.exe'" | Measure-Object
  Count : 57

  # After cleanup attempts on stuck zombies:
  PS> Stop-Process -Id 25956 -Force
  Stop-Process : Cannot stop process "node (25956)" because of the following error: Access is denied

  PS> taskkill /F /PID 25956
  ERROR: The process with PID 25956 could not be terminated.
  Reason: Access is denied.

  # wmic uses a different kernel API path and succeeds:
  PS> wmic process where "ProcessId=25956" delete
  Deleting instance \\DESKTOP-XXX\ROOT\CIMV2:Win32_Process.Handle="25956"
  Instance deletion successful.

  # Process inventory snapshot before cleanup (4 days of normal use):
  Tag        Count OldestHours AvgHours
  mcp-server    42        94.7     73.4    # playwright + context7
  codex-cli      5        95.6     87.0
  gemini-cli     2        80.0     80.0
  phase-runner-orphan-chain  2  33.5  33.5  # stuck IPC chain, wmic-only kill

Steps to Reproduce

  1. Environment: Windows 11, Claude Code 2.1.132, Node v24.9.0
  2. Configure ~/.claude.json with at least 2 stdio MCP servers, e.g.:

```json
{
"mcpServers": {
"context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] },
"playwright": { "command": "npx", "args": ["-y", "@playwright/mcp"] }
}
}

  1. Open Claude Code and let MCP servers initialize. Confirm with:

Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
Where-Object { $_.CommandLine -match 'context7|playwright' } |
Measure-Object
# Expect: 2 (one per MCP)

  1. Close the Claude Code window (or Ctrl+C, or kill the main process).
  2. Re-check the same query → both MCP servers still alive, now orphaned (PPID points to the dead Claude Code main process).
  3. Repeat steps 3-5 across a few days of normal use → orphans accumulate arithmetically. After ~4 days I had 42 MCP orphans + 13 plugin CLI orphans = 55 total.
  4. Some orphans reach a stuck-IPC state and refuse Stop-Process -Force / taskkill /F (Access denied). Only wmic process delete or reboot clears them.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.132

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

_No response_

View original on GitHub ↗

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