Skip to content

Windows: /mcp UI fails to spawn bin/devkit (extensionless shell script) #60

Description

@5uck1ess

Summary

On Windows, Claude Code's in-session MCP launcher cannot spawn bin/devkit because it's an extensionless POSIX shell script (#!/bin/sh). The /mcp UI shows devkit-engine as failed, even though claude mcp list (CLI) reports it as connected. The two disagree because they use different process-spawn code paths.

Environment

Reproduction

  1. Install devkit plugin on Windows.
  2. Let v2.1.6 download bin/devkit-engine-v2.1.6-windows-amd64.exe (works fine post-bin/devkit: fix Windows first-run install (curl+schannel bug, #58) #59).
  3. Open Claude Code, run /mcpplugin:devkit:devkit-engine shows × failed.
  4. In the same session, run claude mcp list → shows ✓ Connected.

Root cause (proven, not speculation)

bin/devkit has no file extension. Claude Code UI spawns MCP servers via Node child_process.spawn without shell:true on Windows. Windows CreateProcess can't execute a shebang script directly, and CMD can't either because the file has no .exe/.cmd/.bat extension.

Reproduced both failure modes with Node:

// 1) Direct spawn (what CC UI does):
spawn('…/bin/devkit', ['mcp'])
// → Error: spawn ENOENT

// 2) Spawn via shell:true (cmd.exe):
spawn('…/bin/devkit', ['mcp'], { shell: true })
// → stderr: "'…/bin/devkit' is not recognized as an internal or external command"

Spawning the already-downloaded engine .exe directly works perfectly — it prints devkit MCP server ready and responds to JSON-RPC over stdio:

spawn('…/bin/devkit-engine-v2.1.6-windows-amd64.exe', ['mcp'])
// → "devkit MCP server ready" on stderr, accepts MCP requests on stdin

claude mcp list succeeds because it uses a different probe path (likely invokes via sh.exe), which masks the UI-launcher issue from simple CLI checks.

Proposed fix

Ship a Windows-compatible launcher. Two options:

Option A — bin/devkit.cmd shim (recommended, minimal)

Add bin/devkit.cmd:

@echo off
sh "%~dp0devkit" %*

Then make plugin.json select per platform, or ship the .cmd and let Claude Code pick it up automatically (Windows spawn treats .cmd as executable).

Pros: keeps the existing download/resume wrapper logic. Requires sh.exe on PATH, but Git Bash is effectively universal on dev Windows and the current script already assumes POSIX tooling.

Option B — platform-specific command in plugin.json

Point mcpServers.devkit-engine.command at the engine .exe directly on Windows. Loses the auto-download wrapper on first run, but once the engine is downloaded (the current wrapper still handles that for other codepaths), direct launch is simpler and has no shell dependency.

Option C — bin/devkit.ps1

PowerShell equivalent that can locate and exec the engine. More portable than .cmd (no dependency on sh.exe), but more code to maintain.

Option A is the smallest diff and matches how most POSIX-first CLIs ship on Windows.

Local workaround (confirmed working)

Edit ~/.claude/plugins/cache/5uck1ess-plugins/devkit/2.1.6/.claude-plugin/plugin.json:

-      "command": "${CLAUDE_PLUGIN_ROOT}/bin/devkit",
+      "command": "${CLAUDE_PLUGIN_ROOT}/bin/devkit-engine-v2.1.6-windows-amd64.exe",

After this change, /mcp UI shows devkit-engine as connected. Gets clobbered on next plugin update, which is why an upstream fix is needed.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions