Repository navigation
Report a stdio server that cannot be started as a launch failure - #177
Conversation
A found launcher whose process the OS or the jail refused to start (Windows os error 193 for npm's extensionless npx script, a permission error, a jail without a policy for the command) came back as "malformed mcp response: spawning ... failed", though the server never ran. It is now Error::LaunchFailed under the new LaunchFailed error name, contract 1.32. 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): Report a stdio server that cannot be started as a launch failure. This pull request separates "the launcher could not be started" from "the server said something malformed". A stdio server whose command is found but whose process cannot be started (Windows os error 193 for npm's extensionless `npx`, a permission error, a jail refusal) previously surfaced as a `MalformedResponse`; it now surfaces as a new `Error::LaunchFailed { command, detail }` carried under a new wire name, `ai.tinyhumans.tinymcp.Error.LaunchFailed`, registered in the bus crate's `ALL` list. The command-not-found path is unchanged and remains `MissingRuntime`. Because a contract name was added, the shipped contract version moves to 1.32 and the version-pinning test is updated to match. The latest-push delta is unavailable — the review state holds the prior reviewed head and rendered evidence but no trusted base-to-head comparison — so this summary describes the whole pull request only, not a push delta. Review snapshot
Completeness: Complete What changedA stdio spawn failure is now reported as a launch failure rather than a protocol failure. The client's `initialize` maps a failed `spawn_process` call to `Error::LaunchFailed { command, detail }`, matching that variant to the new `errors::LAUNCH_FAILED` name in `wire_name`, and the new name is added to the bus crate's `ALL` list so it participates in the error-table invariants. The `initialize` `# Errors` documentation is corrected to distinguish `MissingRuntime` (command not found on the resolved path), `LaunchFailed` (found but not startable, or refused by the jail), `MalformedResponse` (reply shape wrong) and `UnsupportedProtocolVersion` (server settles on an unspoken version). The shipped contract version is bumped to 1.32 with a history entry for the `LaunchFailed` addition, and the pinning test asserts the new value. The cross-cutting error fixtures gain the new variant, and a new stdio test drives a refusing spawner and asserts both the variant with its detail and the wire-name mapping. Features
Tests
FindingsNo active actionable findings. Before mergeNone. How this fits togetherflowchart LR
n0["Error<br/>changed"]:::changed
n1["assorted_other_errors<br/>changed"]:::changed
n2["McpStdioClient<br/>changed"]:::changed
n3["against_a_fake_server<br/>changed"]:::changed
n4["one_of_every_variant"]:::impacted
n5["StdioSpawner"]:::impacted
n6["every_message_is_lowercase_and_unpunctuated"]:::impacted
n7["bare_unauthorized_error"]:::impacted
n8["sync"]:::impacted
n9["StdioLaunch"]:::impacted
n1 -->|uses| n0
n2 -->|uses| n5
n2 -->|uses| n8
n3 -->|uses| n5
n4 -->|uses| n0
n4 -->|calls| n1
n5 -->|uses| n9
n6 -->|calls| n1
n6 -->|tests| n1
n6 -->|calls| n7
n6 -->|tests| n7
n7 -->|uses| n0
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
# Conflicts: # crates/tinymcp-bus/src/version/mod.rs # crates/tinymcp-bus/src/version/mod_tests.rs
# Conflicts: # crates/tinymcp-bus/src/version/mod.rs # crates/tinymcp-bus/src/version/mod_tests.rs
Summary
When a stdio server's launcher is found but its process can't be started, the host got
malformed mcp response: spawningnpxfailed: …, though the server never ran and nothing it said was malformed. This happens with Windows os error 193 for npm's extensionlessnpxscript (the case in #168), with a permission error, or when the jail refuses the command. Hosts and Sentry grouped these with real protocol failures.These now come back as a new
Error::LaunchFailed { command, detail }under a new error name,ai.tinyhumans.tinymcp.Error.LaunchFailed. The command-not-found case staysMissingRuntime, as before.Related issue
Closes #168. The PATHEXT resolution half is in #175.
API or behavior changes
tinymcp_bus::errors::LAUNCH_FAILED(inALL) and a newError::LaunchFailedvariant.MalformedResponsename now usesLaunchFailed. Per the error table's rule, a host that doesn't know the name treats it as a generic failure. openhuman matches on neither name.Validation
On our Linux CI runner, at b029ac1db5. The head differs only by applying
cargo fmt's patch:cargo clippy --all-targets --all-features -- -D warnings: 0 errors, same as main.cargo buildandRUSTDOCFLAGS="-D warnings" cargo doc: ok.cargo test -p tinymcp transport::stdio: 103 passed.-p tinymcp error: 88 passed.-p tinymcp-bus version: 7 passed.cargo test --workspace --no-fail-fast: no failures unique to this branch. The 3 failures are main's known full-suite timeouts (registry::boot,tinybus_module::directories), which also fail on main.Error::malformedfailsa_process_that_cannot_be_started_is_a_launch_failure_not_a_bad_response, which then getsMalformedResponse { detail: "jail refused" }.Tests
a_process_that_cannot_be_started_is_a_launch_failure_not_a_bad_response: a spawner that refuses the launch, as a jail or Windows would, givesLaunchFailedwith the reason, under theLAUNCH_FAILEDname.malformedfails the new test.Documentation
Rustdoc on the variant, the name and
initialize's# Errors, and the contract version history.Checklist
#[allow(...)],#[ignore], or relaxed lints.envcontents in the diff or the description