Skip to content

Commit bda811a

Browse files
feat: Add CORS configuration for browser-based MCP clients
- Add cors middleware to example servers with Mcp-Session-Id exposed - Add CORS documentation section to README - Configure minimal CORS settings (only expose required headers) This enables browser-based clients to connect to MCP servers by properly exposing the Mcp-Session-Id header required for session management. Reported-by: Jerome
1 parent 1ac2e59 commit bda811a

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,26 @@ app.listen(3000);
584584
> );
585585
> ```
586586
587+
588+
#### CORS Configuration for Browser-Based Clients
589+
590+
If you'd like your server to be accessible by browser-based MCP clients, you'll need to configure CORS headers. The `Mcp-Session-Id` header must be exposed for browser clients to access it:
591+
592+
```typescript
593+
import cors from 'cors';
594+
595+
// Add CORS middleware before your MCP routes
596+
app.use(cors({
597+
origin: '*', // Configure appropriately for production
598+
exposedHeaders: ['Mcp-Session-Id']
599+
}));
600+
```
601+
602+
This configuration is necessary because:
603+
- The MCP streamable HTTP transport uses the `Mcp-Session-Id` header for session management
604+
- Browsers restrict access to response headers unless explicitly exposed via CORS
605+
- Without this configuration, browser-based clients won't be able to read the session ID from initialization responses
606+
587607
#### Without Session Management (Stateless)
588608

589609
For simpler use cases where session management isn't needed:

src/examples/server/jsonResponseStreamableHttp.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { McpServer } from '../../server/mcp.js';
44
import { StreamableHTTPServerTransport } from '../../server/streamableHttp.js';
55
import { z } from 'zod';
66
import { CallToolResult, isInitializeRequest } from '../../types.js';
7+
import cors from 'cors';
78

89

910
// Create an MCP server with implementation details
@@ -81,6 +82,12 @@ const getServer = () => {
8182
const app = express();
8283
app.use(express.json());
8384

85+
// Configure CORS to expose Mcp-Session-Id header for browser-based clients
86+
app.use(cors({
87+
origin: '*', // Allow all origins - adjust as needed for production
88+
exposedHeaders: ['Mcp-Session-Id']
89+
}));
90+
8491
// Map to store transports by session ID
8592
const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {};
8693

src/examples/server/simpleStatelessStreamableHttp.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { McpServer } from '../../server/mcp.js';
33
import { StreamableHTTPServerTransport } from '../../server/streamableHttp.js';
44
import { z } from 'zod';
55
import { CallToolResult, GetPromptResult, ReadResourceResult } from '../../types.js';
6+
import cors from 'cors';
67

78
const getServer = () => {
89
// Create an MCP server with implementation details
@@ -96,6 +97,12 @@ const getServer = () => {
9697
const app = express();
9798
app.use(express.json());
9899

100+
// Configure CORS to expose Mcp-Session-Id header for browser-based clients
101+
app.use(cors({
102+
origin: '*', // Allow all origins - adjust as needed for production
103+
exposedHeaders: ['Mcp-Session-Id']
104+
}));
105+
99106
app.post('/mcp', async (req: Request, res: Response) => {
100107
const server = getServer();
101108
try {

src/examples/server/sseAndStreamableHttpCompatibleServer.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { SSEServerTransport } from '../../server/sse.js';
66
import { z } from 'zod';
77
import { CallToolResult, isInitializeRequest } from '../../types.js';
88
import { InMemoryEventStore } from '../shared/inMemoryEventStore.js';
9+
import cors from 'cors';
910

1011
/**
1112
* This example server demonstrates backwards compatibility with both:
@@ -71,6 +72,12 @@ const getServer = () => {
7172
const app = express();
7273
app.use(express.json());
7374

75+
// Configure CORS to expose Mcp-Session-Id header for browser-based clients
76+
app.use(cors({
77+
origin: '*', // Allow all origins - adjust as needed for production
78+
exposedHeaders: ['Mcp-Session-Id']
79+
}));
80+
7481
// Store transports by session ID
7582
const transports: Record<string, StreamableHTTPServerTransport | SSEServerTransport> = {};
7683

0 commit comments

Comments
 (0)