fix(skill-mcp): pass workspace directory as cwd to stdio MCP processes

In OpenCode web multi-workspace mode, skill_mcp spawned stdio child
processes inherited process.cwd() instead of the session's workspace
directory. Pass toolContext.directory through SkillMcpClientInfo to
StdioClientTransport's cwd parameter.
This commit is contained in:
lightrabbit
2026-04-14 06:20:55 +00:00
parent f98f7ec7a4
commit df172ac3d5
4 changed files with 29 additions and 0 deletions
@@ -60,6 +60,7 @@ export async function createStdioClient(params: SkillMcpClientConnectionParams):
args,
env: mergedEnv,
stderr: "ignore",
...(info.directory ? { cwd: info.directory } : {}),
})
const client: McpClient = stdioClientDependencies.createClient(
+1
View File
@@ -24,6 +24,7 @@ export interface SkillMcpClientInfo {
skillName: string
sessionID: string
scope?: SkillScope | "local"
directory?: string
}
export interface SkillMcpServerContext {
+26
View File
@@ -192,6 +192,32 @@ describe("skill_mcp tool", () => {
{},
)
})
it("passes toolContext.directory to the manager", async () => {
// given
loadedSkills = [
createMockSkillWithMcp("test-skill", {
"test-server": { command: "echo", args: ["test"] },
}),
]
const callToolSpy = spyOn(manager, "callTool").mockResolvedValue({ content: [] } as never)
const tool = createSkillMcpTool({
manager,
getLoadedSkills: () => loadedSkills,
getSessionID: () => "session-1",
})
// when
await tool.execute({ mcp_name: "test-server", tool_name: "some-tool" }, mockContext)
// then
expect(callToolSpy).toHaveBeenCalledWith(
expect.objectContaining({ directory: "/test" }),
expect.any(Object),
"some-tool",
{},
)
})
})
})
+1
View File
@@ -167,6 +167,7 @@ export function createSkillMcpTool(options: SkillMcpToolOptions): ToolDefinition
skillName: found.skill.name,
sessionID,
scope: found.skill.scope,
directory: toolContext.directory,
}
const context: SkillMcpServerContext = {