Adapters
You can begin with a single file server and add state only when you need it. Adapters let you swap in storage or queueing code without touching tools or handlers.
Scaling Playbook
Section titled “Scaling Playbook”Start simple and add complexity as needed:
- Local prototyping: Run the transport with no adapters. Every request is stateless and there is nothing to clean up.
- Single server: Add
InMemorySessionAdapter(and optionallyInMemoryClientRequestAdapter) so progress notifications and elicitations can span multiple requests from the same client. - Distributed or serverless: Implement the adapters against shared infrastructure (Redis, SQL, message queues, Durable Objects, etc.).
Deployment Patterns
Section titled “Deployment Patterns”| Environment | Session Storage | State Storage | Transport Configuration |
|---|---|---|---|
| Development | None | N/A | StreamableHttpTransport() |
| Single server | In-memory | In-memory | InMemorySessionAdapter |
| Distributed | Redis/KV | Redis/KV | Custom adapters |
Adapter Configuration
Section titled “Adapter Configuration”Development: Stateless
Section titled “Development: Stateless”const transport = new StreamableHttpTransport()Production: With Sessions and Client Requests
Section titled “Production: With Sessions and Client Requests”const transport = new StreamableHttpTransport({ sessionAdapter: new InMemorySessionAdapter({ maxEventBufferSize: 1024 }), clientRequestAdapter: new InMemoryClientRequestAdapter({ defaultTimeoutMs: 30000 })})Built-in Adapters
Section titled “Built-in Adapters”InMemorySessionAdapter
Section titled “InMemorySessionAdapter”Session storage in memory for single-server deployments.
import { InMemorySessionAdapter } from "mcp-lite";
const sessionAdapter = new InMemorySessionAdapter({ maxEventBufferSize: 1024 // Max events to buffer per session});InMemoryClientRequestAdapter
Section titled “InMemoryClientRequestAdapter”Client request tracking in memory for elicitation and sampling.
import { InMemoryClientRequestAdapter } from "mcp-lite";
const clientRequestAdapter = new InMemoryClientRequestAdapter({ defaultTimeoutMs: 30000 // Default timeout for client requests});Client Requests and Elicitation
Section titled “Client Requests and Elicitation”The server can send JSON-RPC requests back to the MCP client (for example when you call ctx.elicit). Those requests are routed through the ClientRequestAdapter.
Provide one when you need:
- Timeouts or retries for client prompts
- To make sure an elicitation response is delivered even when the original POST is finished
- To back the pending requests with shared storage in a multi-instance deployment
The in-memory adapter covers local runs. For production you can implement ClientRequestAdapter using Redis, a SQL store, Durable Objects, or any queue that can look up pending requests by session and request id.
Custom Adapters
Section titled “Custom Adapters”Implement these interfaces for custom storage:
SessionAdapter Interface
Section titled “SessionAdapter Interface”interface SessionAdapter { generateSessionId(): string create(id: string, meta: SessionMeta): Promise<SessionData> has(id: string): Promise<boolean> get(id: string): Promise<SessionData | undefined> appendEvent(id: string, streamId: string, message: unknown): Promise<EventId> replay(id: string, lastEventId: EventId, write: WriteFunction): Promise<void> delete(id: string): Promise<void>}ClientRequestAdapter Interface
Section titled “ClientRequestAdapter Interface”interface ClientRequestAdapter { createPending(sessionId: string, requestId: string, options): { promise: Promise<Response> } resolvePending(sessionId: string, requestId: string, response: Response): boolean rejectPending(sessionId: string, requestId: string, error: Error): boolean}Production Example
Section titled “Production Example”See examples/cloudflare-worker-kv for a production implementation using Cloudflare KV for both session and client request storage.
Next Steps
Section titled “Next Steps”- Deployment Patterns - Learn deployment strategies
- Elicitation - Implement client requests