claude-code - 💡(How to fix) Fix [BUG] Windows: plugin-shipped MCP servers using bare `npx` fail with `spawn ENOENT` (LSP fix from #17312 missed the MCP spawn path)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Plugin-shipped stdio MCP servers that use bare npx as their command (the default for most official plugins) fail with spawn npx ENOENT on Windows. The LSP spawn fix from #17312 (landed in v2.1.132) addressed the equivalent bug for LSP plugins but didn't extend to the MCP server spawn path — so MCP plugins are still broken in the same way.

This affects every official plugin I tested whose .mcp.json / plugin.json ships "command": "npx".

Error Message

const { spawn } = require('child_process'); const p = spawn('npx', ['-y', '@upstash/context7-mcp', '--version'], { stdio: 'inherit' }); p.on('error', e => console.error('SPAWN ERROR:', e.code, e.message));

Root Cause

On Windows, npx is the batch shim npx.cmd. Node's child_process.spawn only resolves .cmd/.bat extensions via PATHEXT when shell: true (or shell: 'cmd.exe') is set, or when the caller passes the explicit .cmd filename. This is the same Node-on-Windows pattern that #17312 fixed for LSP server spawning in v2.1.132.

Fix Action

Fix / Workaround

Workaround (fragile)

This works (verified all 6 plugins above now show ✓ Connected), but gets wiped whenever the plugin updates, since the patched files live in the plugin cache rather than in any user-owned config.

Note: the location of the MCP block varies across plugins — .mcp.json at the install root, mcpServers inline in .claude-plugin/plugin.json, or a separate mcp.json referenced from plugin.json. The patch has to land in whichever file the plugin actually uses, and claude mcp list doesn't tell you which.

Code Example

const { spawn } = require('child_process');
const p = spawn('npx', ['-y', '@upstash/context7-mcp', '--version'], { stdio: 'inherit' });
p.on('error', e => console.error('SPAWN ERROR:', e.code, e.message));

---

SPAWN ERROR: ENOENT spawn npx ENOENT

---

2.2.5

---

- "command": "npx",
- "args": ["-y", "@upstash/context7-mcp"]
+ "command": "cmd",
+ "args": ["/c", "npx", "-y", "@upstash/context7-mcp"]
RAW_BUFFERClick to expand / collapse

Summary

Plugin-shipped stdio MCP servers that use bare npx as their command (the default for most official plugins) fail with spawn npx ENOENT on Windows. The LSP spawn fix from #17312 (landed in v2.1.132) addressed the equivalent bug for LSP plugins but didn't extend to the MCP server spawn path — so MCP plugins are still broken in the same way.

This affects every official plugin I tested whose .mcp.json / plugin.json ships "command": "npx".

Affected official plugins (as of 2.1.139)

All of these Failed to connect until I manually wrapped each with cmd /c:

PluginConfig locationCommand shipped
context7@claude-plugins-official.mcp.jsonnpx -y @upstash/context7-mcp
chrome-devtools-mcp@claude-plugins-official.claude-plugin/plugin.json (inline)npx chrome-devtools-mcp@latest
azure@claude-plugins-official.mcp.jsonnpx -y @azure/mcp@latest server start
mongodb@claude-plugins-officialmcp.json (referenced from plugin.json)npx -y mongodb-mcp-server@1
desktop-commander@claude-plugins-official.claude-plugin/plugin.json (inline)npx -y @wonderwhy-er/desktop-commander@latest
playwright@claude-plugins-official.mcp.jsonnpx @playwright/mcp@latest

Reproducer (no Claude Code needed)

const { spawn } = require('child_process');
const p = spawn('npx', ['-y', '@upstash/context7-mcp', '--version'], { stdio: 'inherit' });
p.on('error', e => console.error('SPAWN ERROR:', e.code, e.message));

On Windows 10/11, Node 20.x or 22.x:

SPAWN ERROR: ENOENT spawn npx ENOENT

With { shell: true } (or wrapping in cmd /c), it succeeds immediately:

2.2.5

Root cause

On Windows, npx is the batch shim npx.cmd. Node's child_process.spawn only resolves .cmd/.bat extensions via PATHEXT when shell: true (or shell: 'cmd.exe') is set, or when the caller passes the explicit .cmd filename. This is the same Node-on-Windows pattern that #17312 fixed for LSP server spawning in v2.1.132.

Expected behavior

The MCP server spawn path should use shell: true (or equivalent) on process.platform === 'win32' — matching whatever the LSP path now does post-#17312.

Workaround (fragile)

Edit each plugin's manifest under ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/... to wrap the command:

- "command": "npx",
- "args": ["-y", "@upstash/context7-mcp"]
+ "command": "cmd",
+ "args": ["/c", "npx", "-y", "@upstash/context7-mcp"]

This works (verified all 6 plugins above now show ✓ Connected), but gets wiped whenever the plugin updates, since the patched files live in the plugin cache rather than in any user-owned config.

Note: the location of the MCP block varies across plugins — .mcp.json at the install root, mcpServers inline in .claude-plugin/plugin.json, or a separate mcp.json referenced from plugin.json. The patch has to land in whichever file the plugin actually uses, and claude mcp list doesn't tell you which.

Why this is distinct from existing open issues

  • #46360 (Playwright/Windows) is about the claude mcp add CLI mangling /c into C:/ for user-configured servers. This issue is about plugin-shipped configs that never go through claude mcp add.
  • #32951 (local stdio MCP not loaded on native Windows) is about local servers being silently absent from /mcp. Here the servers do appear in claude mcp list — they just fail at the spawn step with a visible "Failed to connect".
  • #17312 / #19658 / #21115 are all LSP-specific. The fix that closed them addressed the LSP code path; the MCP path has the same bug and needs the same fix.

Environment

  • Claude Code: 2.1.139 (latest as of filing)
  • OS: Windows 10 Pro 10.0.19045
  • Node: tested on 20.15.0 and 22.22.2 — both reproduce the spawn ENOENT
  • Shell: PowerShell 7 (also reproduces from Git Bash and a raw node -e invocation)
  • Plugin marketplace: claude-plugins-official

Suggested fix

In whatever module spawns stdio MCP servers, mirror the LSP fix from #17312 — pass shell: true (or shell: 'cmd.exe') when process.platform === 'win32'. Same one-line change that worked for LSP should clear this entire category of plugin failures.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The MCP server spawn path should use shell: true (or equivalent) on process.platform === 'win32' — matching whatever the LSP path now does post-#17312.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING