MCP TypeScript SDK Examples (Server)

April 28, 2026 · View on GitHub

This directory contains runnable MCP server examples built with @modelcontextprotocol/server plus framework adapters:

  • @modelcontextprotocol/express
  • @modelcontextprotocol/hono

For client examples, see ../client/README.md. For guided docs, see ../../docs/server.md.

Running examples

From anywhere in the SDK:

pnpm install
pnpm --filter @modelcontextprotocol/examples-server exec tsx src/simpleStreamableHttp.ts

Or, from within this package:

cd examples/server
pnpm tsx src/simpleStreamableHttp.ts

Example index

ScenarioDescriptionFile
Streamable HTTP server (stateful)Feature-rich server with tools/resources/prompts, logging, tasks, sampling, and optional OAuth.src/simpleStreamableHttp.ts
Streamable HTTP server (stateless)No session tracking; good for simple API-style servers.src/simpleStatelessStreamableHttp.ts
Resource-Server-only authMinimal OAuth RS using SDK's mcpAuthMetadataRouter + requireBearerAuth (no better-auth).src/resourceServerOnly.ts
JSON response mode (no SSE)Streamable HTTP with JSON-only responses and limited notifications.src/jsonResponseStreamableHttp.ts
Server notifications over Streamable HTTPDemonstrates server-initiated notifications via GET+SSE.src/standaloneSseWithGetStreamableHttp.ts
Output schema serverDemonstrates tool output validation with structured output schemas.src/mcpServerOutputSchema.ts
Form elicitation serverCollects non-sensitive user input via schema-driven forms.src/elicitationFormExample.ts
URL elicitation serverSecure browser-based flows for sensitive input (API keys, OAuth, payments).src/elicitationUrlExample.ts
Sampling + tasks serverDemonstrates sampling and experimental task-based execution.src/toolWithSampleServer.ts
Task interactive serverTask-based execution with interactive server→client requests.src/simpleTaskInteractive.ts
Hono Streamable HTTP serverStreamable HTTP server built with Hono instead of Express.src/honoWebStandardStreamableHttp.ts
SSE polling demo serverLegacy SSE server intended for polling demos.src/ssePollingExample.ts

OAuth demo flags (Streamable HTTP server)

pnpm --filter @modelcontextprotocol/examples-server exec tsx src/simpleStreamableHttp.ts --oauth

URL elicitation example (server + client)

Run the server:

pnpm --filter @modelcontextprotocol/examples-server exec tsx src/elicitationUrlExample.ts

Run the client in another terminal:

pnpm --filter @modelcontextprotocol/examples-client exec tsx src/elicitationUrlExample.ts

Multi-node deployment patterns

When deploying MCP servers in a horizontally scaled environment (multiple server instances), there are a few different options that can be useful for different use cases:

  • Stateless mode - no need to maintain state between calls.
  • Persistent storage mode - state stored in a database; any node can handle a session.
  • Local state with message routing - stateful nodes + pub/sub routing for a session.

Stateless mode

To enable stateless mode, configure the NodeStreamableHTTPServerTransport with:

sessionIdGenerator: undefined;
┌─────────────────────────────────────────────┐
│                  Client                     │
└─────────────────────────────────────────────┘


┌─────────────────────────────────────────────┐
│                Load Balancer                │
└─────────────────────────────────────────────┘
          │                       │
          ▼                       ▼
┌─────────────────┐     ┌─────────────────────┐
│  MCP Server #1  │     │    MCP Server #2    │
│ (Node.js)       │     │  (Node.js)          │
└─────────────────┘     └─────────────────────┘

Persistent storage mode

Configure the transport with session management, but use an external event store:

sessionIdGenerator: () => randomUUID(),
eventStore: databaseEventStore
┌─────────────────────────────────────────────┐
│                  Client                     │
└─────────────────────────────────────────────┘


┌─────────────────────────────────────────────┐
│                Load Balancer                │
└─────────────────────────────────────────────┘
          │                       │
          ▼                       ▼
┌─────────────────┐     ┌─────────────────────┐
│  MCP Server #1  │     │    MCP Server #2    │
│ (Node.js)       │     │  (Node.js)          │
└─────────────────┘     └─────────────────────┘
          │                       │
          │                       │
          ▼                       ▼
┌─────────────────────────────────────────────┐
│           Database (PostgreSQL)             │
│                                             │
│  • Session state                            │
│  • Event storage for resumability           │
└─────────────────────────────────────────────┘

Streamable HTTP with distributed message routing

For scenarios where local in-memory state must be maintained on specific nodes, combine Streamable HTTP with pub/sub routing so one node can terminate the client connection while another node owns the session state.

┌─────────────────────────────────────────────┐
│                  Client                     │
└─────────────────────────────────────────────┘


┌─────────────────────────────────────────────┐
│                Load Balancer                │
└─────────────────────────────────────────────┘
          │                       │
          ▼                       ▼
┌─────────────────┐     ┌─────────────────────┐
│  MCP Server #1  │◄───►│    MCP Server #2    │
│ (Has Session A) │     │  (Has Session B)    │
└─────────────────┘     └─────────────────────┘
          ▲│                     ▲│
          │▼                     │▼
┌─────────────────────────────────────────────┐
│         Message Queue / Pub-Sub             │
│                                             │
│  • Session ownership registry               │
│  • Bidirectional message routing            │
│  • Request/response forwarding              │
└─────────────────────────────────────────────┘

Backwards compatibility (Streamable HTTP ↔ legacy SSE)

Start the server:

pnpm --filter @modelcontextprotocol/examples-server exec tsx src/simpleStreamableHttp.ts

Then run the backwards-compatible client:

pnpm --filter @modelcontextprotocol/examples-client exec tsx src/streamableHttpWithSseFallbackClient.ts