Repository navigation
Resolve a bare Windows command through PATHEXT before the bare name - #175
Conversation
executable_candidates tried the bare name first on Windows, and any file counts as executable off Unix. Node installs an extensionless npx shell script beside npx.cmd, so a stdio server with command npx resolved to the script, and CreateProcessW refused it with os error 193 (%1 is not a valid Win32 application). That is the most common stdio MCP config. Try every PATHEXT variant first and the bare name last, so npx resolves to npx.cmd while a real extensionless executable with nothing beside it still resolves. pathext_candidates holds the ordering so it is tested on every platform; a Windows-only test checks the npx/npx.cmd case on disk. Closes tinyhumansai#168
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Tiny Sweeper reviewReviewed head: Verdict: Ready for maintainer review · Priority: none Diagnostics and supporting detailsFull summaryPull request purpose (title): Resolve a bare Windows command through PATHEXT before the bare name. This PR fixes the most common Windows stdio MCP configuration failing with os error 193 (`%1 is not a valid Win32 application`): Node installs an extensionless `npx` shell script beside `npx.cmd`, Windows command resolution tried the bare name first, and because any file counts as executable off Unix the script was selected and `CreateProcessW` refused it. The pull request reorders resolution so every `PATHEXT` variant is tried before the bare name, letting `npx` resolve to `npx.cmd` while a genuine extensionless executable with nothing beside it still resolves; behaviour outside Windows is unchanged. No trusted base-to-head diff was available, so no push delta is described. Review snapshot
Completeness: Complete What changedOn Windows, command resolution in the stdio spawn environment module now enumerates `<name><ext>` candidates for each `PATHEXT` entry first and appends the bare `<name>` last, instead of trying the bare name first. The ordering is factored into a `pathext_candidates` helper gated for Windows and tests, with rustdoc explaining why the bare name is last (Node's extensionless `npx` script is rejected by `CreateProcessW`, issue #168) and that a real extensionless executable still resolves. Empty `PATHEXT` segments are skipped and the default `.COM;.EXE;.BAT;.CMD` list is used when the variable is absent. Non-Windows resolution paths are untouched. Two tests cover the reordering: a platform-independent order assertion and a Windows-only on-disk case. The latest-push delta could not be computed from trusted evidence, so only the whole-pull-request behaviour is described. Features
Tests
FindingsNo active actionable findings. Before mergeNone. Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
Summary
On Windows, a stdio server with command
npxfailed with os error 193,%1 is not a valid Win32 application. Node installs an extensionlessnpxshell script besidenpx.cmd.executable_candidatestried the bare name first, and any file counts as executable off Unix, so resolution picked the script andCreateProcessWrefused it. That's the most common stdio MCP config.Every
PATHEXTvariant is now tried before the bare name.npxresolves tonpx.cmd, and a real extensionless executable with nothing beside it still resolves, which is what the existing tests expect.Related issue
Part of #168 (PATHEXT resolution; the launch-error classification follows in its own PR) (Sentry TAURI-RUST-12J8, 12BC, 1605).
API or behavior changes
On Windows only, resolution order changes:
<name><ext>for eachPATHEXTentry, then<name>. Nothing changes elsewhere.Not in this PR: reporting a spawn failure as a launch error instead of
malformed mcp response. That needs a new bus error name and so a contract bump, which #164 already takes. It'll come as a follow-up.Validation
On our Linux CI runner, at 22c0eb8:
cargo fmt --all -- --check: clean.cargo clippy --all-targets --all-features -- -D warnings: 0 errors, same as main.cargo build --all-targets --all-features: ok.cargo test -p tinymcp spawn_env: 42 passed, includingpathext_variants_come_before_the_bare_name.cargo test --workspace: no failures unique to this branch. The 5 failures are main's known full-suite timeouts inregistry::bootandtinybus_module::directories, none of them nearspawn_env.pathext_variants_come_before_the_bare_name(barebin/npxlisted beforebin/npx.COM).The on-disk Windows test runs on this PR's windows-latest job.
Tests
pathext_variants_come_before_the_bare_namechecks the ordering on every platform. With main's order it fails.a_bare_name_prefers_its_pathext_variant_over_an_extensionless_script(Windows) puts bothnpxandnpx.cmdon disk and must resolve to the.cmd.Documentation
The rustdoc on
pathext_candidatesexplains the order.Checklist
#[allow(...)],#[ignore], or relaxed lints.envcontents in the diff or the description