fix(skill-mcp): always inherit process.env for MCP servers

- Always merge parent process.env when spawning MCP child processes
- Overlay config.env on top if present (for skill-specific overrides)
- Fixes issue where skills without explicit env: block started with zero environment variables
- Adds 2 tests for env inheritance behavior

🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2026-01-02 16:07:33 +09:00
parent 9a92dc8d95
commit a51ad98182
2 changed files with 56 additions and 4 deletions

View File

@@ -106,4 +106,54 @@ describe("SkillMcpManager", () => {
expect(manager.getConnectedServers()).toEqual([])
})
})
describe("environment variable handling", () => {
it("always inherits process.env even when config.env is undefined", async () => {
// #given
const info: SkillMcpClientInfo = {
serverName: "test-server",
skillName: "test-skill",
sessionID: "session-1",
}
const configWithoutEnv: ClaudeCodeMcpServer = {
command: "node",
args: ["-e", "process.exit(0)"],
}
// #when - attempt connection (will fail but exercises env merging code path)
// #then - should not throw "undefined" related errors for env
try {
await manager.getOrCreateClient(info, configWithoutEnv)
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
expect(message).not.toContain("env")
expect(message).not.toContain("undefined")
}
})
it("overlays config.env on top of inherited process.env", async () => {
// #given
const info: SkillMcpClientInfo = {
serverName: "test-server",
skillName: "test-skill",
sessionID: "session-2",
}
const configWithEnv: ClaudeCodeMcpServer = {
command: "node",
args: ["-e", "process.exit(0)"],
env: {
CUSTOM_VAR: "custom_value",
},
}
// #when - attempt connection
// #then - should not throw, env merging should work
try {
await manager.getOrCreateClient(info, configWithEnv)
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
expect(message).toContain("Failed to connect")
}
})
})
})

View File

@@ -55,18 +55,20 @@ export class SkillMcpManager {
const command = config.command
const args = config.args || []
// Always inherit parent process environment
const mergedEnv: Record<string, string> = {}
if (config.env) {
for (const [key, value] of Object.entries(process.env)) {
if (value !== undefined) mergedEnv[key] = value
}
// Overlay with skill-specific env vars if present
if (config.env) {
Object.assign(mergedEnv, config.env)
}
const transport = new StdioClientTransport({
command,
args,
env: config.env ? mergedEnv : undefined,
env: mergedEnv,
})
const client = new Client(