Skip to content

Tolerate MethodNotFound for optional capabilities in ListCapabilities - #6660

Merged
ChrisJBurns merged 1 commit into
stacklok:mainfrom
hellouz818:fix/6339-tolerate-method-not-found-in-listcapabilities
Sep 15, 2026
Merged

ChrisJBurns merged 1 commit into
stacklok:mainfrom
hellouz818:fix/6339-tolerate-method-not-found-in-listcapabilities

Conversation

@hellouz818

Copy link
Copy Markdown
Contributor

Summary

ListCapabilities already respects advertised capabilities, so unadvertised resource and prompt capabilities are not probed.
This change covers the remaining interoperability case where a backend advertises resources or prompts but returns -32601 Method not found for the
corresponding list method.
The session-init path (queryBackendResources / queryBackendPrompts in mcp_session.go) already tolerates this behavior. This PR aligns the ListCapabilities
path, used by health checks and capability aggregation, with the same handling.

This prevents otherwise healthy backends from being marked degraded and keeps their tools available through the vMCP.

Related to #6339

Type of change

  • Bug fix

Test plan

  • Unit tests (task test)
  • Manual testing (describe below)

Verified against a production vMCP deployment running ToolHive v0.46.0 with an Atlassian Jira MCP backend that advertises the resources capability but returns
-32601 for resources/list.

Added regression coverage for:

  • resources/list returning MethodNotFound while tools continue to aggregate
  • prompts/list returning MethodNotFound while tools continue to aggregate
  • tools-only backends not invoking unadvertised resources/list or prompts/list

Does this introduce a user-facing change?

Yes.

Backends that advertise resources or prompts but return -32601 Method not found for the corresponding list method are no longer marked degraded solely because
of that optional capability. Their remaining capabilities, including tools, continue to aggregate and route normally through the vMCP.

Special notes for reviewers

The parent revision already gates resources/list and prompts/list on serverCaps.Resources != nil and serverCaps.Prompts != nil, so the original #6339 case
of probing unadvertised capabilities is already handled.

This PR addresses the adjacent interoperability case where a backend advertises an optional capability but does not implement its list method, as seen with
Atlassian Rovo (#5231).

tools/list remains strict when the backend advertises the tools capability. Advertising tools while returning MethodNotFound for tools/list is treated as an
inconsistent backend implementation.

Generated with Claude Code

The ListCapabilities path (used by health checks and capability
aggregation) was missing the -32601 tolerance that the session-init
path already had. A backend that advertises the resources or prompts
capability but answers the corresponding list method with JSON-RPC
-32601 (Method not found) caused the entire backend to be marked
degraded/unavailable, silently dropping all of its tools.

The parent revision already gates on serverCaps.Resources/Prompts
before probing, so unadvertised capabilities are not called. This
change defends the remaining edge case where a backend advertises a
capability but does not implement the list method (e.g. Atlassian
Rovo, see stacklok#5231), aligning the ListCapabilities path with the
existing session-init tolerance.

Legacy path (queryResources, queryPrompts):
  - Detect mcp.ErrMethodNotFound and return an empty result set with
    a WARN log instead of propagating the error.

Modern path (modernEnumerate):
  - Set degradeNotFound=true for resources/list and prompts/list in
    modernListOptional, matching the existing resources/templates/list
    behavior. Update the modernListOptional doc comment to reflect
    that resources/list and prompts/list are no longer fatal.

tools/list remains strict when the backend advertises the tools
capability; advertising tools while returning MethodNotFound for
tools/list is treated as an inconsistent backend implementation.

Closes stacklok#6339

Signed-off-by: hellouz818 <hellouz818@gmail.com>
@ChrisJBurns

Copy link
Copy Markdown
Collaborator

/retest

@codecov

codecov Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.13%. Comparing base (aa913cb) to head (060c017).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6660      +/-   ##
==========================================
+ Coverage   78.93%   79.13%   +0.19%     
==========================================
  Files         782      785       +3     
  Lines       78065    78309     +244     
==========================================
+ Hits        61620    61966     +346     
+ Misses      16440    16338     -102     
  Partials        5        5              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ChrisJBurns
ChrisJBurns merged commit f3dfc9e into stacklok:main Sep 15, 2026
53 of 54 checks passed
@ChrisJBurns

Copy link
Copy Markdown
Collaborator

Thanks for the contribution @hellouz818 have merged the above! 🚀

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants