From 832e35270a74e667754023a4bf008da71e5482eb Mon Sep 17 00:00:00 2001 From: Sudip Date: Wed, 5 Aug 2026 12:56:43 +0100 Subject: [PATCH] fix: pass Windows AppData vars into MCP child env APPDATA and LOCALAPPDATA are commonly required by Windows MCP servers for config/cache paths. Forward them in the stdio child allowlist. --- .changeset/mcp-child-env-appdata.md | 5 +++++ src/connectors/mcp-client.ts | 9 ++++++--- test/mcp-client.test.ts | 16 +++++++++++++++- 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 .changeset/mcp-child-env-appdata.md diff --git a/.changeset/mcp-child-env-appdata.md b/.changeset/mcp-child-env-appdata.md new file mode 100644 index 00000000..2725ec0a --- /dev/null +++ b/.changeset/mcp-child-env-appdata.md @@ -0,0 +1,5 @@ +--- +"openwiki": patch +--- + +Pass Windows `APPDATA` and `LOCALAPPDATA` into stdio MCP child environments so local MCP servers can resolve their config and cache directories. diff --git a/src/connectors/mcp-client.ts b/src/connectors/mcp-client.ts index ef5b9c62..33e48897 100644 --- a/src/connectors/mcp-client.ts +++ b/src/connectors/mcp-client.ts @@ -733,15 +733,18 @@ function resolveChildEnv( } // Base environment variables an MCP subprocess may legitimately need to run -// (locating binaries, resolving the home dir, temp paths, terminal behavior). -// Deliberately excludes OpenWiki credentials so a spawned MCP server command -// cannot read the user's API keys and OAuth refresh tokens out of process.env. +// (locating binaries, resolving the home dir, AppData caches on Windows, temp +// paths, terminal behavior). Deliberately excludes OpenWiki credentials so a +// spawned MCP server command cannot read the user's API keys and OAuth refresh +// tokens out of process.env. const CHILD_ENV_ALLOWLIST = [ "PATH", "HOME", "HOMEPATH", "HOMEDRIVE", "USERPROFILE", + "APPDATA", + "LOCALAPPDATA", "TMPDIR", "TEMP", "TMP", diff --git a/test/mcp-client.test.ts b/test/mcp-client.test.ts index 44cc55e5..1824df43 100644 --- a/test/mcp-client.test.ts +++ b/test/mcp-client.test.ts @@ -13,13 +13,21 @@ describe("buildChildEnv", () => { const saved: Record = {}; beforeEach(() => { - for (const key of [...SECRET_KEYS, "PATH", "MCP_SERVER_TOKEN"]) { + for (const key of [ + ...SECRET_KEYS, + "PATH", + "APPDATA", + "LOCALAPPDATA", + "MCP_SERVER_TOKEN", + ]) { saved[key] = process.env[key]; } for (const key of SECRET_KEYS) { process.env[key] = `secret-value-for-${key}`; } process.env.PATH = "/usr/bin:/bin"; + process.env.APPDATA = "C:\\Users\\example\\AppData\\Roaming"; + process.env.LOCALAPPDATA = "C:\\Users\\example\\AppData\\Local"; process.env.MCP_SERVER_TOKEN = "declared-token-123"; }); @@ -49,6 +57,12 @@ describe("buildChildEnv", () => { expect(childEnv.PATH).toBe("/usr/bin:/bin"); }); + test("passes through Windows AppData paths used by many MCP servers", () => { + const childEnv = buildChildEnv({}); + expect(childEnv.APPDATA).toBe("C:\\Users\\example\\AppData\\Roaming"); + expect(childEnv.LOCALAPPDATA).toBe("C:\\Users\\example\\AppData\\Local"); + }); + test("resolves only the credentials the transport explicitly declares", () => { const childEnv = buildChildEnv({ MCP_TOKEN: "${MCP_SERVER_TOKEN}" }); expect(childEnv.MCP_TOKEN).toBe("declared-token-123");