fix(mcp): query tools/resources independently per advertised capability (#6798)#9436
Conversation
Previously, `tools/list` was always called regardless of what the server advertised, with `METHOD_NOT_FOUND` errors handled as a special case and all other errors aborting server startup. This was asymmetric with the `resources/list` branch, which gates on the advertised capability and fails soft on errors. That asymmetry surfaces in warpdotdev#6798: a server with healthy resources but a flaky `tools/list` response would fail to start entirely, even though it could have served resources. Per the MCP spec, list methods should only be invoked when the corresponding capability is advertised, and a single list failure should not block the rest of the server's surface. Make `tools/list` symmetric with `resources/list`: - Skip the call when `capabilities.tools` is `None`. - Log and treat any list failure as "no tools" instead of propagating. Adds a regression unit test covering the six relevant capability shapes to lock in the independent-per-capability behavior. Fixes warpdotdev#6798 Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have the users @david-engelmann on file. In order for us to review and merge your code, each contributor must visit https://cla.warp.dev to read and agree to our CLA. Once you have done so, please comment |
|
@cla-bot check |
|
The cla-bot has been summoned, and re-checked this pull request! |
|
I'm starting a first review of this pull request. I completed the review and posted feedback on this pull request. Comment I'm re-reviewing this pull request in response to a review request. I reviewed this pull request and requested human review from: @peicodes. Comment I reviewed this pull request and requested human review from: @peicodes. Comment I reviewed this pull request and requested human review from: @peicodes. Comment You can view the conversation on Warp. I reviewed this pull request and requested human review from: @peicodes. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This PR updates MCP server startup to query resources/list and tools/list only when the server advertised the corresponding capability, and makes tools/list failures fail soft like existing resources/list handling. The added regression test covers the relevant capability combinations for the new predicate helpers.
Concerns
- No blocking correctness or security concerns found in the changed diff.
Verdict
Found: 0 critical, 0 important, 0 suggestions
Approve
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
|
Thanks for contributing! @peicodes could you take a look? |
|
@alokedesai thank you! please let me know if there is anything I should adjust, expand etc. |
peicodes
left a comment
There was a problem hiding this comment.
This is a great fix! I have a small nit, but otherwise the code changes look great
| /// | ||
| /// Per the MCP spec, the client should only invoke a list method when the server | ||
| /// has advertised the corresponding capability during initialization. | ||
| fn should_query_resources(capabilities: Option<&rmcp::model::ServerCapabilities>) -> bool { |
There was a problem hiding this comment.
Nit: Can we move this to a utils.rs in the same directory, and the tests to utils_test.rs? There should be examples of this pattern elsewhere in the codebase
…t.rs Per @peicodes' review nit on warpdotdev#9436, extract `should_query_resources` and `should_query_tools` from `native.rs` into a sibling `utils` module following the codebase's `mod_test`-style convention (helper module + external test file declared from the parent). No behavior change; the spawn_server callsites continue to use the predicates via `super::utils::*` and the regression test `each_capability_is_queried_independently` is preserved verbatim in the new test file. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
/oz-review |
There was a problem hiding this comment.
Overview
This PR makes MCP startup query resources and tools based on independently advertised capabilities and makes tools/list failures degrade to an empty tool list instead of failing server startup.
Concerns
- No blocking correctness or security issues found.
- The new
tools/listfail-soft branch should be covered by a production-flow test; the added test only covers the capability predicates.
Verdict
Found: 0 critical, 0 important, 1 suggestions
Approve with nits
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| let tools = if should_query_tools(capabilities) { | ||
| match service.list_all_tools().await { | ||
| Ok(result) => result, | ||
| Err(err) => { |
There was a problem hiding this comment.
💡 [SUGGESTION] This new fail-soft branch is not exercised by the added predicate-only test; add coverage that a tools/list error does not abort spawn_server and produces an empty tool list.
There was a problem hiding this comment.
Overview
This PR updates MCP templatable server startup so resources and tools are queried independently based on their advertised capabilities, and tool listing failures now degrade to an empty tool list with a warning rather than aborting startup. It also adds predicate-level regression coverage for the capability combinations.
Concerns
- No blocking correctness or security concerns found in the changed lines.
Verdict
Found: 0 critical, 0 important, 0 suggestions
Approve
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
…urce-provider-startup
There was a problem hiding this comment.
Overview
This PR makes templatable MCP startup query resources and tools independently based on the server's advertised capabilities, and makes tools/list failures fail-soft to match existing resources/list behavior.
Concerns
- The added test covers the capability predicates, but not the new fail-soft
tools/listbehavior inspawn_server; a mock/service-level test would better lock down the behavioral change.
Verdict
Found: 0 critical, 0 important, 1 suggestions
Approve with nits
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
…test fail-soft behavior Per @oz-for-oss review on warpdotdev#9436: the predicate-only test `each_capability_is_queried_independently` doesn't catch regressions in the actual fail-soft behavior of `tools/list` — if someone reverts the change to log-and-empty on errors, the predicate test keeps passing. Extract two thin async helpers, `query_tools_for` and `query_resources_for`, that pair the capability gate with the list call and return an empty vec on any error. They take the list call as a closure so unit tests can drive every branch of the control flow (skipped, listed, transport error, MCP error, exactly-one-call) with a fake list function in place of a real `RunningService`. `spawn_server` is updated to call the helpers in place of the previous inline match expressions; behavior is unchanged. Adds 11 helper-level tests (`query_tools_for_*`, `query_resources_for_*`) plus the existing 1 predicate test, validated locally by running an isolated copy of the helpers and tests in a standalone crate against the same rmcp revision Warp pins (15/15 pass). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
/oz-review |
There was a problem hiding this comment.
Overview
This PR refactors MCP startup capability handling so resources/list and tools/list are each gated by their independently advertised server capability, with fail-soft listing behavior for both surfaces. The added tests cover predicate behavior and helper control flow across advertised and non-advertised capability shapes.
Concerns
- No blocking correctness or security concerns found in the changed lines.
Verdict
Found: 0 critical, 0 important, 0 suggestions
Approve
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
Description
Fixes #6798.
Makes
tools/listandresources/listquerying symmetric inspawn_server: each capability is gated on its own advertised flag, and listing failures are fail-soft (logged) instead of aborting server startup.The literal log pattern in #6798 (server advertises
tools+resources, Warp queriesresources/listand never queriestools/list) does not reproduce against the current OSS-release code at native.rs:1957 —service.list_all_tools()was already being called unconditionally. This PR closes the underlying asymmetry that the bug surfaced and locks the behavior down with a regression test:tools/listis now skipped when not advertised by the server (was always called and relied onMETHOD_NOT_FOUNDhandling).tools/listerrors are now logged and treated as "no tools" instead of aborting startup, mirroring howresources/listalready behaves. This is the symmetry the bug was about — a server with healthy resources but a flakytools/listresponse should not fail to start entirely.Spec: per the MCP spec (2025-03-26) §lifecycle, clients must only invoke list methods when the corresponding capability is advertised during initialization.
The two predicates (
should_query_resources,should_query_tools) are deliberately small named functions so the call site documents intent and the regression test exercises the same code path the production flow uses.Testing
Added unit test
each_capability_is_queried_independentlycovering the six relevant capability shapes: tools+resources, tools-only, resources-only, neither,None(nopeer_info), and one all-fields-set sanity check.I was not able to run
./script/presubmitlocally — thewarpuibuild step requiresxcrun metal, which needs fullXcode.app(onlyCommandLineToolsis installed on this machine) — so I'm relying on CI for the workspace-widecargo clippy --all-targets -- -D warningsandcargo nextest run --workspaceverification. Happy to address any CI feedback.Server API dependencies
N/A — client-only change.
Agent Mode
Changelog Entries for Stable
CHANGELOG-BUG-FIX: Fix MCP servers advertising both tools and resources sometimes failing to start due to asymmetric capability handling (#6798).