fix(mcp): Revert recent changes and route Claude Code/Cursor manifests through Node launcher#155
fix(mcp): Revert recent changes and route Claude Code/Cursor manifests through Node launcher#155
Conversation
POSIX posix_spawn requires byte 0-1 == "#\!" for shebang detection. PR ory#145 removed the "#\!/bin/sh" line from scripts/run.cmd to enforce strict cmd.exe stdout cleanliness on Windows MCP hosts. That regressed macOS/Linux MCP launches with: ENOEXEC: posix_spawn '/path/scripts/run.cmd' A single byte 0 cannot satisfy both POSIX shebang detection and cmd.exe echo suppression (which requires "@" or ":" prefix). The two constraints are mutually exclusive for a polyglot file. Resolution: - Add scripts/run.cjs as a small Node dispatcher that invokes run.sh on Unix and "cmd /c run.bat" on Windows. Node is guaranteed in PATH for Claude Code, Cursor, OpenCode, and Codex environments. The launcher forwards SIGTERM/SIGINT/SIGHUP from the MCP host to the child so the lumen binary does not linger as an orphan process when Claude Code or Cursor shuts the launcher down. - Update .claude-plugin/plugin.json and .cursor/mcp.json to invoke "node scripts/run.cjs stdio". Both Claude Code and Cursor now bypass run.cmd entirely. - Restore "#\!/bin/sh" to scripts/run.cmd line 1. This re-enables direct posix_spawn invocation on macOS/Linux for backward compatibility with stale plugin manifests, hook commands (hooks/hooks.json, hooks/hooks-cursor.json), and the OpenCode plugin loader. - Restore the shebang-tolerant Test 3 in test_run_cmd_windows.bat (matches the version at b66a339 prior to PR ory#145). PR ory#145 strengthened Test 3 to enforce empty stderr and added Test 4 to enforce empty stdout under "cmd /c" — both relied on run.cmd being the MCP entry point. Since Claude Code and Cursor now route through run.cjs, those invariants no longer apply; reverting to the original tolerant Test 3 keeps the delegation tests intact while accepting the harmless shebang noise that cmd.exe emits. Codex install docs are unchanged: Codex already documents per-OS scripts (run.sh on Unix, run.cmd on Windows) and never relied on the polyglot being the single MCP entry point. Compatibility: - Claude Code (any OS, post-update): node dispatch path - Cursor (any OS, post-update): node dispatch path - OpenCode (any OS): existing lumen.js dispatcher; unaffected - Codex (any OS): unchanged; per-OS install docs continue to work - Hooks on macOS/Linux: works via restored shebang - Stale Claude/Cursor manifests pointing at run.cmd on macOS: now works Constraint: Cannot satisfy POSIX shebang and cmd.exe stdout cleanliness at byte 0 of a single file Constraint: Plugin manifest schema does not support per-OS command dispatch Rejected: shebang-only restoration | leaves Claude/Cursor still fragile on direct run.cmd invocation Rejected: /bin/sh in manifest | absent on Windows Rejected: bundle bin/lumen directly | requires marketplace per-OS distribution Confidence: high Scope-risk: narrow Directive: do not remove #\!/bin/sh from run.cmd without restoring per-OS dispatch via the manifest
📝 WalkthroughWalkthroughThe PR refactors the MCP launcher infrastructure from a batch-based polyglot runner to a Node.js entry point ( ChangesMCP Launcher Refactoring
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/run.cmd (1)
1-13:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse CRLF line endings for
scripts/run.cmd.Windows batch label/goto parsing can fail with LF-only line endings, particularly when labels cross 512-byte boundaries—a known cmd.exe bug documented by the bazel-lib project and others. This file is currently 190 bytes and below the boundary threshold, but converting to CRLF follows the safe practice for all
.batand.cmdfiles. No.gitattributesrules currently enforce line endings for these scripts, so an explicit conversion is needed.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/run.cmd` around lines 1 - 13, The script uses LF-only line endings which can break Windows cmd.exe label/goto parsing; convert scripts/run.cmd to use CRLF line endings (Windows-style) so labels like ":batch" and the batch section starting with "@echo off" are correctly parsed on Windows; ensure the file is saved with CRLF encoding (e.g., via your editor or a git core.eol/.gitattributes rule) and verify the resulting run.cmd contains CRLF line endings throughout while preserving the existing content such as the shebang line and the exec/call blocks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@scripts/run.cmd`:
- Around line 1-13: The script uses LF-only line endings which can break Windows
cmd.exe label/goto parsing; convert scripts/run.cmd to use CRLF line endings
(Windows-style) so labels like ":batch" and the batch section starting with
"@echo off" are correctly parsed on Windows; ensure the file is saved with CRLF
encoding (e.g., via your editor or a git core.eol/.gitattributes rule) and
verify the resulting run.cmd contains CRLF line endings throughout while
preserving the existing content such as the shebang line and the exec/call
blocks.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: e5095c8b-4e3e-445f-b7a7-5bb4b9dc6578
📒 Files selected for processing (6)
.claude-plugin/plugin.json.cursor-plugin/INSTALL.md.cursor/mcp.jsonscripts/run.cjsscripts/run.cmdscripts/test_run_cmd_windows.bat
Declining. CRLF would re-break macOS posix_spawn dispatch — exactly the
|
|
PR #154 by @hypn4 also targets this regression. Unfortunately I didn't see it until after I finished mine. This PR is narrower — a minimum-diff alternative for the case where a fast-merge surgical patch is preferable to the larger architectural change. Scope comparison
RecommendationAccept this one as the quick fix and then ask @hypn4 to split #154 up into a few PRs. SHA-256 verification, Lock file for concurrent prefetch, Cache dir resolution chain are all useful contributions but should be their own PRs. Then look into whether the single However, right now MacOS is in a broken state which is why I'm suggesting minimal changes to begin with. Fully recognizing @hypn4's effort and contributions, their regression test in #153 should be added either way as a next step if this gets approved. |
Fix MacOS MCP. Currently the MCP server won't load on MacOS. POSIX posix_spawn requires byte 0-1 == "#!" for shebang detection.
PR #145 removed the
#\!/bin/shline fromscripts/run.cmdto enforce strict cmd.exe stdout cleanliness on Windows MCP hosts. That regressed macOS/Linux MCP launches with:A single byte 0 cannot satisfy both POSIX shebang detection and
cmd.exeecho suppression (which requires "@" or ":" prefix). The two constraints are mutually exclusive for a polyglot file.Resolution:
cmd /c run.baton Windows. Node is guaranteed in PATH for Claude Code, Cursor, OpenCode, and Codex environments. The launcher forwards SIGTERM/SIGINT/SIGHUP from the MCP host to the child so the lumen binary does not linger as an orphan process when Claude Code or Cursor shuts the launcher down..claude-plugin/plugin.jsonand.cursor/mcp.jsonto invokenode scripts/run.cjs stdio. Both Claude Code and Cursor now bypassrun.cmdentirely.#\!/bin/shtoscripts/run.cmdline 1. This re-enables direct posix_spawn invocation on macOS/Linux for backward compatibility with stale plugin manifests, hook commands (hooks/hooks.json,hooks/hooks-cursor.json), and the OpenCode plugin loader.test_run_cmd_windows.bat(matches the version atb66a339prior to PR fix(scripts): eliminate stdout pollution in run.cmd polyglot #145). PR fix(scripts): eliminate stdout pollution in run.cmd polyglot #145 strengthened Test 3 to enforce empty stderr and added Test 4 to enforce empty stdout undercmd /c— both relied on run.cmd being the MCP entry point. Since Claude Code and Cursor now route throughrun.cjs, those invariants no longer apply; reverting to the original tolerant Test 3 keeps the delegation tests intact while accepting the harmless shebang noise thatcmd.exeemits.Codex already documents per-OS scripts (
run.shon Unix,run.cmdon Windows) and never relied on the polyglot being the single MCP entry point.Compatibility:
Constraint: Cannot satisfy POSIX shebang and
cmd.exestdout cleanliness at byte 0 of a single fileConstraint: Plugin manifest schema does not support per-OS command dispatch
Rejected: shebang-only restoration | leaves Claude/Cursor still fragile on direct run.cmd invocation
Rejected:
/bin/shin manifest | absent on WindowsRejected: bundle
bin/lumendirectly | requires marketplace per-OS distributionConfidence: high
Scope-risk: narrow
Directive: do not remove
#\!/bin/shfromrun.cmdwithout restoring per-OS dispatch via the manifestSummary by CodeRabbit
Documentation
Chores