feat: add RedisEventStore for production SSE resumability#2685
Open
Ar-maan05 wants to merge 12 commits into
Open
feat: add RedisEventStore for production SSE resumability#2685Ar-maan05 wants to merge 12 commits into
Ar-maan05 wants to merge 12 commits into
Conversation
…deprecation warnings
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.
Description
Closes #2570
This PR adds a production-grade, Redis-backed EventStore ( RedisEventStore ) to support SSE stream resumability in multi-process/multi-worker deployments.
The implementation resides in a new mcp.server.contrib package designed for production-grade add-ons requiring optional dependencies.
Design & Architecture
• Atomic Monotonic IDs: Uses a Redis string counter ( {prefix}counter ) and INCR to generate unique, monotonic integer event IDs safely across concurrent processes.
• Event Metadata: Uses a Redis Hash ( {prefix}event:{event_id} ) storing stream_id and the serialized JSONRPCMessage payload.
• Stream Ordering: Uses a Sorted Set ( {prefix}stream:{stream_id} ) to map event IDs to their integer score, allowing ZRANGEBYSCORE to perform
• Storing a message = None sentinel writes an empty string to Redis to identify priming events, which are skipped on replay.
• Cleans up keys using an optional ttl (Time to Live) on all keys generated ( counter , event , stream ). Logs a warning if ttl=None to prevent unbounded memory growth.
• Supports dynamic key_prefix to isolate multiple MCP servers sharing a single Redis instance/cluster.
• redis is placed in [project.optional-dependencies] under the redis extra.
• Type annotations/imports of redis.asyncio are enclosed inside if TYPE_CHECKING: guards. This ensures the MCP SDK remains fully importable and functional at runtime for users who do not install the redis extra.
How to Use
Install the optional dependency:
Configure your SSE manager:
Verification & Testing
Unit Tests
Wrote 21 extensive async unit tests using fakeredis to avoid external server dependencies in CI/CD.
• Monotonic ID generation and collision-free concurrency.
• Correct message serialization and deserialization roundtrips.
• Stream boundary isolation and replay sort order.
• Expiry/TTL setting correctness.
• Key prefix multi-tenant isolation.
• Warning log emissions.
Result: 21 passed.
Quality & Linting
• Checked and validated with pyright : 0 errors.
• Checked and formatted with ruff : All checks passed.