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: 5 minutes)
  • Server restart: In-memory sessions are lost (see Storage Providers)

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: 600000  // 10 minutes (default: 5 minutes)
});

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
  • ✅ Notifications work (single server)
  • ❌ Can’t distribute across multiple instances
  • ⚠️ Active SSE connections still lost on restart

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