diff --git a/AGENTS.md b/AGENTS.md index 5d12644..0630b8a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -57,7 +57,7 @@ test/ managedLifecycle.test.ts Managed install with real file I/O (26 tests) mcpConfig.test.ts MCP config with real temp directories (14 tests) managedInstall.test.ts Managed Update compares latest vs managed binary (10 tests) - mcpRegister.test.ts Native MCP definition helper for binary path (2 tests) + mcpRegister.test.ts Native MCP definition helper for binary path (6 tests) statusRefresh.test.ts Status and MCP refresh order after input change (1 test) outputChannel.test.ts Output channel logging wrapper (22 tests) patchloomCli.test.ts Patchloom CLI integration with real binary + managed install e2e MCP (49 tests incl. e2e) diff --git a/src/mcp/register.ts b/src/mcp/register.ts index 5fd219c..ea60348 100644 --- a/src/mcp/register.ts +++ b/src/mcp/register.ts @@ -61,6 +61,8 @@ interface VsCodeLmWithMcp { interface VsCodeWithMcpApi { EventEmitter: typeof VSCode.EventEmitter; + Uri: { file(path: string): VSCode.Uri }; + workspace: { workspaceFolders?: readonly VSCode.WorkspaceFolder[] }; lm: VsCodeLmWithMcp; McpStdioServerDefinition?: McpStdioServerDefinitionCtor; } @@ -76,12 +78,17 @@ function mcpStdioCtor(vscode: VsCodeWithMcpApi): McpStdioServerDefinitionCtor | export function createMcpStdioServerDefinition( Ctor: McpStdioServerDefinitionCtor, - descriptor: McpServerBinaryDescriptor + descriptor: McpServerBinaryDescriptor, + cwd?: unknown ): unknown | undefined { const args = [...descriptor.args]; const env = descriptor.env ?? {}; try { - return new Ctor(descriptor.label, descriptor.command, args, env); + const definition = new Ctor(descriptor.label, descriptor.command, args, env); + if (cwd !== undefined && definition && typeof definition === "object") { + (definition as { cwd?: unknown }).cwd = cwd; + } + return definition; } catch { return undefined; } @@ -118,9 +125,10 @@ export async function registerMcpServerProviderWithBinary(context: VSCode.Extens onDidChangeMcpServerDefinitions: emitter.event, provideMcpServerDefinitions: async () => { const runtime = await getPatchloomRuntimeConfig(); + const workspaceCwd = vscode.workspace.workspaceFolders?.[0]?.uri; const definitions: unknown[] = []; for (const descriptor of mcpServerDefinitionsForBinary(resolvedBinaryPath, runtime.extraEnv)) { - const definition = createMcpStdioServerDefinition(Ctor, descriptor); + const definition = createMcpStdioServerDefinition(Ctor, descriptor, workspaceCwd); if (definition !== undefined) { definitions.push(definition); } diff --git a/test/unit/mcpRegister.test.ts b/test/unit/mcpRegister.test.ts index e274013..de2096f 100644 --- a/test/unit/mcpRegister.test.ts +++ b/test/unit/mcpRegister.test.ts @@ -6,6 +6,8 @@ import { } from "../../src/mcp/register.js"; class FakeStdio { + cwd?: { fsPath: string }; + constructor( public label: string, public command: string, @@ -58,3 +60,16 @@ test("createMcpStdioServerDefinition forwards PATCHLOOM env", () => { }) as FakeStdio; assert.equal(instance.env.PATCHLOOM_MCP_SURFACE, "core"); }); + +test("createMcpStdioServerDefinition assigns workspace cwd after construct", () => { + const instance = createMcpStdioServerDefinition( + FakeStdio, + { + label: "Patchloom MCP", + command: "/opt/patchloom", + args: ["mcp-server"] + }, + { fsPath: "/workspace/demo" } + ) as FakeStdio; + assert.equal(instance.cwd?.fsPath, "/workspace/demo"); +});