Skip to content

Commit a111401

Browse files
committed
Adjusted the MCPConnection::resoveCwd() logic + added tests.
1 parent 7ea4d85 commit a111401

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

core/context/mcp/MCPConnection.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
22
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
3+
import { fileURLToPath } from "url";
34

45
import {
56
SSEClientTransport,
@@ -9,7 +10,6 @@ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"
910
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
1011
import { WebSocketClientTransport } from "@modelcontextprotocol/sdk/client/websocket.js";
1112

12-
import { fileURLToPath } from "node:url";
1313
import {
1414
IDE,
1515
MCPConnectionStatus,
@@ -20,6 +20,7 @@ import {
2020
MCPServerStatus,
2121
MCPTool,
2222
} from "../..";
23+
import { resolveRelativePathInDir } from "../../util/ideUtils";
2324
import { getEnvPathFromUserShell } from "../../util/shellPath";
2425
import { getOauthToken } from "./MCPOauth";
2526

@@ -350,16 +351,34 @@ class MCPConnection {
350351
* @returns Current working directory (user-provided cwd or workspace root).
351352
*/
352353
private async resolveCwd(cwd?: string) {
353-
// Return cwd if it has been explicitly set.
354-
if (cwd) {
354+
if (!cwd) {
355+
return this.resolveWorkspaceCwd(undefined);
356+
}
357+
358+
if (cwd.startsWith("file://")) {
359+
return fileURLToPath(cwd);
360+
}
361+
362+
// Return cwd if cwd is an absolute path.
363+
if (cwd.charAt(0) === "/") {
355364
return cwd;
356365
}
357-
// Otherwise use workspace folder.
358-
const workspaceDirs = await this.extras?.ide.getWorkspaceDirs();
359-
if (workspaceDirs) {
360-
if (workspaceDirs.length > 0) {
361-
cwd = fileURLToPath(workspaceDirs[0]);
366+
367+
return this.resolveWorkspaceCwd(cwd);
368+
}
369+
370+
private async resolveWorkspaceCwd(cwd: string | undefined) {
371+
const IDE = await this.extras?.ide;
372+
if (IDE) {
373+
const target = cwd ?? ".";
374+
const resolved = await resolveRelativePathInDir(target, IDE);
375+
if (resolved) {
376+
if (resolved.startsWith("file://")) {
377+
return fileURLToPath(resolved);
378+
}
379+
return resolved;
362380
}
381+
return resolved;
363382
}
364383
return cwd;
365384
}

core/context/mcp/MCPConnection.vitest.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
22
import { beforeEach, describe, expect, it, vi } from "vitest";
3+
import * as ideUtils from "../../util/ideUtils";
34
import MCPConnection from "./MCPConnection";
45

56
// Mock the shell path utility
@@ -152,6 +153,39 @@ describe("MCPConnection", () => {
152153
});
153154
});
154155

156+
describe("resolveCwd", () => {
157+
const baseOptions = {
158+
name: "test-mcp",
159+
id: "test-id",
160+
transport: {
161+
type: "stdio" as const,
162+
command: "test-cmd",
163+
args: [],
164+
},
165+
};
166+
167+
it("should return absolute cwd unchanged", async () => {
168+
const conn = new MCPConnection(baseOptions);
169+
170+
await expect((conn as any).resolveCwd("/tmp/project")).resolves.toBe(
171+
"/tmp/project",
172+
);
173+
});
174+
175+
it("should resolve relative cwd using IDE workspace", async () => {
176+
const ide = {} as any;
177+
const mockResolve = vi
178+
.spyOn(ideUtils, "resolveRelativePathInDir")
179+
.mockResolvedValue("file:///workspace/src");
180+
const conn = new MCPConnection(baseOptions, { ide });
181+
182+
await expect((conn as any).resolveCwd("src")).resolves.toBe(
183+
"/workspace/src",
184+
);
185+
expect(mockResolve).toHaveBeenCalledWith("src", ide);
186+
});
187+
});
188+
155189
describe("connectClient", () => {
156190
const options = {
157191
name: "test-mcp",

0 commit comments

Comments
 (0)