Skip to content

Add regression tests gating the mcp-go to go-sdk migration #5742

Description

@JAORMX

Summary

#5729 migrates ToolHive from mark3labs/mcp-go to the go-sdk-backed mcpcompat shim (toolhive-core v0.0.27). An audit found functional regressions in the shim — tracked with fixes in stacklok/toolhive-core#156. To guarantee the migration lands with zero functional loss, ToolHive needs regression tests that pin the current (mcp-go) behavior: they should fail against shim v0.0.27 and pass once #5729 bumps to the fixed toolhive-core release.

These tests are the acceptance gate for toolhive-core#156 and merge-blocking evidence for #5729.

Test matrix

1. stdio bridge notification forwarding (end-to-end)

Backend emits → client of the bridge receives, over pkg/transport/bridge.go:

  • notifications/progress (with progressToken correlation)
  • notifications/message (logging)
  • notifications/tools/list_changed — and a subsequent tools/list through the bridge reflects the changed tool set
  • notifications/resources/list_changed, notifications/prompts/list_changed

Currently ALL of these are dropped end-to-end under the shim (client half never registers progress/logging handlers; server half cannot send list_changed).

2. vMCP session lifecycle

  • Per-request session validation: terminate a session out-of-band (auth-failure path or cross-pod Terminate via shared Redis storage), then verify the origin pod rejects the next request on that Mcp-Session-Id (today the shim skips Validate for local sessions).
  • DELETE termination still evicts cache, closes backend connections, and returns the spec status.
  • Session identity binding: a second principal reusing a session ID is rejected.

3. Per-session tool projection (security-relevant)

Runtime validation that the shim's per-session go-sdk Server + live tool reconciliation preserves vMCP behavior:

  • Two concurrent sessions with different authz outcomes see different tools/list results.
  • A tool filtered for session A cannot be invoked by session A via tools/call while remaining callable in session B.
  • SetSessionTools reconciliation mid-session is reflected in the next tools/list.

4. SSE keep-alive

  • An idle long-lived text/event-stream response from the vMCP server carries periodic keep-alive bytes (SSE comments or pings) at the configured WithHeartbeatInterval cadence (currently a silent no-op under the shim).

5. Pagination behavior

  • A vMCP server exposing >1000 tools: verify downstream clients receive the complete set (go-sdk paginates at 1000; mcp-go returned everything). Either the server page size is raised or the test documents/exercises cursor-following.

6. Local proxy Host-header behavior

  • Localhost-bound proxy accessed with a non-localhost Host header behaves as before the migration (go-sdk's DNS-rebinding protection defaults on and returns 403; decide and pin the intended behavior).

7. Remote auth error mapping

  • 401 from a remote backend surfaces ErrUnauthorized/ErrAuthorizationRequired sentinels consumed by pkg/vmcp/client auth discovery.
  • 403-on-initialize maps to the legacy-SSE fallback path as it did under mcp-go.

Notes

Generated with Claude Code

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions