Skip to content

Conversation

@therealnb
Copy link
Contributor

@therealnb therealnb commented Nov 7, 2025

Description

This PR ensures MCP servers are fully ready before notifying clients, preventing connection timing issues described in #2499.

Changes

The proxy now:

  1. Starts the container and proxy
  2. NEW: Repeatedly calls the initialize endpoint until it succeeds (HTTP 200)
  3. Waits up to 5 minutes with exponential backoff (100ms → 2s)
  4. Only then updates client configurations

Implementation Details

For streamable-http and SSE transports, the runner makes direct HTTP calls to the MCP initialize endpoint with proper headers:

  • Content-Type: application/json
  • Accept: application/json, text/event-stream (required by some MCP servers)
  • MCP-Protocol-Version: 2024-11-05

The function uses exponential backoff to avoid hammering the server, with delays capped at 2 seconds between attempts and an overall timeout of 5 minutes for slow-starting servers like mcp-optimizer.

Testing

  • ✅ Builds successfully
  • ✅ Linter passes (fixed all gosec, lll, and revive issues)
  • ✅ Manually tested with mcp-optimizer (which requires ~30s to start)
  • ✅ Backward compatible (continues with warning if initialize times out)

Fixes #2499, #2271

There is a video of this working here.

This ensures MCP servers are fully ready before notifying clients,
preventing connection timing issues.

The proxy now:
1. Starts the container and proxy
2. Repeatedly calls the initialize endpoint until it succeeds (HTTP 200)
3. Waits up to 5 minutes with exponential backoff (100ms-2s)
4. Only then updates client configurations

For streamable-http transport, the proxy calls POST /mcp with proper
headers (Accept: application/json, text/event-stream) to ensure
compatibility with servers that require both content types.

Fixes #2499
@codecov
Copy link

codecov bot commented Nov 7, 2025

Codecov Report

❌ Patch coverage is 0% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.54%. Comparing base (84ebaa0) to head (6223f0f).

Files with missing lines Patch % Lines
pkg/runner/runner.go 0.00% 71 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2504      +/-   ##
==========================================
- Coverage   55.66%   55.54%   -0.12%     
==========================================
  Files         295      295              
  Lines       28086    28150      +64     
==========================================
+ Hits        15633    15635       +2     
- Misses      11031    11094      +63     
+ Partials     1422     1421       -1     

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Contributor

@amirejaz amirejaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

./bin/thv run time --proxy-mode sse is not working, it is stuck on:
3:49PM �[34mINFO�[0m Waiting for MCP server to accept initialize requests at http://localhost:38870/messages (timeout: 5m0s).

Signed-off-by: nigel brown <[email protected]>
Signed-off-by: nigel brown <[email protected]>
Signed-off-by: nigel brown <[email protected]>
Signed-off-by: nigel brown <[email protected]>
because it waits for init. Longer timeout

Signed-off-by: nigel brown <[email protected]>
@eleftherias
Copy link
Member

There is an issue with calling initialize for STDIO MCP servers multiple times. The behaviour is not determined by the spec so they may reject the request #1982. That's why ToolHive avoids calling initialize itself and only forwards the client request.

@therealnb
Copy link
Contributor Author

Discussion here.

The OSV server transport changed from sse to streamable-http on November 4, 2025 in commit 31f2d8b (PR #2441).

Signed-off-by: nigel brown <[email protected]>
The OSV MCP server transport changed from sse to streamable-http in the
registry update on 2025-11-04 (commit 31f2d8b). This was causing test
failures with 5-minute timeouts as the tests were still trying to start
the server with --transport sse.

Changes:
- Updated all transport references from sse to streamable-http
- Changed MCP client initialization from NewMCPClientForSSE to
  NewMCPClientForStreamableHTTP
- Updated URL endpoint expectations from /sse to /mcp
- Fixed formatting issues with golangci-lint

Tests now pass: 13 Passed | 0 Failed
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.

handle impetulant client config changes

5 participants