Skip to content

fix(mcp): query tools/resources independently per advertised capability (#6798)#9436

Open
david-engelmann wants to merge 4 commits intowarpdotdev:masterfrom
david-engelmann:david/6798-mcp-resource-provider-startup
Open

fix(mcp): query tools/resources independently per advertised capability (#6798)#9436
david-engelmann wants to merge 4 commits intowarpdotdev:masterfrom
david-engelmann:david/6798-mcp-resource-provider-startup

Conversation

@david-engelmann
Copy link
Copy Markdown

@david-engelmann david-engelmann commented Apr 29, 2026

Description

Fixes #6798.

Makes tools/list and resources/list querying symmetric in spawn_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 queries resources/list and never queries tools/list) does not reproduce against the current OSS-release code at native.rs:1957service.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/list is now skipped when not advertised by the server (was always called and relied on METHOD_NOT_FOUND handling).
  • tools/list errors are now logged and treated as "no tools" instead of aborting startup, mirroring how resources/list already behaves. This is the symmetry the bug was about — a server with healthy resources but a flaky tools/list response 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_independently covering the six relevant capability shapes: tools+resources, tools-only, resources-only, neither, None (no peer_info), and one all-fields-set sanity check.

I was not able to run ./script/presubmit locally — the warpui build step requires xcrun metal, which needs full Xcode.app (only CommandLineTools is installed on this machine) — so I'm relying on CI for the workspace-wide cargo clippy --all-targets -- -D warnings and cargo nextest run --workspace verification. Happy to address any CI feedback.

Server API dependencies

N/A — client-only change.

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI 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).

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]>
@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented Apr 29, 2026

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 to trigger another check.

@david-engelmann
Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot cla-bot Bot added the cla-signed label Apr 29, 2026
@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented Apr 29, 2026

The cla-bot has been summoned, and re-checked this pull request!

@david-engelmann david-engelmann marked this pull request as ready for review April 29, 2026 15:53
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented Apr 29, 2026

@david-engelmann

I'm starting a first review of this pull request.

I completed the review and posted feedback on this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

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 /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

I reviewed this pull request and requested human review from: @peicodes.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

I reviewed this pull request and requested human review from: @peicodes.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

You can view the conversation on Warp.

I reviewed this pull request and requested human review from: @peicodes.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@alokedesai
Copy link
Copy Markdown
Member

Thanks for contributing! @peicodes could you take a look?

@david-engelmann
Copy link
Copy Markdown
Author

@alokedesai thank you! please let me know if there is anything I should adjust, expand etc.

Copy link
Copy Markdown
Contributor

@peicodes peicodes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@captainsafia captainsafia added the external-contributor Indicates that a PR has been opened by someone outside the Warp team. label Apr 30, 2026 — with Warp Dev Github Integration
…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]>
@david-engelmann
Copy link
Copy Markdown
Author

/oz-review

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/list fail-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) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [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.

@oz-for-oss oz-for-oss Bot requested a review from peicodes April 30, 2026 21:25
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/list behavior in spawn_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

Comment thread app/src/ai/mcp/templatable_manager/utils_test.rs
…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]>
@david-engelmann
Copy link
Copy Markdown
Author

/oz-review

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed external-contributor Indicates that a PR has been opened by someone outside the Warp team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP service with a resource provider fails to start in Warp

4 participants