Summary
mcp-health-check.js PreToolUse hook fails on Windows with spawn npx ENOENT, marking MCP servers as unhealthy and blocking all subsequent MCP tool calls until the cooldown expires.
This is the same class of Windows spawn bug as #1435 (GateGuard), but in a different hook.
Environment
- OS: Windows 10 Pro (10.0.19045)
- Shell: Git Bash (via Claude Code)
- ECC version: 1.10.0
- Claude Code: VS Code extension
- Node/npx: Available on PATH (
which npx → /c/Program Files/nodejs/npx)
Steps to Reproduce
- Install ECC plugin with an MCP server configured in
~/.claude.json (e.g., npx -y @azure-devops/mcp biztechonline)
- Use any
mcp__* tool in Claude Code on Windows
- The
pre:mcp-health-check hook fires and attempts spawn('npx', ...)
- Spawn fails with
ENOENT because Node.js child_process.spawn does not resolve .cmd extensions on Windows
Expected Behavior
The health check should either:
- Resolve
npx correctly on Windows (use npx.cmd, full path, or shell: true)
- Gracefully skip the probe if the spawn fails, rather than marking the server unhealthy
Actual Behavior
[MCPHealthCheck] azure-devops is unavailable (spawn npx ENOENT). Blocking wit_my_work_items so Claude can fall back to non-MCP tools.
- Server marked unhealthy with 30s backoff in
~/.claude/mcp-health-cache.json
- All MCP tool calls blocked until cooldown expires
- Manual edit of
mcp-health-cache.json required to restore functionality
- Cycle repeats on next health check probe
Workaround
Disable the hook via ECC_DISABLED_HOOKS in ~/.claude/settings.json:
{
"env": {
"ECC_DISABLED_HOOKS": "pre:mcp-health-check"
}
}
Root Cause
In scripts/hooks/mcp-health-check.js, the hook uses spawn('npx', ...). On Windows, Node.js child_process.spawn does not automatically resolve .cmd extensions — npx is actually npx.cmd on Windows.
Suggested Fix
Same pattern as the GateGuard Windows fix in #1439:
// Option A: shell: true
spawn('npx', args, { ...opts, shell: true });
// Option B: platform-aware binary
const npxBin = process.platform === 'win32' ? 'npx.cmd' : 'npx';
spawn(npxBin, args, { ...opts });
Also consider: if the spawn probe fails, treat it as "unknown" rather than "unhealthy" — the MCP server itself may be perfectly reachable via Claude Code's own stdio transport.
Summary
mcp-health-check.jsPreToolUse hook fails on Windows withspawn npx ENOENT, marking MCP servers as unhealthy and blocking all subsequent MCP tool calls until the cooldown expires.This is the same class of Windows spawn bug as #1435 (GateGuard), but in a different hook.
Environment
which npx→/c/Program Files/nodejs/npx)Steps to Reproduce
~/.claude.json(e.g.,npx -y @azure-devops/mcp biztechonline)mcp__*tool in Claude Code on Windowspre:mcp-health-checkhook fires and attemptsspawn('npx', ...)ENOENTbecause Node.jschild_process.spawndoes not resolve.cmdextensions on WindowsExpected Behavior
The health check should either:
npxcorrectly on Windows (usenpx.cmd, full path, orshell: true)Actual Behavior
~/.claude/mcp-health-cache.jsonmcp-health-cache.jsonrequired to restore functionalityWorkaround
Disable the hook via
ECC_DISABLED_HOOKSin~/.claude/settings.json:{ "env": { "ECC_DISABLED_HOOKS": "pre:mcp-health-check" } }Root Cause
In
scripts/hooks/mcp-health-check.js, the hook usesspawn('npx', ...). On Windows, Node.jschild_process.spawndoes not automatically resolve.cmdextensions —npxis actuallynpx.cmdon Windows.Suggested Fix
Same pattern as the GateGuard Windows fix in #1439:
Also consider: if the spawn probe fails, treat it as "unknown" rather than "unhealthy" — the MCP server itself may be perfectly reachable via Claude Code's own stdio transport.