stacklok / stacklok/toolhive

vMCP: extend backend-init list-method tolerance to HTTP-level method-missing signals

Open
#5,242 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement go vmcp
Dominant language
Go
Stars
2.2k
Forks
300
Avg merge
1d 15h
Merged PRs (30d)
184

Description

Background

PR #5232 (issue #5231) added narrow tolerance in pkg/vmcp/session/internal/backend/mcp_session.go::initAndQueryCapabilities so that a backend advertising the resources or prompts capability but returning JSON-RPC -32601 (method not found) for resources/list / prompts/list no longer aborts backend init and silently drops every tool from that backend.

That fix is intentionally scoped to JSON-RPC -32601 envelopes only. The recovery comment now explicitly states "HTTP-level method absence is intentionally fatal" — review thread: https://github.com/stacklok/toolhive/pull/5232#discussion_r3211850406.

Problem

Some real-world backends sit behind reverse proxies, API gateways, or non-MCP front doors that surface "this method isn't implemented" as an HTTP-level response (404 / 405 / 501) rather than as a JSON-RPC -32601 envelope. Under those conditions:

  • mcp-go's streamable-HTTP / SSE transport layers return a non-sentinel transport error (not wrapping mcp.ErrMethodNotFound).
  • errors.Is(listErr, mcp.ErrMethodNotFound) therefore evaluates false.
  • The fatal case listErr != nil arm fires → init aborts → every tool from that backend is silently dropped.

This reproduces the original #5231 symptom for a slightly different class of misbehaving backends.

Proposed work

  1. Enumerate the transport-level signals to be treated as method-missing. Candidates: HTTP 404 Not Found, 405 Method Not Allowed, 501 Not Implemented.
  2. Decide where the discrimination happens — at the adapter / transport boundary (preferred, keeps pkg/vmcp/session/internal/backend clean) versus inside initAndQueryCapabilities.
  3. Extend the existing errors.Is(listErr, mcp.ErrMethodNotFound) case in mcp_session.go (or replace it with a richer predicate) so the chosen transport-level errors recover with the same WARN-and-continue behavior as -32601.
  4. Add tests that exercise each chosen HTTP status against the existing fakeBackend harness in mcp_session_capabilities_test.go.
  5. Keep tools/list strict — recovery should remain limited to resources/list and prompts/list, matching the scope of #5231.

Acceptance criteria

  • Concrete list of HTTP statuses recovered, documented in the recovery comment alongside the existing -32601 note.
  • Recovery path emits the same slog.Warn breadcrumb (backendID / name / baseURL / method) as the JSON-RPC -32601 path.
  • Backend with tools + resources capabilities and resources/list returning HTTP 404/405/501 still initializes successfully and exposes its tools.
  • Backend with tools/list returning HTTP 404/405/501 still aborts init (regression guard).
  • Unit tests added for each recovered status.

References

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with pkg/vmcp/session/internal/backend/mcp_session.go, especially initAndQueryCapabilities and its existing errors.Is handling, then read mcp_session_capabilities_test.go and the fakeBackend harness. Trace how streamable-HTTP and SSE transport errors expose HTTP 404, 405, and 501, and run the capability tests. Done means the chosen statuses recover only for resources/list and prompts/list, preserve the warning fields, and tools/list remains fatal.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend, networking, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.