turul-mcp-session-storage
Pluggable session storage backends for the turul-mcp-framework, supporting everything from in-memory development to distributed production deployments.
Overview
turul-mcp-session-storage
provides the SessionStorage
trait and multiple implementations for persisting MCP session data, state, and SSE events across different storage backends.
Features
- ✅ Pluggable Architecture - Swap backends without code changes
- ✅ Production Ready - Multiple production-grade backends
- ✅ Session Persistence - Sessions survive server restarts
- ✅ State Management - Type-safe session state storage
- ✅ SSE Event Storage - Event replay for SSE resumability
- ✅ Automatic Cleanup - TTL-based session expiry
- ✅ Multi-Instance Support - Distributed session sharing
Storage Backends
Backend | Use Case | Features | Production Ready |
---|---|---|---|
InMemory | Development/Testing | Fast, simple | ✅ Dev only |
SQLite | Single-instance production | File-based, ACID | ✅ Yes |
PostgreSQL | Multi-instance production | Distributed, scalable | ✅ Yes |
DynamoDB | Serverless/AWS Lambda | Auto-scaling, managed | ✅ Yes |
Quick Start
Add this to your Cargo.toml
:
[]
= { = "0.2.0", = ["sqlite"] }
= "0.2.0"
In-Memory (Development)
use McpServer;
use InMemorySessionStorage;
use Arc;
async
SQLite (Single Instance)
use SqliteSessionStorage;
use Arc;
// SQLite with file persistence (defaults to sessions.db in current directory)
let storage = new;
let server = builder
.with_session_storage
.build?;
PostgreSQL (Multi-Instance)
use PostgresSessionStorage;
use Arc;
// PostgreSQL for distributed deployments
let storage = new;
let server = builder
.with_session_storage
.build?;
DynamoDB (Serverless)
use DynamoDbSessionStorage;
use Arc;
// DynamoDB for AWS Lambda deployments
let storage = new;
let server = builder
.with_session_storage
.build?;
Session Management
Session Lifecycle
Sessions follow this lifecycle:
- Creation - Server assigns UUID v7 session ID
- Usage - Tools read/write session state
- Persistence - State automatically saved to storage
- Expiry - TTL-based cleanup (default 30 minutes)
- Cleanup - Automatic background cleanup
Session State API
use SessionContext;
use ;
// In your tool implementation
async
Session Information
async
SSE Event Storage
Event Persistence
All session backends support SSE event storage for resumability:
use SessionContext;
async
Event Replay
SSE clients can resume from any point using Last-Event-ID
:
GET /mcp HTTP/1.1
Accept: text/event-stream
Last-Event-ID: event-123
Mcp-Session-Id: sess-456
The storage backend will replay all events after event-123
.
Backend Configuration
SQLite Configuration
use ;
let config = SqliteConfig ;
let storage = with_config.await?;
PostgreSQL Configuration
use ;
let config = PostgreSqlConfig ;
let storage = with_config.await?;
DynamoDB Configuration
use ;
let config = DynamoDbConfig ;
let storage = with_config.await?;
Production Deployment
Single-Instance with SQLite
use ;
let storage = with_config.await?;
Multi-Instance with PostgreSQL
use ;
use Arc;
let database_url = var?;
let config = PostgresConfig ;
let storage = with_config.await?;
let server = builder
.bind
.with_session_storage
.build?;
Serverless with DynamoDB
For AWS Lambda and serverless:
use DynamoDbSessionStorage;
// Serverless DynamoDB setup
let storage = new.await?; // Uses AWS SDK defaults
// Perfect for Lambda deployments
let lambda_server = new
.storage
.build
.await?;
Custom Storage Backend
Implementing SessionStorage
use ;
use async_trait;
use Uuid;
use HashMap;
Error Handling
Storage Errors
Each backend defines its own error type:
use ;
match storage.get_session.await
Graceful Degradation
The framework provides graceful degradation when storage fails:
// Session operations that fail gracefully
if let Err = session.set_typed_state.await
Performance & Monitoring
Connection Pooling
Production backends use connection pooling:
// PostgreSQL with custom pool size
let storage = with_config.await?;
Metrics Collection
// Session metrics (example - implement in your monitoring)
async
Testing
Test Utilities
use *;
async
Integration Tests
# Test all backends
# Test specific backend
# Test with real databases (requires setup)
Feature Flags
[]
= { = "0.1.1", = ["sqlite", "postgres"] }
default
- Only InMemory backendsqlite
- SQLite backendpostgres
- PostgreSQL backenddynamodb
- DynamoDB backendredis
- Redis backend (planned)
Migration Guide
Upgrading Storage Backends
When upgrading from InMemory to persistent storage:
// Before (development)
let storage = new;
// After (production)
let storage = new;
// Server code stays the same!
let server = builder
.with_session_storage // No changes needed
.build?;
License
Licensed under the MIT License. See LICENSE for details.