Repository navigation
Conversation
Add two opt-in limits so retained state cannot be grown without bound: - maxSessionsPerPrincipal caps the non-expired sessions a caller may keep active. Keyed by the session's (issuer, subject) pair when authorization identifies a caller, else a shared anonymous bucket. At the cap a new session is refused with SESSION_LIMIT_REACHED, and existing sessions keep working and expire on their own. The Redis store enforces it with an atomic Lua script (pruning expired ids on each create) so concurrent creates across instances cannot overshoot the cap. - maxResourceSubscriptionsPerSession caps the distinct URIs one session may subscribe to. Duplicates stay idempotent; only a new URI at the cap fails with SUBSCRIPTION_LIMIT_REACHED. Enforced atomically on Redis. The memory and Redis session stores both accept the options (default Infinity, no change for existing deployments). The subscribe handler and the POST/GET /mcp session-creation paths surface the errors as stable protocol errors. The GET SSE path now resolves the session before hijacking the reply, so a refused session answers with a 429 instead of a hung stream. Adds memory + Redis store tests and HTTP integration tests covering duplicate subscriptions, per-principal isolation, expiry cleanup, and concurrent Redis writes. Documents both options in the README and types.
This branch has not been deployed
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.
Adds opt-in limits so retained state cannot be grown without bound. Both default to
Infinity, so existing deployments behave exactly as before.maxSessionsPerPrincipalcaps the non-expired sessions a caller may keep active, keyed by the (issuer, subject) pair when authorization identifies a caller and otherwise by a shared anonymous bucket. At the cap a new session is refused withSESSION_LIMIT_REACHED(-32035), while existing sessions keep working and expire on their own. The Redis store enforces it with an atomic Lua script (pruning expired ids on each create) so concurrent creates across instances cannot overshoot the cap.maxResourceSubscriptionsPerSessioncaps the distinct URIs one session may subscribe to. Duplicates stay idempotent; only a new URI at the cap fails withSUBSCRIPTION_LIMIT_REACHED(-32036), enforced atomically on Redis.Both memory and Redis session stores accept the new options. The
resources/subscribehandler and thePOST/GET /mcpsession-creation paths surface these as stable protocol errors; theGETSSE path now resolves the session before hijacking the reply, so a refused session answers with a429instead of hanging.Covers memory and Redis backends, duplicate subscriptions, per-principal isolation, expiry cleanup, and concurrent Redis writes. Documents both options in the README and plugin types.
Fixes #312