Problem
The EventStore abstract class in streamable_http.py enables SSE stream resumability, but the only available implementation is the in-memory SimpleEventStore in the test suite. This works for single-process development but breaks in any realistic production deployment:
- Kubernetes / multi-replica: Each pod has its own in-memory state. A client reconnecting after a pod restart or load-balancer reroute to a different replica will find no events to replay — resumability silently fails.
- Process restarts: Any server restart drops all stored events, making
Last-Event-ID reconnection useless.
- Horizontal scaling: As agent workloads scale out, there's no way to share event history across instances.
Proposed Solution
Add two concrete EventStore implementations as optional extras:
RedisEventStore (mcp[redis])
- Store events as Redis Lists per
stream_id with configurable TTL
store_event: RPUSH + EXPIRE
replay_events_after: LRANGE + filter by event ID
- Uses
redis-py async client with connection pooling
- Suitable for high-throughput, low-latency workloads
PostgresEventStore (mcp[postgres])
- Store events in a simple
mcp_events(stream_id, event_id SERIAL, message JSONB, created_at) table
replay_events_after: indexed query WHERE stream_id = ? AND event_id > ?
- Uses
asyncpg
- Suitable for workloads needing durability or auditability
Both implementations would:
- Be tested with
testcontainers (real Redis/Postgres containers, no mocks)
- Include TTL/cleanup configuration to prevent unbounded growth
- Live under
src/mcp/server/contrib/ or a similar location — open to maintainer preference on placement
Why Now
The resumability feature was added relatively recently and the EventStore interface is clean and well-defined. Adding distributed backends is the natural next step before production adoption grows and this becomes a pain point.
Before I Start Coding
- Is there a preferred location for optional contrib implementations?
- Any preference on
redis-py vs coredis for the Redis client?
- Should these ship as optional extras in
pyproject.toml (mcp[redis]) or as a separate package?
Happy to start with Redis only and follow up with Postgres in a second PR if that's easier to review.
Problem
The
EventStoreabstract class instreamable_http.pyenables SSE stream resumability, but the only available implementation is the in-memorySimpleEventStorein the test suite. This works for single-process development but breaks in any realistic production deployment:Last-Event-IDreconnection useless.Proposed Solution
Add two concrete
EventStoreimplementations as optional extras:RedisEventStore(mcp[redis])stream_idwith configurable TTLstore_event:RPUSH+EXPIREreplay_events_after:LRANGE+ filter by event IDredis-pyasync client with connection poolingPostgresEventStore(mcp[postgres])mcp_events(stream_id, event_id SERIAL, message JSONB, created_at)tablereplay_events_after: indexed queryWHERE stream_id = ? AND event_id > ?asyncpgBoth implementations would:
testcontainers(real Redis/Postgres containers, no mocks)src/mcp/server/contrib/or a similar location — open to maintainer preference on placementWhy Now
The resumability feature was added relatively recently and the
EventStoreinterface is clean and well-defined. Adding distributed backends is the natural next step before production adoption grows and this becomes a pain point.Before I Start Coding
redis-pyvscoredisfor the Redis client?pyproject.toml(mcp[redis]) or as a separate package?Happy to start with Redis only and follow up with Postgres in a second PR if that's easier to review.