Depends on #3866
Session-scoped clients multiply backend connections (N sessions × M backends). Without limits, a burst of session creation requests can exhaust file descriptors or memory. Implement configurable limits to protect the system.
Global session limit:
- Configurable via
TOOLHIVE_MAX_SESSIONS (or equivalent config key)
- When reached: reject new
InitializeRequest with HTTP 503 and a Retry-After header
- Error body:
{"error": {"code": -32000, "message": "Maximum concurrent sessions exceeded. Please try again later or contact administrator."}}
- No request queueing — reject immediately;
Retry-After gives clients the retry signal
- Do not expose current session count in the error response
Per-client session limit:
- Configurable maximum sessions per client identity/IP
- Enforced independently of the global limit
Idle session timeout:
- Sessions inactive for a configurable period (e.g. 5 minutes with no incoming requests) should be expired proactively, independently of the global session TTL
- This reclaims backend connections faster than waiting for the full TTL to elapse, reducing the steady-state connection count under low-traffic conditions
- Idle timeout must reset on every request touching the session (i.e. any
CallTool, ReadResource, or GetPrompt resets the idle clock)
- Configurable separately from the session TTL; idle timeout must be shorter than or equal to TTL
Acceptance Criteria
RFC: THV-0038 — Session-scoped client lifecycle
Depends on #3866
Session-scoped clients multiply backend connections (N sessions × M backends). Without limits, a burst of session creation requests can exhaust file descriptors or memory. Implement configurable limits to protect the system.
Global session limit:
TOOLHIVE_MAX_SESSIONS(or equivalent config key)InitializeRequestwith HTTP 503 and aRetry-Afterheader{"error": {"code": -32000, "message": "Maximum concurrent sessions exceeded. Please try again later or contact administrator."}}Retry-Aftergives clients the retry signalPer-client session limit:
Idle session timeout:
CallTool,ReadResource, orGetPromptresets the idle clock)Acceptance Criteria
Retry-AfterheaderRetry-Afteron global limit hit, per-client limit enforced, idle session expired after inactivity, active session not expired while in use, error response contains no internal dataRFC: THV-0038 — Session-scoped client lifecycle