fix: deliver codex MCP server via CODEX_HOME overlay on Windows (#681) - #683
Conversation
On Windows every `bili codex` launch rides an npm .cmd shim through cmd.exe. The inline `-c mcp_servers.bili.command=<JSON path>` value embeds an absolute path carrying both quotes and spaces; cmd.exe strips the TOML-required quotes (it has no literal-quote escape), leaving malformed TOML — so the bili MCP server never registers and plugin-mode compression silently never activates (stock node location C:\Program Files\nodejs\node.exe is the common trigger). Fix: on win32 deliver [mcp_servers.bili] via a file instead of argv — a persistent <CODEX_HOME>-bili overlay (reusing the pi/omp/dsh machinery) whose merged config.toml holds the block, pointed at by CODEX_HOME. POSIX keeps the byte-identical inline -c args (gated on process.platform). If the overlay cannot be built, injection degrades to wire mode (compression still active) with a warning. - client-config.ts: resolveCodexHome (CODEX_HOME || ~/.codex) - launcher.ts: prepareCodexHome / mergeCodexBiliBlock / stripCodexBiliBlock / prepareCodexMcpInjection; codex launch branch refactored to use them - tests/launcher.test.ts: 6 new unit tests Pre-flight: typecheck clean; full suite 1240/1241 (the single failure is a pre-existing environment-dependent resolveClientCommand test, unrelated); build success.
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)npm install -g billion-context@pr-683Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf billion-context-pr683.tgz
npm install -g packageThis comment is automatically updated on each push. |
[bot] 🏷 ## Review verdict: ready for human merge Duplicate screening — searched open/closed issues & PRs for Windows/codex/MCP-injection delivery; no other item covers this. This PR implements #681 (root-cause fix), not a duplicate of anything; #679 (dsh spawn crash) is a different mechanism and stays separate. Triage / layering — the reported symptom is "MCP server never registers on Windows"; the root cause is structural, not a quoting bug: What I verified (local, node v22.23.2):
Code-level findings:
Minor observations (report-only, not blocking):
I made no code changes — nothing needed fixing. Merge is human-only per repo rules: #683 中文摘要:审核了 PR #683(Windows 上改用 CODEX_HOME 文件覆盖层投递 codex MCP server,根治 cmd.exe 无法传递带引号路径导致内联 TOML 失效的问题)——根因判断正确、方案打到核心,typecheck/build 通过、合入当前 master 后全量测试 1301/1301 绿、diff 干净无越界改动,可以合并。 |
What & why
Fixes #681.
On Windows every
bili codexlaunch rides an npm.cmdshim throughcmd.exe. The default MCP injection passes the bili server definition inline:When node lives under a spaced path (the stock location
C:\Program Files\nodejs\node.exe), that single argv token contains double quotes and spaces.cmd.exetreats\"purely as a quote-state toggle and has no escape for a literal quote, so it strips the token's surrounding quotes before the shim sees it. Codex then receives an unquoted TOML value with spaces — invalid TOML — so thebiliMCP server never registers and plugin-mode compression silently never activates.This is broader than spaced paths: any Windows absolute path in an inline
-cvalue breaks, because a valid TOML string requires enclosing quotes that cmd.exe always strips. No quoting scheme can fix it — the incompatibility is fundamental.Fix
Stop encoding the path into argv on Windows. Deliver
[mcp_servers.bili]via a file instead: a persistent<CODEX_HOME>-bilioverlay (reusing the proven pi/omp/dsh overlay machinery) whose mergedconfig.tomlholds the block, pointed at byCODEX_HOME. Every real-home entry exceptconfig.tomlis shared (auth.json, sessions, model settings survive). POSIX keeps the byte-identical inline-cargs (gated onprocess.platform === "win32"), so macOS/Linux are untouched.If the overlay cannot be built (e.g. hollow on a locked-down Windows), injection degrades gracefully to wire mode — codex still runs and compression stays active server-side — with a logged warning rather than a broken launch.
Changes
src/client-config.ts:resolveCodexHome(CODEX_HOME || ~/.codex), re-exported from launcher.src/launcher.ts:prepareCodexHome/mergeCodexBiliBlock/stripCodexBiliBlock/prepareCodexMcpInjection; the codex launch branch now routes throughprepareCodexMcpInjectionafter env is set (covers both direct-URL and MITM sub-branches).tests/launcher.test.ts: 6 new unit tests (resolve + overlay build/replace/preserve + platform gating).Pre-flight
npm run typecheck— cleannpm test— 1240/1241 pass; the single failure is a pre-existing, environment-dependentresolveClientCommandtest (this machine has/usr/bin/codexinstalled) — identical failure on the clean tree, unrelated to this changenpm run build— success