mirror of
https://github.com/openai/codex.git
synced 2026-05-02 10:26:45 +00:00
fix: resolve Windows MCP server execution for script-based tools (#3828)
## 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:** ```bash 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. --------- Co-authored-by: Eric Traut <etraut@openai.com>
This commit is contained in:
@@ -47,6 +47,7 @@ use crate::logging_client_handler::LoggingClientHandler;
|
||||
use crate::oauth::OAuthCredentialsStoreMode;
|
||||
use crate::oauth::OAuthPersistor;
|
||||
use crate::oauth::StoredOAuthTokens;
|
||||
use crate::program_resolver;
|
||||
use crate::utils::apply_default_headers;
|
||||
use crate::utils::build_default_headers;
|
||||
use crate::utils::convert_call_tool_result;
|
||||
@@ -91,13 +92,20 @@ impl RmcpClient {
|
||||
cwd: Option<PathBuf>,
|
||||
) -> io::Result<Self> {
|
||||
let program_name = program.to_string_lossy().into_owned();
|
||||
let mut command = Command::new(&program);
|
||||
|
||||
// Build environment for program resolution and subprocess
|
||||
let envs = create_env_for_mcp_server(env, env_vars);
|
||||
|
||||
// Resolve program to executable path (platform-specific)
|
||||
let resolved_program = program_resolver::resolve(program, &envs)?;
|
||||
|
||||
let mut command = Command::new(resolved_program);
|
||||
command
|
||||
.kill_on_drop(true)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.env_clear()
|
||||
.envs(create_env_for_mcp_server(env, env_vars))
|
||||
.envs(envs)
|
||||
.args(&args);
|
||||
if let Some(cwd) = cwd {
|
||||
command.current_dir(cwd);
|
||||
|
||||
Reference in New Issue
Block a user