Skip to content

Conversation

@25621
Copy link

@25621 25621 commented Sep 18, 2025

What?

Fixes MCP server initialization failures on Windows when using script-based tools like npx, pnpm, and yarn that rely on .cmd/.bat files rather than .exe binaries.

Fixes #2945

Why?

Windows users encounter "program not found" errors when configuring MCP servers with commands like npx in their ~/.codex/config.toml. This happens because:

  • Tools like npx are batch scripts (npx.cmd) on Windows, not executable binaries
  • Rust's std::process::Command bypasses the shell and cannot execute these scripts directly
  • The Windows shell normally handles this by checking PATHEXT for executable extensions

Without this fix, Windows users must specify full paths or add .cmd extensions manually, which breaks cross-platform compatibility.

How?

Added platform-specific program resolution using the which crate to find the correct executable path:

  • Windows: Resolves programs through PATH/PATHEXT to find .cmd/.bat scripts
  • Unix: Returns the program unchanged (no-op, as Unix handles scripts natively)

Changes

  • Added which = "6" dependency to mcp-client/Cargo.toml
  • Implemented program_resolver module in mcp_client.rs with platform-specific resolution
  • Added comprehensive tests for both Windows and Unix behavior

Testing

Added platform-specific tests to verify:

  • Unix systems execute scripts without extensions
  • Windows fails without proper extensions
  • Windows succeeds with explicit extensions
  • Cross-platform resolution enables successful execution

Tested on:

  • Windows 11 (NT 10.0.26100.0 x64)
  • PowerShell 5.1 & 7+, CMD, Git Bash
  • MCP servers: playwright, context7, supabase
  • WSL (verified no regression)

Local checks passed:

cargo test && cargo clippy --tests && cargo fmt -- --config imports_granularity=Item

Results

Before:

🖐 MCP client for `playwright` failed to start: program not found

After:

🖐 MCP client for `playwright` failed to start: request timed out

Windows users can now use simple commands like npx in their config without specifying full paths or extensions. The timeout issue is a separate concern that will be addressed in a follow-up PR.

@github-actions
Copy link

github-actions bot commented Sep 18, 2025

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@25621
Copy link
Author

25621 commented Sep 18, 2025

I have read the CLA Document and I hereby sign the CLA

github-actions bot added a commit that referenced this pull request Sep 18, 2025
dylan-hurd-oai pushed a commit that referenced this pull request Oct 29, 2025
# Preserve PATH precedence & fix Windows MCP env propagation

## Problem & intent

Preserve user PATH precedence and reduce Windows setup friction for MCP
servers by avoiding PATH reordering and ensuring Windows child processes
receive essential env vars.

- Addresses: #4180 #5225 #2945 #3245 #3385 #2892 #3310 #3457 #4370  
- Supersedes: #4182, #3866, #3828 (overlapping/inferior once this
merges)
- Notes: #2626 / #2646 are the original PATH-mutation sources being
corrected.

---

## Before / After

**Before**  
- PATH was **prepended** with an `apply_patch` helper dir (Rust + Node
wrapper), reordering tools and breaking virtualenvs/shims on
macOS/Linux.
- On Windows, MCP servers missed core env vars and often failed to start
without explicit per-server env blocks.

**After**  
- Helper dir is **appended** to PATH (preserves user/tool precedence).  
- Windows MCP child env now includes common core variables and mirrors
`PATH` → `Path`, so typical CLIs/plugins work **without** per-server env
blocks.

---

## Scope of change

### `codex-rs/arg0/src/lib.rs`
- Append temp/helper dir to `PATH` instead of prepending.

### `codex-cli/bin/codex.js`
- Mirror the same append behavior for the Node wrapper.

### `codex-rs/rmcp-client/src/utils.rs`
- Expand Windows `DEFAULT_ENV_VARS` (e.g., `COMSPEC`, `SYSTEMROOT`,
`PROGRAMFILES*`, `APPDATA`, etc.).
- Mirror `PATH` → `Path` for Windows child processes.  
- Small unit test; conditional `mut` + `clippy` cleanup.

---

## Security effects

No broadened privileges. Only environment propagation for well-known
Windows keys on stdio MCP child processes. No sandbox policy changes and
no network additions.

---

## Testing evidence

**Static**  
- `cargo fmt`  
- `cargo clippy -p codex-arg0 -D warnings` → **clean**  
- `cargo clippy -p codex-rmcp-client -D warnings` → **clean**  
- `cargo test -p codex-rmcp-client` → **13 passed**

**Manual**  
- Local verification on Windows PowerShell 5/7 and WSL (no `unused_mut`
warnings on non-Windows targets).

---

## Checklist

- [x] Append (not prepend) helper dir to PATH in Rust and Node wrappers
- [x] Windows MCP child inherits core env vars; `PATH` mirrored to
`Path`
- [x] `cargo fmt` / `clippy` clean across touched crates  
- [x] Unit tests updated/passing where applicable  
- [x] Cross-platform behavior preserved (macOS/Linux PATH precedence
intact)
vinhnx pushed a commit to vinhnx/codex that referenced this pull request Nov 2, 2025
…#5579)

# Preserve PATH precedence & fix Windows MCP env propagation

## Problem & intent

Preserve user PATH precedence and reduce Windows setup friction for MCP
servers by avoiding PATH reordering and ensuring Windows child processes
receive essential env vars.

- Addresses: openai#4180 openai#5225 openai#2945 openai#3245 openai#3385 openai#2892 openai#3310 openai#3457 openai#4370  
- Supersedes: openai#4182, openai#3866, openai#3828 (overlapping/inferior once this
merges)
- Notes: openai#2626 / openai#2646 are the original PATH-mutation sources being
corrected.

---

## Before / After

**Before**  
- PATH was **prepended** with an `apply_patch` helper dir (Rust + Node
wrapper), reordering tools and breaking virtualenvs/shims on
macOS/Linux.
- On Windows, MCP servers missed core env vars and often failed to start
without explicit per-server env blocks.

**After**  
- Helper dir is **appended** to PATH (preserves user/tool precedence).  
- Windows MCP child env now includes common core variables and mirrors
`PATH` → `Path`, so typical CLIs/plugins work **without** per-server env
blocks.

---

## Scope of change

### `codex-rs/arg0/src/lib.rs`
- Append temp/helper dir to `PATH` instead of prepending.

### `codex-cli/bin/codex.js`
- Mirror the same append behavior for the Node wrapper.

### `codex-rs/rmcp-client/src/utils.rs`
- Expand Windows `DEFAULT_ENV_VARS` (e.g., `COMSPEC`, `SYSTEMROOT`,
`PROGRAMFILES*`, `APPDATA`, etc.).
- Mirror `PATH` → `Path` for Windows child processes.  
- Small unit test; conditional `mut` + `clippy` cleanup.

---

## Security effects

No broadened privileges. Only environment propagation for well-known
Windows keys on stdio MCP child processes. No sandbox policy changes and
no network additions.

---

## Testing evidence

**Static**  
- `cargo fmt`  
- `cargo clippy -p codex-arg0 -D warnings` → **clean**  
- `cargo clippy -p codex-rmcp-client -D warnings` → **clean**  
- `cargo test -p codex-rmcp-client` → **13 passed**

**Manual**  
- Local verification on Windows PowerShell 5/7 and WSL (no `unused_mut`
warnings on non-Windows targets).

---

## Checklist

- [x] Append (not prepend) helper dir to PATH in Rust and Node wrappers
- [x] Windows MCP child inherits core env vars; `PATH` mirrored to
`Path`
- [x] `cargo fmt` / `clippy` clean across touched crates  
- [x] Unit tests updated/passing where applicable  
- [x] Cross-platform behavior preserved (macOS/Linux PATH precedence
intact)
@etraut-openai
Copy link
Collaborator

Thanks for the contribution, and apologies for the slow response. We received a large number of PRs, and we're just now getting through the backlog.

It looks like this PR has gone stale. If this PR is still relevant, could you please resolve the merge conflicts and make sure the tests still run? Thanks!

@etraut-openai etraut-openai added the needs-response Additional information is requested label Nov 7, 2025
@25621 25621 force-pushed the fix/windows-mcp-script-resolution branch from b12b045 to 5c75710 Compare November 7, 2025 15:07
25621 added a commit to 25621/codex that referenced this pull request Nov 7, 2025
…ed tools

This ports the fix from the original PR openai#3828 to rmcp-client,
which replaced mcp-client in PR openai#5529.

On Windows, script-based MCP servers (e.g., npx, pnpm, yarn) that
rely on .cmd or .bat files fail to execute. This happens because
Rust's Command does not resolve scripts via PATHEXT like the
shell does.

This fix uses the which crate to resolve the full executable path
(including .cmd/.bat extensions) before spawning the process,
allowing these tools to run correctly.

Changes:
- Add which crate dependency to rmcp-client/Cargo.toml
- Implement program_resolver module with platform-specific logic:
  * Windows: Resolves .cmd/.bat scripts using which::which_in
  * Unix: No-op (OS handles shebangs natively)
- Modify new_stdio_client to resolve program path before Command::new
- Add unit tests for program resolution on both platforms

Fixes: openai#2945
@25621 25621 force-pushed the fix/windows-mcp-script-resolution branch from 5c75710 to 74e4237 Compare November 7, 2025 15:17
@25621
Copy link
Author

25621 commented Nov 7, 2025

Hi @etraut-openai,

Thank you for reviewing! I've resolved the conflicts and updated the PR:

The Windows script resolution logic remains unchanged - using the which crate to properly resolve .cmd/.bat scripts that Windows requires for tools like npx, pnpm, and yarn.

Ready for merge. Let me know if you need any adjustments!

@etraut-openai
Copy link
Collaborator

@25621, looks like there are some lint (cargo clippy) issues remaining.

…ed tools

This ports the fix from the original PR openai#3828 to rmcp-client,
which replaced mcp-client in PR openai#5529.

On Windows, script-based MCP servers (e.g., npx, pnpm, yarn) that
rely on .cmd or .bat files fail to execute. This happens because
Rust's Command does not resolve scripts via PATHEXT like the
shell does.

This fix uses the which crate to resolve the full executable path
(including .cmd/.bat extensions) before spawning the process,
allowing these tools to run correctly.

Changes:
- Add which crate dependency to rmcp-client/Cargo.toml
- Implement program_resolver module with platform-specific logic:
  * Windows: Resolves .cmd/.bat scripts using which::which_in
  * Unix: No-op (OS handles shebangs natively)
- Modify new_stdio_client to resolve program path before Command::new
- Add unit tests for program resolution on both platforms

Fixes: openai#2945
@25621 25621 force-pushed the fix/windows-mcp-script-resolution branch from 74e4237 to 577b2a6 Compare November 8, 2025 01:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-response Additional information is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP client for playwright failed to start: program not found

2 participants