diff --git a/core/context/mcp/MCPConnection.ts b/core/context/mcp/MCPConnection.ts index f1199066f2..d25e9f6a0e 100644 --- a/core/context/mcp/MCPConnection.ts +++ b/core/context/mcp/MCPConnection.ts @@ -1,5 +1,6 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; +import { homedir } from "os"; import { fileURLToPath } from "url"; import { @@ -476,6 +477,13 @@ Org-level secrets can only be used for MCP by Background Agents (https://docs.co if (resolved.startsWith("file://")) { return fileURLToPath(resolved); } + // Remote URIs (e.g. vscode-remote://ssh-remote+host/path) cannot be + // used as a local cwd for child_process.spawn(). When the extension + // runs in the Local Extension Host on Windows while connected to a + // remote workspace, fall back to the user's home directory. + if (resolved.includes("://")) { + return homedir(); + } return resolved; } return resolved; diff --git a/core/context/mcp/MCPConnection.vitest.ts b/core/context/mcp/MCPConnection.vitest.ts index 7920a9a1dd..adb4b9c549 100644 --- a/core/context/mcp/MCPConnection.vitest.ts +++ b/core/context/mcp/MCPConnection.vitest.ts @@ -175,6 +175,17 @@ describe("MCPConnection", () => { ); expect(mockResolve).toHaveBeenCalledWith("src", ide); }); + + it("should fall back to homedir for remote URIs that cannot be used as local cwd", async () => { + const ide = {} as any; + vi.spyOn(ideUtils, "resolveRelativePathInDir").mockResolvedValue( + "vscode-remote://ssh-remote+192.168.137.2/home/user/project", + ); + const conn = new MCPConnection(baseOptions, { ide }); + + const { homedir } = require("os"); + await expect((conn as any).resolveCwd("src")).resolves.toBe(homedir()); + }); }); describe("connectClient", () => {