Skip to content

Commit ce17a45

Browse files
committed
feat(examples): add CORS headers for web client access
Enable browser-based MCP clients to access server examples by adding CORS middleware with proper MCP-specific headers: - Access-Control-Allow-Headers: Content-Type, mcp-session-id, mcp-protocol-version, last-event-id - Access-Control-Expose-Headers: mcp-session-id, mcp-protocol-version This addresses the CORS requirements discussed in ggml-org/llama.cpp#18334 for web frontends accessing MCP servers via Streamable HTTP and SSE. Updated examples: - simpleStreamableHttp.ts - simpleStatelessStreamableHttp.ts - simpleSseServer.ts - jsonResponseStreamableHttp.ts - standaloneSseWithGetStreamableHttp.ts - sseAndStreamableHttpCompatibleServer.ts - ssePollingExample.ts (updated existing cors() to include MCP headers)
1 parent 6b4d99f commit ce17a45

File tree

7 files changed

+83
-1
lines changed

7 files changed

+83
-1
lines changed

examples/server/src/jsonResponseStreamableHttp.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto';
22

33
import type { CallToolResult } from '@modelcontextprotocol/server';
44
import { createMcpExpressApp, isInitializeRequest, McpServer, StreamableHTTPServerTransport } from '@modelcontextprotocol/server';
5+
import cors from 'cors';
56
import type { Request, Response } from 'express';
67
import * as z from 'zod/v4';
78

@@ -95,6 +96,17 @@ const getServer = () => {
9596

9697
const app = createMcpExpressApp();
9798

99+
// Enable CORS for web clients
100+
// This allows browser-based MCP clients to access this server
101+
app.use(
102+
cors({
103+
origin: '*',
104+
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
105+
allowedHeaders: ['Content-Type', 'mcp-session-id', 'mcp-protocol-version', 'last-event-id'],
106+
exposedHeaders: ['mcp-session-id', 'mcp-protocol-version']
107+
})
108+
);
109+
98110
// Map to store transports by session ID
99111
const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {};
100112

examples/server/src/simpleSseServer.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { CallToolResult } from '@modelcontextprotocol/server';
22
import { createMcpExpressApp, McpServer, SSEServerTransport } from '@modelcontextprotocol/server';
3+
import cors from 'cors';
34
import type { Request, Response } from 'express';
45
import * as z from 'zod/v4';
56

@@ -78,6 +79,17 @@ const getServer = () => {
7879

7980
const app = createMcpExpressApp();
8081

82+
// Enable CORS for web clients
83+
// This allows browser-based MCP clients to access this server
84+
app.use(
85+
cors({
86+
origin: '*',
87+
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
88+
allowedHeaders: ['Content-Type', 'mcp-session-id', 'mcp-protocol-version', 'last-event-id'],
89+
exposedHeaders: ['mcp-session-id', 'mcp-protocol-version']
90+
})
91+
);
92+
8193
// Store transports by session ID
8294
const transports: Record<string, SSEServerTransport> = {};
8395

examples/server/src/simpleStatelessStreamableHttp.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { CallToolResult, GetPromptResult, ReadResourceResult } from '@modelcontextprotocol/server';
22
import { createMcpExpressApp, McpServer, StreamableHTTPServerTransport } from '@modelcontextprotocol/server';
3+
import cors from 'cors';
34
import type { Request, Response } from 'express';
45
import * as z from 'zod/v4';
56

@@ -100,6 +101,17 @@ const getServer = () => {
100101

101102
const app = createMcpExpressApp();
102103

104+
// Enable CORS for web clients
105+
// This allows browser-based MCP clients to access this server
106+
app.use(
107+
cors({
108+
origin: '*',
109+
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
110+
allowedHeaders: ['Content-Type', 'mcp-session-id', 'mcp-protocol-version', 'last-event-id'],
111+
exposedHeaders: ['mcp-session-id', 'mcp-protocol-version']
112+
})
113+
);
114+
103115
app.post('/mcp', async (req: Request, res: Response) => {
104116
const server = getServer();
105117
try {

examples/server/src/simpleStreamableHttp.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
requireBearerAuth,
2323
StreamableHTTPServerTransport
2424
} from '@modelcontextprotocol/server';
25+
import cors from 'cors';
2526
import type { Request, Response } from 'express';
2627
import * as z from 'zod/v4';
2728

@@ -520,6 +521,17 @@ const AUTH_PORT = process.env.MCP_AUTH_PORT ? parseInt(process.env.MCP_AUTH_PORT
520521

521522
const app = createMcpExpressApp();
522523

524+
// Enable CORS for web clients
525+
// This allows browser-based MCP clients to access this server
526+
app.use(
527+
cors({
528+
origin: '*',
529+
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
530+
allowedHeaders: ['Content-Type', 'mcp-session-id', 'mcp-protocol-version', 'last-event-id'],
531+
exposedHeaders: ['mcp-session-id', 'mcp-protocol-version']
532+
})
533+
);
534+
523535
// Set up OAuth if enabled
524536
let authMiddleware = null;
525537
if (useOAuth) {

examples/server/src/sseAndStreamableHttpCompatibleServer.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
SSEServerTransport,
99
StreamableHTTPServerTransport
1010
} from '@modelcontextprotocol/server';
11+
import cors from 'cors';
1112
import type { Request, Response } from 'express';
1213
import * as z from 'zod/v4';
1314

@@ -80,6 +81,17 @@ const getServer = () => {
8081
// Create Express application
8182
const app = createMcpExpressApp();
8283

84+
// Enable CORS for web clients
85+
// This allows browser-based MCP clients to access this server
86+
app.use(
87+
cors({
88+
origin: '*',
89+
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
90+
allowedHeaders: ['Content-Type', 'mcp-session-id', 'mcp-protocol-version', 'last-event-id'],
91+
exposedHeaders: ['mcp-session-id', 'mcp-protocol-version']
92+
})
93+
);
94+
8395
// Store transports by session ID
8496
const transports: Record<string, StreamableHTTPServerTransport | SSEServerTransport> = {};
8597

examples/server/src/ssePollingExample.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,17 @@ server.tool(
105105

106106
// Set up Express app
107107
const app = createMcpExpressApp();
108-
app.use(cors());
108+
109+
// Enable CORS for web clients
110+
// This allows browser-based MCP clients to access this server
111+
app.use(
112+
cors({
113+
origin: '*',
114+
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
115+
allowedHeaders: ['Content-Type', 'mcp-session-id', 'mcp-protocol-version', 'last-event-id'],
116+
exposedHeaders: ['mcp-session-id', 'mcp-protocol-version']
117+
})
118+
);
109119

110120
// Create event store for resumability
111121
const eventStore = new InMemoryEventStore();

examples/server/src/standaloneSseWithGetStreamableHttp.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto';
22

33
import type { ReadResourceResult } from '@modelcontextprotocol/server';
44
import { createMcpExpressApp, isInitializeRequest, McpServer, StreamableHTTPServerTransport } from '@modelcontextprotocol/server';
5+
import cors from 'cors';
56
import type { Request, Response } from 'express';
67

78
// Create an MCP server with implementation details
@@ -36,6 +37,17 @@ const resourceChangeInterval = setInterval(() => {
3637

3738
const app = createMcpExpressApp();
3839

40+
// Enable CORS for web clients
41+
// This allows browser-based MCP clients to access this server
42+
app.use(
43+
cors({
44+
origin: '*',
45+
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
46+
allowedHeaders: ['Content-Type', 'mcp-session-id', 'mcp-protocol-version', 'last-event-id'],
47+
exposedHeaders: ['mcp-session-id', 'mcp-protocol-version']
48+
})
49+
);
50+
3951
app.post('/mcp', async (req: Request, res: Response) => {
4052
console.log('Received MCP request:', req.body);
4153
try {

0 commit comments

Comments
 (0)