diff --git a/.changeset/fix-default-inherited-env-vars-windows.md b/.changeset/fix-default-inherited-env-vars-windows.md new file mode 100644 index 0000000000..beabc436cf --- /dev/null +++ b/.changeset/fix-default-inherited-env-vars-windows.md @@ -0,0 +1,5 @@ +--- +'@modelcontextprotocol/client': patch +--- + +Add missing Windows environment variables to `DEFAULT_INHERITED_ENV_VARS`: `PATHEXT`, `COMSPEC`, `PROGRAMFILES(X86)`, `PROGRAMW6432`, and `WINDIR`. Without `PATHEXT`, spawning common tools like `npm` or `git` from a stdio MCP server fails with `ENOENT` on Windows because Node can't resolve the `.cmd`/`.exe` extension. diff --git a/packages/client/src/client/stdio.ts b/packages/client/src/client/stdio.ts index 5dcb8ef9a6..6d59f6a9e3 100644 --- a/packages/client/src/client/stdio.ts +++ b/packages/client/src/client/stdio.ts @@ -47,17 +47,22 @@ export const DEFAULT_INHERITED_ENV_VARS = process.platform === 'win32' ? [ 'APPDATA', + 'COMSPEC', 'HOMEDRIVE', 'HOMEPATH', 'LOCALAPPDATA', 'PATH', + 'PATHEXT', 'PROCESSOR_ARCHITECTURE', + 'PROGRAMFILES', + 'PROGRAMFILES(X86)', + 'PROGRAMW6432', 'SYSTEMDRIVE', 'SYSTEMROOT', 'TEMP', 'USERNAME', 'USERPROFILE', - 'PROGRAMFILES' + 'WINDIR' ] : /* list inspired by the default env inheritance of sudo */ ['HOME', 'LOGNAME', 'PATH', 'SHELL', 'TERM', 'USER']; diff --git a/packages/client/test/client/stdio.test.ts b/packages/client/test/client/stdio.test.ts index 28a7834bcb..ed540de7b7 100644 --- a/packages/client/test/client/stdio.test.ts +++ b/packages/client/test/client/stdio.test.ts @@ -1,7 +1,7 @@ import type { JSONRPCMessage } from '@modelcontextprotocol/core'; import type { StdioServerParameters } from '../../src/client/stdio.js'; -import { StdioClientTransport } from '../../src/client/stdio.js'; +import { DEFAULT_INHERITED_ENV_VARS, StdioClientTransport } from '../../src/client/stdio.js'; // Configure default server parameters based on OS // Uses 'more' command for Windows and 'tee' command for Unix/Linux @@ -77,3 +77,33 @@ test('should return child process pid', async () => { await client.close(); expect(client.pid).toBeNull(); }); + +test('DEFAULT_INHERITED_ENV_VARS matches the host platform', () => { + if (process.platform === 'win32') { + // Variables Windows tooling needs to resolve executables and shells. + // Missing PATHEXT or COMSPEC causes spawn ENOENT for npm/git/etc. + expect(DEFAULT_INHERITED_ENV_VARS).toEqual( + expect.arrayContaining([ + 'APPDATA', + 'COMSPEC', + 'HOMEDRIVE', + 'HOMEPATH', + 'LOCALAPPDATA', + 'PATH', + 'PATHEXT', + 'PROCESSOR_ARCHITECTURE', + 'PROGRAMFILES', + 'PROGRAMFILES(X86)', + 'PROGRAMW6432', + 'SYSTEMDRIVE', + 'SYSTEMROOT', + 'TEMP', + 'USERNAME', + 'USERPROFILE', + 'WINDIR' + ]) + ); + } else { + expect(DEFAULT_INHERITED_ENV_VARS).toEqual(['HOME', 'LOGNAME', 'PATH', 'SHELL', 'TERM', 'USER']); + } +});