Add --session-ttl flag and fix three session timeout bugs#5117
Open
Add --session-ttl flag and fix three session timeout bugs#5117
Conversation
cc9c396 to
bdca9c6
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #5117 +/- ##
==========================================
+ Coverage 67.12% 67.33% +0.20%
==========================================
Files 597 598 +1
Lines 60170 60533 +363
==========================================
+ Hits 40390 40759 +369
+ Misses 16706 16690 -16
- Partials 3074 3084 +10 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
The session inactivity timeout was previously a hardcoded constant (2h for transport proxies, 30m for vMCP). This adds a --session-ttl flag to thv run, thv vmcp serve, and the standalone vmcp serve command, and threads it through the runner, transport factory, and all three proxy types (HTTP+SSE, Streamable HTTP, Transparent). Zero means "use the default"; negative values are rejected at the CLI/builder layer. The runner resolves the effective TTL once and passes the non-zero value to both the transport config and Redis storage, so all consumers use the same session lifetime. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sessions were evicted by the TTL cleanup goroutine even while actively in use because session activity was not being recorded in the right places: 1. SSE keep-alive ticks now call sessionManager.Get to refresh the TTL while the SSE socket is open, so the cleanup goroutine does not evict clients that have not sent a POST request recently. 2. Single notifications/client-responses forwarded via the streamable HTTP proxy now also refresh the session TTL; previously the session header was not read from the request in that code path. 3. Removed ephemeral session creation in the streamable proxy for requests that arrive without an Mcp-Session-Id header. The old code created a UUID-keyed session per request and never cleaned it up, leaking memory over time. Sessionless requests are now routed with an empty sessID that is used only for in-process waiter-channel correlation; no persistent session object is created. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
bdca9c6 to
d62c210
Compare
jerm-dro
requested changes
Apr 29, 2026
Returning sessID="" for sessionless POSTs collapsed concurrent
sessionless requests with the same JSON-RPC id onto the same
compositeKey("", idKey). The in-process waiters and idRestore
sync.Maps silently overwrote, so one client could receive another
client's response payload (with the JSON-RPC id rewritten to its
own) and the losing client hung until the proxy request timeout.
Generate a per-request UUID in resolveSessionForRequest and
resolveSessionForBatch when no session header is provided. The
token is used solely as an in-process routing key and is not
registered with the session manager, so the original memory-leak
fix is preserved.
Add TestSessionlessConcurrentRequestsAreNotMixed: fires two
concurrent sessionless POSTs with the same JSON-RPC id but
different methods, with a sync barrier in the fake backend to
guarantee both proxy waiters are registered before any response
is dispatched. The backend echoes req.Method back so each client
can prove it received its own payload, not the other client's.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
MCP sessions were being evicted by the background TTL cleanup goroutine even while actively
in use, and there was no way to configure how long sessions should live. This PR fixes both.
Configurable TTL (
--session-ttlflag):SessionTTL time.Durationtotypes.Config,RunConfig, andvmcp.ServeConfigWithSessionTTLbuilder option inpkg/runner--session-ttlflag tothv run,thv vmcp serve, andvmcp serveafter all options are applied (previously
WithSessionTTLafterWithSessionStoragewould silently drop Redis storage)
Three session timeout bug fixes:
sessionManager.Getto refresh the TTL while the socketis open, preventing eviction of idle-SSE clients
header was not being read in that code path)
Mcp-Session-Id—sessionless requests now use
sessID=""for in-process waiter-channel correlationwithout creating persistent session objects (memory leak fix)
Type of change
Test plan
task test)task lint-fix)All tests in the changed packages pass. Pre-existing failures in
pkg/mcp/serverareunrelated (missing container runtime in the sandbox environment).
Changes
pkg/transport/types/transport.goSessionTTLtoConfigpkg/transport/proxy/httpsse/http_proxy.gopkg/transport/proxy/streamable/streamable_proxy.gopkg/transport/proxy/transparent/transparent_proxy.goSessionTTLpkg/transport/http.go,pkg/transport/stdio.gosessionTTLfield; wire from factorypkg/transport/factory.goSessionTTLfrom config to transportspkg/runner/config.goSessionTTLtoRunConfigpkg/runner/config_builder.goWithSessionTTLoptionpkg/runner/runner.gocmd/thv/app/run_flags.go,cmd/thv/app/vmcp.go--session-ttlflagcmd/vmcp/app/commands.go--session-ttlflagpkg/vmcp/cli/serve.goSessionTTLtoServeConfig; validationpkg/runner/config_builder_test.goWithSessionTTLDoes this introduce a user-facing change?
Yes. New optional
--session-ttlflag onthv run,thv vmcp serve, andvmcp serve.Accepts a Go duration string (e.g.
--session-ttl=4h). Defaults to the existing hardcodedvalues (2h for proxies, 30m for vMCP) so existing behaviour is unchanged when omitted.
Generated with Claude Code