You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
vMCP's per-session backend bootstrap (initAndQueryCapabilities in pkg/vmcp/session/internal/backend/mcp_session.go) treats any error from resources/list (and by symmetry prompts/list) as fatal. If a backend advertises the resources capability in its initialize response but does not actually implement resources/list, vMCP refuses to initialise the backend at all and silently drops every tool from that backend out of tools/list.
The ergonomic outcome: a user goes through the entire OAuth chain successfully, then has zero visibility that anything failed — the backend's tools just don't appear.
We've hit this against Atlassian's hosted Rovo MCP server (https://mcp.atlassian.com/v1/mcp), which advertises capabilities.resources in its initialize response but responds to resources/list with JSON-RPC -32601 Method not found. The same pattern is plausible for any third-party MCP server we don't control — we shouldn't require server-side spec compliance to use a backend at all.
Steps to reproduce
Configure a VirtualMCPServer with at least one backend that advertises resources in its initialize response but doesn't implement resources/list. (Atlassian Rovo via MCPServerEntry + upstreamInject is one real-world example.)
Complete the OAuth flow for the upstream so the user has a valid token for that backend.
Open an MCP session against vMCP.
Expected behavior
The backend initialises successfully and its tools appear in tools/list. Resources/prompts are absent (because the backend doesn't actually offer any), and a WARN log records that the backend advertised the capability but didn't honour the list method.
Actual behavior
vMCP logs:
{\"level\":\"WARN\",\"msg\":\"Failed to initialise backend for session; continuing without it\",\"backendID\":\"atlassian-rovo\",\"backendName\":\"atlassian-rovo\",\"error\":\"failed to initialise backend atlassian-rovo: list resources failed: method not found: Method not found\"}
The backend's tools never appear in the session. The user has no UI signal that anything went wrong.
The doubled "method not found: Method not found" string is from mcp-go's JSONRPCErrorDetails.AsError() wrapping the sentinel mcp.ErrMethodNotFound ("method not found") with the upstream message ("Method not found"). Practical implication: callers can detect this case via errors.Is(err, mcp.ErrMethodNotFound).
Suggested fix
In initAndQueryCapabilities, treat mcp.ErrMethodNotFound from resources/list and prompts/list as "the backend has no resources/prompts" rather than as a fatal init error. Tools is intentionally left strict: a backend whose tools/list is unavailable is not useful to surface at all.
When a backend advertises capabilities.resources in initialize but resources/list returns JSON-RPC error -32601 (mcp.ErrMethodNotFound), the backend initialises successfully with an empty resource set; its tools are reachable via tools/list on the vMCP session.
Same behaviour for prompts/list: a -32601 from a backend that advertised prompts does not abort backend init.
tools/list failures remain fatal (a backend with no working tool surface is not useful to expose).
Any non--32601 error from resources/list or prompts/list (timeout, transport error, other JSON-RPC error codes) still aborts init — we are not silencing arbitrary failures, only the specific spec-violation case where the server contradicts its own advertised capabilities.
A WARN-level log line records the spec violation, including the backend ID and which list method was missing, so operators can surface a bug to the upstream server author. Do not log at ERROR — this is a recoverable, expected-in-the-wild condition.
Unit tests in pkg/vmcp/session/internal/backend/ cover:
resources/list returns -32601 after server advertised resources → init succeeds, no resources, WARN logged
prompts/list returns -32601 after server advertised prompts → init succeeds, no prompts, WARN logged
tools/list returns -32601 → init still fails (regression guard)
resources/list returns a non--32601 JSON-RPC error → init still fails (regression guard)
Manual verification with the Atlassian Rovo MCP server (https://mcp.atlassian.com/v1/mcp) wired up via MCPServerEntry + upstreamInject: after OAuth completes, tools/list on the vMCP session returns the workload-prefixed Atlassian tools (e.g. atlassian-rovo_<tool>).
Environment
ToolHive version: main (reproduced on the gateway-5fdf997cdc-* image running in arn:aws:eks:us-east-1:781189302813:cluster/rovo-demo3-toolhive-dev)
mcp-go: v0.49.0
Additional context
The same fragility class is worth a quick audit elsewhere in the session bootstrap: any place that derives "the server supports method X" from the initialize response and then unconditionally calls X. prompts/list is the obvious sibling and is included above. Subscriptions / completions paths are worth a glance.
This is purely a vMCP-side fix; we cannot wait for upstream MCP servers to become spec-compliant before users can call their tools through vMCP.
Bug description
vMCP's per-session backend bootstrap (
initAndQueryCapabilitiesinpkg/vmcp/session/internal/backend/mcp_session.go) treats any error fromresources/list(and by symmetryprompts/list) as fatal. If a backend advertises theresourcescapability in itsinitializeresponse but does not actually implementresources/list, vMCP refuses to initialise the backend at all and silently drops every tool from that backend out oftools/list.The ergonomic outcome: a user goes through the entire OAuth chain successfully, then has zero visibility that anything failed — the backend's tools just don't appear.
We've hit this against Atlassian's hosted Rovo MCP server (
https://mcp.atlassian.com/v1/mcp), which advertisescapabilities.resourcesin itsinitializeresponse but responds toresources/listwith JSON-RPC-32601 Method not found. The same pattern is plausible for any third-party MCP server we don't control — we shouldn't require server-side spec compliance to use a backend at all.Steps to reproduce
VirtualMCPServerwith at least one backend that advertisesresourcesin itsinitializeresponse but doesn't implementresources/list. (Atlassian Rovo viaMCPServerEntry+upstreamInjectis one real-world example.)Expected behavior
The backend initialises successfully and its tools appear in
tools/list. Resources/prompts are absent (because the backend doesn't actually offer any), and a WARN log records that the backend advertised the capability but didn't honour the list method.Actual behavior
vMCP logs:
The backend's tools never appear in the session. The user has no UI signal that anything went wrong.
The fatal error originates here:
pkg/vmcp/session/internal/backend/mcp_session.go:387-389Same shape at
prompts/list(lines 402-406) andtools/list(lines 369-373).The doubled "method not found: Method not found" string is from
mcp-go'sJSONRPCErrorDetails.AsError()wrapping the sentinelmcp.ErrMethodNotFound("method not found") with the upstream message ("Method not found"). Practical implication: callers can detect this case viaerrors.Is(err, mcp.ErrMethodNotFound).Suggested fix
In
initAndQueryCapabilities, treatmcp.ErrMethodNotFoundfromresources/listandprompts/listas "the backend has no resources/prompts" rather than as a fatal init error. Tools is intentionally left strict: a backend whosetools/listis unavailable is not useful to surface at all.Sketch:
Acceptance criteria
capabilities.resourcesininitializebutresources/listreturns JSON-RPC error-32601(mcp.ErrMethodNotFound), the backend initialises successfully with an empty resource set; its tools are reachable viatools/liston the vMCP session.prompts/list: a-32601from a backend that advertisedpromptsdoes not abort backend init.tools/listfailures remain fatal (a backend with no working tool surface is not useful to expose).-32601error fromresources/listorprompts/list(timeout, transport error, other JSON-RPC error codes) still aborts init — we are not silencing arbitrary failures, only the specific spec-violation case where the server contradicts its own advertised capabilities.pkg/vmcp/session/internal/backend/cover:-32601after server advertisedresources→ init succeeds, no resources, WARN logged-32601after server advertisedprompts→ init succeeds, no prompts, WARN logged-32601→ init still fails (regression guard)-32601JSON-RPC error → init still fails (regression guard)https://mcp.atlassian.com/v1/mcp) wired up viaMCPServerEntry+upstreamInject: after OAuth completes,tools/liston the vMCP session returns the workload-prefixed Atlassian tools (e.g.atlassian-rovo_<tool>).Environment
main(reproduced on thegateway-5fdf997cdc-*image running inarn:aws:eks:us-east-1:781189302813:cluster/rovo-demo3-toolhive-dev)Additional context
initializeresponse and then unconditionally calls X.prompts/listis the obvious sibling and is included above. Subscriptions / completions paths are worth a glance.