From ae49f839132cda671c7ce5f88cdf5cdfef042ff2 Mon Sep 17 00:00:00 2001 From: roboomp Date: Thu, 11 Jun 2026 04:00:05 +0000 Subject: [PATCH] fix(mcp): hid windows cmd stdio shims Wrap Windows MCP .cmd/.bat stdio launches through a hidden cmd.exe invocation so PATH shims such as npx keep stdio attached without flashing a console. Fixes #2287 --- packages/coding-agent/CHANGELOG.md | 2 +- packages/coding-agent/src/mcp/transports/stdio.ts | 3 +++ packages/coding-agent/test/mcp-stdio-transport.test.ts | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index c1b019efa..7bb3e057e 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -163,7 +163,7 @@ - Fixed pasting into the ask tool's "Other (type your own)" text box (and hook input/editor dialogs) on terminals with OSC 5522 enhanced paste (kitty protocol): the enhanced-paste focus routing only targets components exposing a `pasteText` hook, and the dialog wrappers had none, so the payload was stuffed into the main prompt editor hidden behind the dialog. `HookEditorComponent` and `HookInputComponent` now forward `pasteText` to their inner editor/input (pasting also resets the input dialog's timeout countdown like any keystroke). - Fixed auto-retry giving up after one attempt ("Provider requested Xms wait, exceeds retry.maxDelayMs") on a usage-limit 429 when every sibling account was only momentarily blocked: the retry delay now waits for the earliest sibling unblock when that comes sooner than the provider's multi-hour retry-after, so the next attempt picks up the recovered account instead of failing fast. - Fixed Hindsight `per-project-tagged` mental-model seeding so each project gets its own conventions/decisions models and session context only injects active-project or untagged models ([#2218](https://github.com/can1357/oh-my-pi/issues/2218)). -- Fixed Windows stdio MCP `.cmd` commands by wrapping batch shims with `cmd.exe /d /s /c` using the outer command quotes required by `cmd /s`, while preserving literal `%` and quoted JSON arguments for Codegraph MCP ([#2220](https://github.com/can1357/oh-my-pi/issues/2220)). +- Fixed Windows stdio MCP `.cmd` commands by wrapping batch shims such as `npx.cmd` and `codegraph.cmd` with hidden `cmd.exe /d /s /c` launches using the outer command quotes required by `cmd /s`, while preserving literal `%` and quoted JSON arguments ([#2220](https://github.com/can1357/oh-my-pi/issues/2220), [#2287](https://github.com/can1357/oh-my-pi/issues/2287)). - Fixed the bundled `explore` agent's `thinking-level: med` frontmatter — not a valid effort (`minimal`/`low`/`medium`/`high`/`xhigh`), so it silently parsed to undefined and the agent ran without its intended thinking level - Discovery context-file reads (`~/.claude`, `~/.cursor`, project trees, `@`-imports) now stat-gate to regular files before reading: a FIFO/socket/char device dropped where a context file is expected previously blocked startup forever on a read that can never see EOF. - Fixed the read tool's provider-visible `path` schema and docs so web URLs and internal URI targets (`omp://`, `issue://`, `pr://`, etc.) are advertised alongside local files ([#2215](https://github.com/can1357/oh-my-pi/issues/2215)). diff --git a/packages/coding-agent/src/mcp/transports/stdio.ts b/packages/coding-agent/src/mcp/transports/stdio.ts index 69a35f152..219307be5 100644 --- a/packages/coding-agent/src/mcp/transports/stdio.ts +++ b/packages/coding-agent/src/mcp/transports/stdio.ts @@ -25,6 +25,7 @@ import { isMCPTimeoutEnabled, resolveMCPTimeoutMs } from "../timeout"; /** Subprocess argv for launching an MCP stdio server. */ export interface StdioSpawnCommand { cmd: string[]; + windowsHide?: boolean; } /** Inputs used to resolve platform-specific stdio spawn behavior. */ @@ -153,6 +154,7 @@ export async function resolveStdioSpawnCommand( return { cmd: [resolveComSpec(options.env), "/d", "/s", "/c", buildCmdExeCommand(resolvedCommand, args)], + windowsHide: true, }; } @@ -255,6 +257,7 @@ export class StdioTransport implements MCPTransport { stdin: "pipe", stdout: "pipe", stderr: "pipe", + windowsHide: spawnCommand.windowsHide, }); this.#connected = true; diff --git a/packages/coding-agent/test/mcp-stdio-transport.test.ts b/packages/coding-agent/test/mcp-stdio-transport.test.ts index 190469ed2..f2ff7f59f 100644 --- a/packages/coding-agent/test/mcp-stdio-transport.test.ts +++ b/packages/coding-agent/test/mcp-stdio-transport.test.ts @@ -32,6 +32,7 @@ describe("resolveStdioSpawnCommand", () => { "/c", `""${shim}" "serve" "--mcp""`, ]); + expect(result.windowsHide).toBe(true); } finally { await fs.rm(tempDir, { recursive: true, force: true }); } @@ -63,6 +64,7 @@ describe("resolveStdioSpawnCommand", () => { "/c", `""${shim}" "serve" "--header" "Authorization=^%TOKEN^%""`, ]); + expect(result.windowsHide).toBe(true); } finally { await fs.rm(tempDir, { recursive: true, force: true }); } @@ -94,6 +96,7 @@ describe("resolveStdioSpawnCommand", () => { "/c", `""${shim}" "--config" "{^"a^":^"b&c|d^"}""`, ]); + expect(result.windowsHide).toBe(true); } finally { await fs.rm(tempDir, { recursive: true, force: true }); } @@ -133,6 +136,7 @@ describe("resolveStdioSpawnCommand", () => { "/c", `""${shim}" "serve" "--mcp""`, ]); + expect(result.windowsHide).toBe(true); } finally { await fs.rm(tempDir, { recursive: true, force: true }); } @@ -159,6 +163,7 @@ describe("resolveStdioSpawnCommand", () => { "/c", `""codegraph.cmd" "serve" "--mcp""`, ]); + expect(result.windowsHide).toBe(true); }); it("leaves non-Windows commands untouched", async () => { @@ -168,6 +173,7 @@ describe("resolveStdioSpawnCommand", () => { ); expect(result.cmd).toEqual(["codegraph", "serve", "--mcp"]); + expect(result.windowsHide).toBeUndefined(); }); });