Skip to content

fix: disable standalone SSE stream in streamable HTTP transport to prevent HTTP MCP server startup failures#4428

Merged
lpcox merged 4 commits intomainfrom
copilot/fix-http-mcp-server-error
Apr 23, 2026
Merged

fix: disable standalone SSE stream in streamable HTTP transport to prevent HTTP MCP server startup failures#4428
lpcox merged 4 commits intomainfrom
copilot/fix-http-mcp-server-error

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 23, 2026

HTTP MCP servers (e.g. Unwrap) show status: error at gateway startup and advertise no tools to Copilot CLI, despite the endpoint being reachable.

Root cause

The SDK's StreamableClientTransport automatically issues a GET request for a persistent SSE stream synchronously inside client.Connect(), immediately after the initialize POST succeeds:

  1. POST initialize → server responds ✓
  2. sessionUpdated()connectStandaloneSSE() → GET request
  3. Server returns 5xx (or any non-4xx/non-405) → c.fail() marks connection as broken
  4. client.Connect() tries to send initialized notification → c.Write() sees failure → returns error
  5. All three transports fail → recordError()/health reports status: error

Additionally, MaxRetries: 0 in the SDK defaults to 5 retries, not 0, contrary to the existing comment.

Changes

  • internal/mcp/http_transport.go / connection.go: Set DisableStandaloneSSE: true and MaxRetries: -1 on StreamableClientTransport in both tryStreamableHTTPTransport and reconnectSDKTransport. The gateway is a request-response proxy and has no use for server-initiated SSE notifications from backends.
return &sdk.StreamableClientTransport{
    Endpoint:             url,
    HTTPClient:           httpClient,
    MaxRetries:           -1, // Disable retries (-1 = 0 retries; SDK treats 0 as "use default: 5")
    DisableStandaloneSSE: true,
}
  • internal/mcp/http_connection_test.go: Adds regression test TestNewHTTPConnection_StreamableTransport_BadSSEEndpoint — server returns valid initialize result for POST but 500 for GET; connection must succeed via streamable transport with zero GET requests issued.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /tmp/go-build900524329/b513/launcher.test /tmp/go-build900524329/b513/launcher.test -test.testlogfile=/tmp/go-build900524329/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s /tmp/go-build900524329/b410/vet.cfg g_.a o_.o x_amd64/vet 01.o roundrobin 03.o x_amd64/vet -W wkO_kTNLT .cfg x_amd64/vet . --gdwarf2 --64 x_amd64/vet (dns block)
  • invalid-host-that-does-not-exist-12345.com
    • Triggering command: /tmp/go-build900524329/b495/config.test /tmp/go-build900524329/b495/config.test -test.testlogfile=/tmp/go-build900524329/b495/testlog.txt -test.paniconexit0 -test.timeout=10m0s /tmp/go-build900524329/b399/vet.cfg g_.a 9742532/b151/ x_amd64/vet --gdwarf-5 grpcsync p=/opt/hostedtoolcache/go/1.25.9/tmp/go-build511290287/b107/vet.cfg x_amd64/vet -W ABSZSCNGR .cfg x_amd64/vet . --gdwarf2 --64 x_amd64/vet (dns block)
  • nonexistent.local
    • Triggering command: /tmp/go-build900524329/b513/launcher.test /tmp/go-build900524329/b513/launcher.test -test.testlogfile=/tmp/go-build900524329/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s /tmp/go-build900524329/b410/vet.cfg g_.a o_.o x_amd64/vet 01.o roundrobin 03.o x_amd64/vet -W wkO_kTNLT .cfg x_amd64/vet . --gdwarf2 --64 x_amd64/vet (dns block)
  • slow.example.com
    • Triggering command: /tmp/go-build900524329/b513/launcher.test /tmp/go-build900524329/b513/launcher.test -test.testlogfile=/tmp/go-build900524329/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s /tmp/go-build900524329/b410/vet.cfg g_.a o_.o x_amd64/vet 01.o roundrobin 03.o x_amd64/vet -W wkO_kTNLT .cfg x_amd64/vet . --gdwarf2 --64 x_amd64/vet (dns block)
  • this-host-does-not-exist-12345.com
    • Triggering command: /tmp/go-build3852249779/b001/mcp.test /tmp/go-build3852249779/b001/mcp.test -test.testlogfile=/tmp/go-build3852249779/b001/testlog.txt -test.paniconexit0 -test.run=TestNewHTTPConnection|TestHTTPConnection -test.v=true -test.timeout=1m0s 0/internal/tracetransform/instrumentation.go x_amd64/compile OUTPUT 9742532/b015/ 168.63.129.16 x_amd64/compile -w p/go-build security 64=/_/GOROOT OUTPUT 64/src/runtime/c-unsafeptr=false 168.63.129.16 git (dns block)
    • Triggering command: /tmp/go-build900524329/b522/mcp.test /tmp/go-build900524329/b522/mcp.test -test.testlogfile=/tmp/go-build900524329/b522/testlog.txt -test.paniconexit0 -test.timeout=10m0s 9742�� olang.org/protob-errorsas .cfg x_amd64/vet --gdwarf-5 --64 -o x_amd64/vet -o 9742532/b408/_pk-s -trimpath x_amd64/vet -p g/grpc/binarylog/usr/bin/runc -lang=go1.25 x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build3289280713/b001/mcp.test /tmp/go-build3289280713/b001/mcp.test -test.testlogfile=/tmp/go-build3289280713/b001/testlog.txt -test.paniconexit0 -test.run=TestNewHTTPConnection -test.v=true -test.timeout=1m0s y bin/bash ntime.v2.task/mogit .cfg x_amd64/vet /usr/bin/runc.original --ve�� 30977974af8f49f3088e082efdf88695 runtime-runc/moby /usr/local/bin/iptables io.containerd.ru/bin/sh .cfg x_amd64/vet b83/log.json (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI and others added 2 commits April 23, 2026 22:55
Copilot AI changed the title [WIP] Fix HTTP MCP server error state on startup fix: disable standalone SSE stream in streamable HTTP transport to prevent HTTP MCP server startup failures Apr 23, 2026
Copilot AI requested a review from lpcox April 23, 2026 22:57
@lpcox lpcox marked this pull request as ready for review April 23, 2026 23:06
Copilot AI review requested due to automatic review settings April 23, 2026 23:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Disables the SDK’s standalone SSE GET stream (and implicit retries) for streamable HTTP transports to prevent MCP HTTP backends from causing gateway startup/connect failures, and adds a regression test for the failure mode.

Changes:

  • Configure sdk.StreamableClientTransport with DisableStandaloneSSE: true and MaxRetries: -1 on initial connect.
  • Apply the same streamable transport configuration during SDK transport reconnects.
  • Add a regression test ensuring no SSE GET is issued when the server would error on GET.
Show a summary per file
File Description
internal/mcp/http_transport.go Disables standalone SSE and SDK retries for streamable HTTP transport creation.
internal/mcp/connection.go Ensures reconnect path uses the same streamable transport settings (no SSE GET, no retries).
internal/mcp/http_connection_test.go Adds regression test asserting streamable connect succeeds without issuing any GET requests.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment thread internal/mcp/http_connection_test.go Outdated
Comment on lines +599 to +607
getMethodCount := 0

testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet {
// Simulate a server that returns 500 for the SSE GET stream.
// Before the fix this would call c.fail() and break the connection;
// after the fix the GET is never issued.
getMethodCount++
w.WriteHeader(http.StatusInternalServerError)
@lpcox
Copy link
Copy Markdown
Collaborator

lpcox commented Apr 23, 2026

@copilot address this review feedback #4428 (review)

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 23, 2026

@copilot address this review feedback #4428 (review)

Fixed in fc18b1e — replaced the plain int with atomic.Int32 (increment via .Add(1), read via .Load()). The test now passes cleanly under -race.

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.

HTTP MCP server enters error state on startup; tools never advertised to Copilot CLI (Unwrap MCP repro)

3 participants