Repository navigation
fix(upstream): re-initialize a terminated Streamable HTTP session and retry once (Spec 113-e) - #1501
Merged
Merged
Conversation
… retry once (Spec 113-e) mcp-go maps HTTP 404 for an unknown session id to ErrSessionTerminated and clears the session id. Previously that error flipped the server to Error and forced a full reconnect. The managed client now re-initializes the session in place (single-flight per stale session id), retries list/prompt/ping requests once, and retries tools/call once only for read-only tools whose identity hash is unchanged. connectionEpoch is not touched.
Deploying mcpproxy-docs with
|
| Latest commit: |
8889f63
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://382eddda.mcpproxy-docs.pages.dev |
| Branch Preview URL: | https://113-e-session-terminated-rei.mcpproxy-docs.pages.dev |
…r re-init, keep recovery error (Spec 113-e review r1)
Contributor
📦 Build ArtifactsWorkflow Run: View Run Available Artifacts
How to DownloadOption 1: GitHub Web UI (easiest)
Option 2: GitHub CLI gh run download 37440084534 --repo smart-mcp-proxy/mcpproxy-go
|
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
…ted-reinit # Conflicts: # internal/upstream/managed/client.go
Dumbris
enabled auto-merge (squash)
October 6, 2026 17:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a remote Streamable HTTP upstream forgets a session (restart, expiry) it answers HTTP 404 to the session id mcpproxy holds. mcp-go v1.0.0 maps every such 404 to
transport.ErrSessionTerminatedand clears the transport's session id. Today that error text ("terminated") matchesisConnectionError, so the server flips to Error and goes through a full reconnect, and the failing call is lost. Gap G8 of the Anthropic MCP-proxy talk audit (Spec 113, US5).What changed
core/session_reinit.go:SessionSnapshot()(transport session id + whether the negotiated protocol is stateless) andReinitializeSession(ctx), a fresh initialize on the same mcp-go client/transport.connectionEpochis never touched.managed/session_reinit.go: single-flight re-init keyed by the stale session id. Concurrent callers share one flight; a caller that finds a newer session proceeds; a request about to go out with an empty session id while one is known joins the flight instead of sending without a session. The flight does initialize plus a synchronous tools/list, refreshes the identity baseline, and schedules the normal discovery callback if the toolset changed.tools/callpath, the ListTools leader (so the cached-tool-count path is covered), prompts list/get, and the health ping. List/get/ping are retried once.tools/callis retried once only for read-only tools (readOnlyHintand not destructive) whose identity hash is unchanged (FR-081); otherwise the call returnsErrSessionReestablished(session re-established, call not repeated) and the server is not marked Error. A pinned call whose tool changed getsErrConnectionGenerationChanged.isConnectionError(retry also 404, or re-init fails: existing path).session_reinit_countinGetConnectionStatus.docs/setup.md: troubleshooting note.mcp-go v1.0.0 verification (FR-088)
Pinned by
TestMCPGo_SessionTerminated_ReinitializeOnSameTransport: a 404 on a non-initialize POST givesErrSessionTerminatedand clears the session id; a request with no session id that is 404'd gives it too; a secondInitializeon the same client/transport stores a new session id and the client works again. No divergence from the plan.Tests run
core(mcp-go behaviour pin, snapshot/reinit) andmanaged(TestSessionReinit_*: single read call = 1 re-init and state stays Ready; 10 concurrent calls = exactly 1 re-init; write tool not repeated and next call works; changed hash not retried and pinned call refused; ListTools retried; ping-first then call sends no session-less request; retry also 404 fails; pinned call epoch unchanged).-race -count=15stable.go test -race ./internal/upstream/...green;go build ./cmd/mcpproxyandgo build -tags server -o /dev/null ./cmd/mcpproxygreen.--build-tags server) on./internal/upstream/...: only 2 pre-existing govetreflect.Ptrfindings in files this PR does not touch (core/connection_stdio.go:375,core/client_secret_test.go:452)../scripts/test-api-e2e.shon an isolated port, run alone: 65/66; the one failure ("Audit log: server-edition binary present") is environmental and fails identically on origin/main. Earlier runs overlapped with sibling agents' e2e runs (shared launcher port 39933) and showed launcher failures that vanished when run alone.Assumptions
tools/callis limited to read-only tools per FR-081 (a non-conforming server or intermediary could 404 after executing). Spec 018 operation type is not visible tomanaged.Client, so only thereadOnlyHintannotation is used; tools without that hint get the "re-established, not repeated" error. A follow-up could pass thecall_tool_readvariant down.WithContinuousListeningis only used in an e2e test), so there is no listener to restore; not implemented.error_class=session_terminatedlabelling belongs to 113-c; this PR exposes the sentinelmanaged.ErrSessionReestablishedfor it to map.SessionSnapshotmodern flag anderrors.Ischeck).Spec: #1495
Review: opencode github-copilot/gpt-6.1-sol, 2 rounds, clean; follow-ups: (1) Spec 018 call_tool_read variant not passed down so unannotated read tools are not retried; (2) residual narrow window where a request that snapshotted the old session id is sent on the new id before the flight's tools/list verifies (closing it would serialize sends behind long tool calls); (3) tool-change epoch bump is not a mechanism in this codebase (FR-083 relies on the differential update path); (4) test hardening: RetryAlso404 reaching the retry, listener fixture; (5) a caller ctx deadline while waiting on a flight is classed as a connection error like any other deadline.