Skip to main content
MCP servers can operate in two modes: stateful (with session tracking) and stateless (no session tracking).

Session Lifecycle

1. Session Initialization

A session begins when a client sends an initialize request:

2. Subsequent Requests

After initialization, the client includes the session ID in all requests:

3. Session Termination

Sessions can end in several ways:
  • Client closes: Client sends DELETE request to /mcp
  • Idle timeout: Session expires after inactivity (default: 1 day)
  • Server restart: In-memory sessions are lost; use Redis Storage to persist sessions across restarts

4. Session Not Found (404)

Per the MCP specification, when a client sends a request with an invalid or expired session ID, the server MUST return HTTP 404: Modern MCP clients (like mcp-use client) automatically handle 404 responses by sending a new initialize request.

Stateful vs Stateless Modes

Stateful Mode (Default for Node.js)

In stateful mode, the server tracks sessions across requests:
import { MCPServer } from 'mcp-use/server';

const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0',
  stateless: false  // Explicitly enable stateful mode
});

server.start({ port: 3000 });
Auto-detection: When stateless is not explicitly set, the server automatically detects mode per-request:
  • Client sends Accept: application/json, text/event-stream → Stateful mode
  • Client sends Accept: application/json only → Stateless mode
This enables compatibility with k6, curl, and other HTTP-only clients while maintaining full SSE support for capable clients. Features:
  • Session tracking with unique IDs
  • Client capability storage (sampling, elicitation, roots)
  • SSE streaming with resumability
  • Resource subscriptions and notifications
  • Idle session cleanup
Use cases:
  • Development and debugging
  • Single-instance deployments
  • Applications requiring persistent client context
  • Servers using sampling, elicitation, or notifications

Stateless Mode (Default for Deno)

In stateless mode, each request is independent:
import { MCPServer } from 'mcp-use/server';

const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0',
  stateless: true  // Force stateless mode
});

server.start({ port: 3000 });
Features:
  • No session tracking
  • New server instance per request
  • No memory of previous requests
  • Horizontal scaling friendly
Use cases:
  • Edge functions (Cloudflare Workers, Deno Deploy)
  • Serverless deployments (AWS Lambda, Vercel)
  • Load-balanced distributed systems
  • Simple, stateless APIs
Auto-detection:
// Auto-detects based on runtime
const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0'
  // stateless: true on Deno/edge runtimes
  // stateless: false on Node.js
});

Storage Providers

mcp-use supports multiple storage providers for session management:

Session Configuration

Idle Timeout

Configure how long sessions remain active without requests:
const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0',
  sessionIdleTimeoutMs: 3600000  // 1 hour (default: 1 day)
});

Deployment Patterns

Single Server

Simple development/single-instance deployment:
import { MCPServer } from 'mcp-use/server';

const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0'
  // Uses InMemorySessionStore + InMemoryStreamManager (defaults)
});
Characteristics:
  • ✅ All features work (notifications, sampling, subscriptions)
  • ✅ No external dependencies
  • ❌ Sessions lost on restart
  • ❌ Can’t scale horizontally

Persistent Sessions

Session metadata survives restarts, but still single server:
import { MCPServer, RedisSessionStore } from 'mcp-use/server';

const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0',
  sessionStore: new RedisSessionStore({ client: redis })
  // streamManager defaults to InMemoryStreamManager
});
Characteristics:
  • ✅ Session metadata persists across restarts
  • ✅ Clients resume sessions without re-initializing after a deploy
  • ✅ Notifications work (single server)
  • ❌ Can’t distribute across multiple instances
  • ⚠️ Active SSE connections still lost on restart (clients must reconnect)

Redis Session Example

Complete runnable example with session recovery and notifications across restarts.

Distributed

Complete horizontal scaling with all MCP features:
import { 
  MCPServer, 
  RedisSessionStore, 
  RedisStreamManager 
} from 'mcp-use/server';

const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0',
  sessionStore: new RedisSessionStore({ client: redis }),
  streamManager: new RedisStreamManager({ client: redis, pubSubClient: pubSubRedis })
});
Characteristics:
  • ✅ Full horizontal scaling
  • ✅ Notifications work across ALL servers
  • ✅ Sampling works across instances
  • ✅ Resource subscriptions work distributed
  • ✅ Load balancer can route requests anywhere
  • ✅ Session metadata persists

Stateless

No sessions, no state:
const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0',
  stateless: true
  // No session or stream managers needed
});
Characteristics:
  • ✅ Infinite horizontal scaling
  • ✅ No Redis needed
  • ❌ No notifications
  • ❌ No sampling
  • ❌ No resource subscriptions
  • ❌ No SSE streaming