Skip to content

StdioClientTransport: explicit Path in env is ignored on Windows (inherited PATH wins) #2859

Description

@ohad6k

Summary

On Windows, an explicit Path (or any casing other than PATH) passed in StdioServerParameters.env is silently ignored. The inherited PATH from getDefaultEnvironment() wins, so the server runs with the parent's PATH instead of the one the caller configured.

This is separate from #2037 (which variables are inherited). It is about precedence when the caller's key differs only in case.

Where

packages/client/src/client/stdio.ts (main @ 7f7a94c):

env: {
    ...getDefaultEnvironment(),   // emits the key 'PATH'
    ...this._serverParams.env     // caller passes 'Path'
},

The spread keeps both PATH and Path as separate keys. On Windows, Node's child_process resolves duplicate case-insensitive keys by taking the first one in sorted order, and PATH sorts before Path, so the inherited value reaches the child.

Repro (Windows, Node v24.12.0)

import { spawnSync } from 'node:child_process';
const env = { PATH: process.env.PATH, SYSTEMROOT: process.env.SYSTEMROOT, ...{ Path: 'C:\explicit-only' } };
const r = spawnSync(process.execPath, ['-e', 'console.log(process.env.PATH)'], { env });
console.log(r.stdout.toString());

Expected: C:\explicit-only
Actual: the parent's full PATH.

Path is the casing Windows itself uses in process.env keys listings and in many config files, so callers hit this without doing anything unusual.

Suggested fix

When building the merged env on win32, skip an inherited default whose key matches an explicit key case-insensitively (or delete it before spreading). The same fix was proposed for the AI SDK's MCP stdio transport in vercel/ai#21431 / #21435, with regression tests for Path casing.

Happy to open a PR with a test if that's welcome.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions