stacklok / stacklok/toolhive

proxyrunner tool-filter middleware strips SEP-2322 Modern envelope from tools/list, breaking vMCP health checks

Open Beginner friendly
#6,684 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs-triage
Dominant language
Go
Stars
2.2k
Forks
300
Avg merge
1d 15h
Merged PRs (30d)
184

Description

Bug

With an MCPServer that has toolConfigRef set, proxyrunner's tool-filter middleware (pkg/mcp/tool_filter.go, NewListToolsMappingMiddleware) buffers and rewrites tools/list SSE responses to apply the filter. The re-emitted body drops the SEP-2322 ("Modern") envelope fields: resultType, _meta (incl. io.modelcontextprotocol/serverInfo), ttlMs, cacheScope.

Impact on vMCP

vMCP classifies the backend as Modern (server/discover answers enveloped), then sends a Modern tools/list. The backend replies enveloped, but the proxy filter strips the envelope, so vMCP receives a Legacy-shaped success body → errLegacyResponseBody ("backend returned a Legacy-shaped body (no resultType); it may have executed") → health check fails → circuit breaker opens permanently; backend stays unavailable even though it is fully functional.

Reproduced on operator+vmcp+proxyrunner v0.49.0 (also reproduced with operator/vmcp at v0.48.0, same error string). Exactly the backends with toolConfigRef fail; all unfiltered backends in the same vMCP groups are healthy.

Wire evidence

Backend direct (bypassing proxy) — enveloped, correct:

data: {"jsonrpc":"2.0","id":2,"result":{"resultType":"complete","_meta":{"io.modelcontextprotocol/serverInfo":{"name":"github-mcp-server",...}}, ... "tools":[...]}}

Via proxyrunner with toolConfigRef — envelope stripped:

data: {"jsonrpc":"2.0","id":2,"result":{"tools":[...]}}

Same backend image behind an identical proxyrunner without toolConfigRef passes through enveloped and is classified healthy.

Expected

The filter should preserve the Modern envelope fields (rewrite only result.tools), or skip rewriting when the response is enveloped.

Workaround

Drop toolConfigRef and enforce the tool set server-side (e.g. GITHUB_READ_ONLY/GITHUB_TOOLSETS, kubernetes-mcp read_only = true).

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 in pkg/mcp/tool_filter.go at NewListToolsMappingMiddleware and trace how tools/list SSE responses are buffered and re-emitted. Preserve the SEP-2322 envelope while changing only result.tools, or skip rewriting enveloped responses; done means filtered Modern responses retain resultType, _meta, ttlMs, and cacheScope.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.