[BUG] Windows: npx-based MCP/plugin servers fail to connect (spawn EINVAL from .cmd shim)

Resolved 💬 2 comments Opened Jun 13, 2026 by kimmeyh Closed Jun 15, 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, every plugin/MCP server launched via the bare command npx fails with "Failed to connect". claude mcp list shows the server as "Failed to connect". The two official-marketplace plugins that ship this config -- context7 and playwright -- are both broken out of the box.

Root cause: Claude Code spawns the MCP server command directly (no shell). On Windows, npx resolves to npx.cmd, and since Node.js 18.20.2 / 20.12.2 (the CVE-2024-27980 hardening) child_process.spawn throws EINVAL when asked to spawn a .cmd/.bat file without shell: true. So the server process never starts and the MCP handshake never begins.

This is environment-independent: it reproduces for any Windows user on Node >= 18.20.2 (all Node 22.x) with any MCP server configured as "command": "npx". Servers that launch a real .exe (e.g. serena-mcp-server) connect fine on the same machine, which isolates the cause to the .cmd-shim spawn.

What Should Happen?

npx-based MCP servers should connect successfully on Windows, the same as on macOS/Linux. Claude Code's MCP spawner should launch .cmd-shim commands (npx/npm/pnpm/yarn) via a shell on Windows -- either spawn with shell: true, or invoke as cmd.exe /c <command> <args...> -- per Node's post-CVE-2024-27980 guidance.

Error Messages/Logs

claude mcp list:
  plugin:context7:context7: npx -y @upstash/context7-mcp - Failed to connect
  plugin:playwright:playwright: npx @playwright/mcp@latest - Failed to connect

Minimal pure-Node reproduction of the underlying spawn failure:

  > node -e "const{spawnSync}=require('child_process'); const r=spawnSync('npx.cmd',['--version'],{stdio:'pipe'}); console.log(r.error?r.error.code:'ok',(r.stdout||'').toString().trim());"
  EINVAL

  > node -e "const{spawnSync}=require('child_process'); const r=spawnSync('cmd',['/c','npx','--version'],{stdio:'pipe'}); console.log(r.error?r.error.code:'ok',(r.stdout||'').toString().trim());"
  ok 11.4.2

Direct spawn of npx.cmd -> EINVAL. Routing through cmd /c -> works.

Steps to Reproduce

  1. On Windows 11 with Node.js >= 18.20.2 (e.g. Node 22.9.0), configure any MCP server with "command": "npx" -- or install the official context7 or playwright plugin, which ship this config:

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

  1. Run: claude mcp list
  2. Observe: the npx-based server(s) show "Failed to connect".

Deterministic root-cause repro (no Claude Code needed):

  1. Run: node -e "const{spawnSync}=require('child_process'); console.log(spawnSync('npx.cmd',['--version'],{stdio:'pipe'}).error?.code)"
  2. Observe: EINVAL (whereas cmd /c npx --version succeeds)

Workaround that fixes it: change the config to
"command": "cmd", "args": ["/c", "npx", "-y", "@upstash/context7-mcp"]

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

not sure

Claude Code Version

2.1.177 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

PowerShell

Additional Information

Affected official-marketplace plugins out of the box: context7 and playwright (both use "command": "npx").

Why the fix belongs in Claude Code's spawner rather than per-plugin config: the cmd /c workaround must be applied to each plugin's .mcp.json (both the loaded cache copy and the marketplace source copy) and can be reverted by a future plugin update. Spawning .cmd shims via shell on Windows fixes every affected user at once.

Suggested fixes (in priority order):
A. On Windows, spawn MCP server commands with shell: true (aligns with Node's post-CVE-2024-27980 guidance).
B. Rewrite the launch to cmd.exe /c <command> <args...>.
Secondary: when a spawn throws EINVAL on Windows for a .cmd target, surface a clearer error than "Failed to connect".

Note on a misleading secondary symptom: on a cold npx cache, npx -y <pkg> must download the package, which can exceed the 30s MCP connection timeout and show "connection timed out after 30000ms". That is separate -- even with a fully warmed cache the EINVAL failure persists, so warming the cache does not fix it.

Environment:
Claude Code 2.1.177 | Windows 11 (10.0.26200.8524) | Node v22.9.0 | npm 11.4.2 | npx 11.4.2

View original on GitHub ↗

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