@modelcontextprotocol/sdk 1.9.0 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +321 -28
- package/dist/cjs/client/index.d.ts.map +1 -1
- package/dist/cjs/client/index.js +5 -0
- package/dist/cjs/client/index.js.map +1 -1
- package/dist/cjs/client/streamableHttp.d.ts +124 -0
- package/dist/cjs/client/streamableHttp.d.ts.map +1 -0
- package/dist/cjs/client/streamableHttp.js +353 -0
- package/dist/cjs/client/streamableHttp.js.map +1 -0
- package/dist/cjs/examples/client/simpleStreamableHttp.d.ts +2 -0
- package/dist/cjs/examples/client/simpleStreamableHttp.d.ts.map +1 -0
- package/dist/cjs/examples/client/simpleStreamableHttp.js +448 -0
- package/dist/cjs/examples/client/simpleStreamableHttp.js.map +1 -0
- package/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.d.ts +2 -0
- package/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.d.ts.map +1 -0
- package/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.js +168 -0
- package/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.js.map +1 -0
- package/dist/cjs/examples/server/jsonResponseStreamableHttp.d.ts +2 -0
- package/dist/cjs/examples/server/jsonResponseStreamableHttp.d.ts.map +1 -0
- package/dist/cjs/examples/server/jsonResponseStreamableHttp.js +139 -0
- package/dist/cjs/examples/server/jsonResponseStreamableHttp.js.map +1 -0
- package/dist/cjs/examples/server/simpleSseServer.d.ts +2 -0
- package/dist/cjs/examples/server/simpleSseServer.d.ts.map +1 -0
- package/dist/cjs/examples/server/simpleSseServer.js +148 -0
- package/dist/cjs/examples/server/simpleSseServer.js.map +1 -0
- package/dist/cjs/examples/server/simpleStatelessStreamableHttp.d.ts +2 -0
- package/dist/cjs/examples/server/simpleStatelessStreamableHttp.d.ts.map +1 -0
- package/dist/cjs/examples/server/simpleStatelessStreamableHttp.js +149 -0
- package/dist/cjs/examples/server/simpleStatelessStreamableHttp.js.map +1 -0
- package/dist/cjs/examples/server/simpleStreamableHttp.d.ts +2 -0
- package/dist/cjs/examples/server/simpleStreamableHttp.d.ts.map +1 -0
- package/dist/cjs/examples/server/simpleStreamableHttp.js +250 -0
- package/dist/cjs/examples/server/simpleStreamableHttp.js.map +1 -0
- package/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.d.ts +2 -0
- package/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.d.ts.map +1 -0
- package/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.js +229 -0
- package/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.js.map +1 -0
- package/dist/cjs/examples/server/standaloneSseWithGetStreamableHttp.d.ts +2 -0
- package/dist/cjs/examples/server/standaloneSseWithGetStreamableHttp.d.ts.map +1 -0
- package/dist/cjs/examples/server/standaloneSseWithGetStreamableHttp.js +112 -0
- package/dist/cjs/examples/server/standaloneSseWithGetStreamableHttp.js.map +1 -0
- package/dist/cjs/examples/shared/inMemoryEventStore.d.ts +31 -0
- package/dist/cjs/examples/shared/inMemoryEventStore.d.ts.map +1 -0
- package/dist/cjs/examples/shared/inMemoryEventStore.js +69 -0
- package/dist/cjs/examples/shared/inMemoryEventStore.js.map +1 -0
- package/dist/cjs/inMemory.d.ts +13 -3
- package/dist/cjs/inMemory.d.ts.map +1 -1
- package/dist/cjs/inMemory.js +9 -7
- package/dist/cjs/inMemory.js.map +1 -1
- package/dist/cjs/server/auth/types.d.ts +5 -0
- package/dist/cjs/server/auth/types.d.ts.map +1 -1
- package/dist/cjs/server/mcp.d.ts +100 -19
- package/dist/cjs/server/mcp.d.ts.map +1 -1
- package/dist/cjs/server/mcp.js +154 -12
- package/dist/cjs/server/mcp.js.map +1 -1
- package/dist/cjs/server/sse.d.ts +10 -3
- package/dist/cjs/server/sse.d.ts.map +1 -1
- package/dist/cjs/server/sse.js +13 -4
- package/dist/cjs/server/sse.js.map +1 -1
- package/dist/cjs/server/streamableHttp.d.ts +146 -0
- package/dist/cjs/server/streamableHttp.d.ts.map +1 -0
- package/dist/cjs/server/streamableHttp.js +538 -0
- package/dist/cjs/server/streamableHttp.js.map +1 -0
- package/dist/cjs/shared/protocol.d.ts +31 -5
- package/dist/cjs/shared/protocol.d.ts.map +1 -1
- package/dist/cjs/shared/protocol.js +23 -15
- package/dist/cjs/shared/protocol.js.map +1 -1
- package/dist/cjs/shared/transport.d.ts +32 -3
- package/dist/cjs/shared/transport.d.ts.map +1 -1
- package/dist/cjs/types.d.ts +6 -0
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/types.js +14 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +5 -0
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/streamableHttp.d.ts +124 -0
- package/dist/esm/client/streamableHttp.d.ts.map +1 -0
- package/dist/esm/client/streamableHttp.js +348 -0
- package/dist/esm/client/streamableHttp.js.map +1 -0
- package/dist/esm/examples/client/simpleStreamableHttp.d.ts +2 -0
- package/dist/esm/examples/client/simpleStreamableHttp.d.ts.map +1 -0
- package/dist/esm/examples/client/simpleStreamableHttp.js +446 -0
- package/dist/esm/examples/client/simpleStreamableHttp.js.map +1 -0
- package/dist/esm/examples/client/streamableHttpWithSseFallbackClient.d.ts +2 -0
- package/dist/esm/examples/client/streamableHttpWithSseFallbackClient.d.ts.map +1 -0
- package/dist/esm/examples/client/streamableHttpWithSseFallbackClient.js +166 -0
- package/dist/esm/examples/client/streamableHttpWithSseFallbackClient.js.map +1 -0
- package/dist/esm/examples/server/jsonResponseStreamableHttp.d.ts +2 -0
- package/dist/esm/examples/server/jsonResponseStreamableHttp.d.ts.map +1 -0
- package/dist/esm/examples/server/jsonResponseStreamableHttp.js +134 -0
- package/dist/esm/examples/server/jsonResponseStreamableHttp.js.map +1 -0
- package/dist/esm/examples/server/simpleSseServer.d.ts +2 -0
- package/dist/esm/examples/server/simpleSseServer.d.ts.map +1 -0
- package/dist/esm/examples/server/simpleSseServer.js +143 -0
- package/dist/esm/examples/server/simpleSseServer.js.map +1 -0
- package/dist/esm/examples/server/simpleStatelessStreamableHttp.d.ts +2 -0
- package/dist/esm/examples/server/simpleStatelessStreamableHttp.d.ts.map +1 -0
- package/dist/esm/examples/server/simpleStatelessStreamableHttp.js +144 -0
- package/dist/esm/examples/server/simpleStatelessStreamableHttp.js.map +1 -0
- package/dist/esm/examples/server/simpleStreamableHttp.d.ts +2 -0
- package/dist/esm/examples/server/simpleStreamableHttp.d.ts.map +1 -0
- package/dist/esm/examples/server/simpleStreamableHttp.js +245 -0
- package/dist/esm/examples/server/simpleStreamableHttp.js.map +1 -0
- package/dist/esm/examples/server/sseAndStreamableHttpCompatibleServer.d.ts +2 -0
- package/dist/esm/examples/server/sseAndStreamableHttpCompatibleServer.d.ts.map +1 -0
- package/dist/esm/examples/server/sseAndStreamableHttpCompatibleServer.js +224 -0
- package/dist/esm/examples/server/sseAndStreamableHttpCompatibleServer.js.map +1 -0
- package/dist/esm/examples/server/standaloneSseWithGetStreamableHttp.d.ts +2 -0
- package/dist/esm/examples/server/standaloneSseWithGetStreamableHttp.d.ts.map +1 -0
- package/dist/esm/examples/server/standaloneSseWithGetStreamableHttp.js +107 -0
- package/dist/esm/examples/server/standaloneSseWithGetStreamableHttp.js.map +1 -0
- package/dist/esm/examples/shared/inMemoryEventStore.d.ts +31 -0
- package/dist/esm/examples/shared/inMemoryEventStore.d.ts.map +1 -0
- package/dist/esm/examples/shared/inMemoryEventStore.js +65 -0
- package/dist/esm/examples/shared/inMemoryEventStore.js.map +1 -0
- package/dist/esm/inMemory.d.ts +13 -3
- package/dist/esm/inMemory.d.ts.map +1 -1
- package/dist/esm/inMemory.js +9 -7
- package/dist/esm/inMemory.js.map +1 -1
- package/dist/esm/server/auth/types.d.ts +5 -0
- package/dist/esm/server/auth/types.d.ts.map +1 -1
- package/dist/esm/server/mcp.d.ts +100 -19
- package/dist/esm/server/mcp.d.ts.map +1 -1
- package/dist/esm/server/mcp.js +154 -12
- package/dist/esm/server/mcp.js.map +1 -1
- package/dist/esm/server/sse.d.ts +10 -3
- package/dist/esm/server/sse.d.ts.map +1 -1
- package/dist/esm/server/sse.js +13 -4
- package/dist/esm/server/sse.js.map +1 -1
- package/dist/esm/server/streamableHttp.d.ts +146 -0
- package/dist/esm/server/streamableHttp.d.ts.map +1 -0
- package/dist/esm/server/streamableHttp.js +531 -0
- package/dist/esm/server/streamableHttp.js.map +1 -0
- package/dist/esm/shared/protocol.d.ts +31 -5
- package/dist/esm/shared/protocol.d.ts.map +1 -1
- package/dist/esm/shared/protocol.js +24 -16
- package/dist/esm/shared/protocol.js.map +1 -1
- package/dist/esm/shared/transport.d.ts +32 -3
- package/dist/esm/shared/transport.d.ts.map +1 -1
- package/dist/esm/types.d.ts +6 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js +6 -0
- package/dist/esm/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { McpServer } from '../../server/mcp.js';
|
|
4
|
+
import { StreamableHTTPServerTransport } from '../../server/streamableHttp.js';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { isInitializeRequest } from '../../types.js';
|
|
7
|
+
import { InMemoryEventStore } from '../shared/inMemoryEventStore.js';
|
|
8
|
+
// Create an MCP server with implementation details
|
|
9
|
+
const server = new McpServer({
|
|
10
|
+
name: 'simple-streamable-http-server',
|
|
11
|
+
version: '1.0.0',
|
|
12
|
+
}, { capabilities: { logging: {} } });
|
|
13
|
+
// Register a simple tool that returns a greeting
|
|
14
|
+
server.tool('greet', 'A simple greeting tool', {
|
|
15
|
+
name: z.string().describe('Name to greet'),
|
|
16
|
+
}, async ({ name }) => {
|
|
17
|
+
return {
|
|
18
|
+
content: [
|
|
19
|
+
{
|
|
20
|
+
type: 'text',
|
|
21
|
+
text: `Hello, ${name}!`,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
// Register a tool that sends multiple greetings with notifications
|
|
27
|
+
server.tool('multi-greet', 'A tool that sends different greetings with delays between them', {
|
|
28
|
+
name: z.string().describe('Name to greet'),
|
|
29
|
+
}, async ({ name }, { sendNotification }) => {
|
|
30
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
31
|
+
await sendNotification({
|
|
32
|
+
method: "notifications/message",
|
|
33
|
+
params: { level: "debug", data: `Starting multi-greet for ${name}` }
|
|
34
|
+
});
|
|
35
|
+
await sleep(1000); // Wait 1 second before first greeting
|
|
36
|
+
await sendNotification({
|
|
37
|
+
method: "notifications/message",
|
|
38
|
+
params: { level: "info", data: `Sending first greeting to ${name}` }
|
|
39
|
+
});
|
|
40
|
+
await sleep(1000); // Wait another second before second greeting
|
|
41
|
+
await sendNotification({
|
|
42
|
+
method: "notifications/message",
|
|
43
|
+
params: { level: "info", data: `Sending second greeting to ${name}` }
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
content: [
|
|
47
|
+
{
|
|
48
|
+
type: 'text',
|
|
49
|
+
text: `Good morning, ${name}!`,
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
// Register a simple prompt
|
|
55
|
+
server.prompt('greeting-template', 'A simple greeting prompt template', {
|
|
56
|
+
name: z.string().describe('Name to include in greeting'),
|
|
57
|
+
}, async ({ name }) => {
|
|
58
|
+
return {
|
|
59
|
+
messages: [
|
|
60
|
+
{
|
|
61
|
+
role: 'user',
|
|
62
|
+
content: {
|
|
63
|
+
type: 'text',
|
|
64
|
+
text: `Please greet ${name} in a friendly manner.`,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
// Register a tool specifically for testing resumability
|
|
71
|
+
server.tool('start-notification-stream', 'Starts sending periodic notifications for testing resumability', {
|
|
72
|
+
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
|
73
|
+
count: z.number().describe('Number of notifications to send (0 for 100)').default(50),
|
|
74
|
+
}, async ({ interval, count }, { sendNotification }) => {
|
|
75
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
76
|
+
let counter = 0;
|
|
77
|
+
while (count === 0 || counter < count) {
|
|
78
|
+
counter++;
|
|
79
|
+
try {
|
|
80
|
+
await sendNotification({
|
|
81
|
+
method: "notifications/message",
|
|
82
|
+
params: {
|
|
83
|
+
level: "info",
|
|
84
|
+
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.error("Error sending notification:", error);
|
|
90
|
+
}
|
|
91
|
+
// Wait for the specified interval
|
|
92
|
+
await sleep(interval);
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
content: [
|
|
96
|
+
{
|
|
97
|
+
type: 'text',
|
|
98
|
+
text: `Started sending periodic notifications every ${interval}ms`,
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
// Create a simple resource at a fixed URI
|
|
104
|
+
server.resource('greeting-resource', 'https://example.com/greetings/default', { mimeType: 'text/plain' }, async () => {
|
|
105
|
+
return {
|
|
106
|
+
contents: [
|
|
107
|
+
{
|
|
108
|
+
uri: 'https://example.com/greetings/default',
|
|
109
|
+
text: 'Hello, world!',
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
const app = express();
|
|
115
|
+
app.use(express.json());
|
|
116
|
+
// Map to store transports by session ID
|
|
117
|
+
const transports = {};
|
|
118
|
+
app.post('/mcp', async (req, res) => {
|
|
119
|
+
console.log('Received MCP request:', req.body);
|
|
120
|
+
try {
|
|
121
|
+
// Check for existing session ID
|
|
122
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
123
|
+
let transport;
|
|
124
|
+
if (sessionId && transports[sessionId]) {
|
|
125
|
+
// Reuse existing transport
|
|
126
|
+
transport = transports[sessionId];
|
|
127
|
+
}
|
|
128
|
+
else if (!sessionId && isInitializeRequest(req.body)) {
|
|
129
|
+
// New initialization request
|
|
130
|
+
const eventStore = new InMemoryEventStore();
|
|
131
|
+
transport = new StreamableHTTPServerTransport({
|
|
132
|
+
sessionIdGenerator: () => randomUUID(),
|
|
133
|
+
eventStore, // Enable resumability
|
|
134
|
+
onsessioninitialized: (sessionId) => {
|
|
135
|
+
// Store the transport by session ID when session is initialized
|
|
136
|
+
// This avoids race conditions where requests might come in before the session is stored
|
|
137
|
+
console.log(`Session initialized with ID: ${sessionId}`);
|
|
138
|
+
transports[sessionId] = transport;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// Set up onclose handler to clean up transport when closed
|
|
142
|
+
transport.onclose = () => {
|
|
143
|
+
const sid = transport.sessionId;
|
|
144
|
+
if (sid && transports[sid]) {
|
|
145
|
+
console.log(`Transport closed for session ${sid}, removing from transports map`);
|
|
146
|
+
delete transports[sid];
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
// Connect the transport to the MCP server BEFORE handling the request
|
|
150
|
+
// so responses can flow back through the same transport
|
|
151
|
+
await server.connect(transport);
|
|
152
|
+
await transport.handleRequest(req, res, req.body);
|
|
153
|
+
return; // Already handled
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// Invalid request - no session ID or not initialization request
|
|
157
|
+
res.status(400).json({
|
|
158
|
+
jsonrpc: '2.0',
|
|
159
|
+
error: {
|
|
160
|
+
code: -32000,
|
|
161
|
+
message: 'Bad Request: No valid session ID provided',
|
|
162
|
+
},
|
|
163
|
+
id: null,
|
|
164
|
+
});
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// Handle the request with existing transport - no need to reconnect
|
|
168
|
+
// The existing transport is already connected to the server
|
|
169
|
+
await transport.handleRequest(req, res, req.body);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error('Error handling MCP request:', error);
|
|
173
|
+
if (!res.headersSent) {
|
|
174
|
+
res.status(500).json({
|
|
175
|
+
jsonrpc: '2.0',
|
|
176
|
+
error: {
|
|
177
|
+
code: -32603,
|
|
178
|
+
message: 'Internal server error',
|
|
179
|
+
},
|
|
180
|
+
id: null,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
// Handle GET requests for SSE streams (using built-in support from StreamableHTTP)
|
|
186
|
+
app.get('/mcp', async (req, res) => {
|
|
187
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
188
|
+
if (!sessionId || !transports[sessionId]) {
|
|
189
|
+
res.status(400).send('Invalid or missing session ID');
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
// Check for Last-Event-ID header for resumability
|
|
193
|
+
const lastEventId = req.headers['last-event-id'];
|
|
194
|
+
if (lastEventId) {
|
|
195
|
+
console.log(`Client reconnecting with Last-Event-ID: ${lastEventId}`);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
console.log(`Establishing new SSE stream for session ${sessionId}`);
|
|
199
|
+
}
|
|
200
|
+
const transport = transports[sessionId];
|
|
201
|
+
await transport.handleRequest(req, res);
|
|
202
|
+
});
|
|
203
|
+
// Handle DELETE requests for session termination (according to MCP spec)
|
|
204
|
+
app.delete('/mcp', async (req, res) => {
|
|
205
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
206
|
+
if (!sessionId || !transports[sessionId]) {
|
|
207
|
+
res.status(400).send('Invalid or missing session ID');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
console.log(`Received session termination request for session ${sessionId}`);
|
|
211
|
+
try {
|
|
212
|
+
const transport = transports[sessionId];
|
|
213
|
+
await transport.handleRequest(req, res);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
console.error('Error handling session termination:', error);
|
|
217
|
+
if (!res.headersSent) {
|
|
218
|
+
res.status(500).send('Error processing session termination');
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
// Start the server
|
|
223
|
+
const PORT = 3000;
|
|
224
|
+
app.listen(PORT, () => {
|
|
225
|
+
console.log(`MCP Streamable HTTP Server listening on port ${PORT}`);
|
|
226
|
+
});
|
|
227
|
+
// Handle server shutdown
|
|
228
|
+
process.on('SIGINT', async () => {
|
|
229
|
+
console.log('Shutting down server...');
|
|
230
|
+
// Close all active transports to properly clean up resources
|
|
231
|
+
for (const sessionId in transports) {
|
|
232
|
+
try {
|
|
233
|
+
console.log(`Closing transport for session ${sessionId}`);
|
|
234
|
+
await transports[sessionId].close();
|
|
235
|
+
delete transports[sessionId];
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
console.error(`Error closing transport for session ${sessionId}:`, error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
await server.close();
|
|
242
|
+
console.log('Server shutdown complete');
|
|
243
|
+
process.exit(0);
|
|
244
|
+
});
|
|
245
|
+
//# sourceMappingURL=simpleStreamableHttp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simpleStreamableHttp.js","sourceRoot":"","sources":["../../../../src/examples/server/simpleStreamableHttp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sseAndStreamableHttpCompatibleServer.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/sseAndStreamableHttpCompatibleServer.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { McpServer } from '../../server/mcp.js';
|
|
4
|
+
import { StreamableHTTPServerTransport } from '../../server/streamableHttp.js';
|
|
5
|
+
import { SSEServerTransport } from '../../server/sse.js';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { isInitializeRequest } from '../../types.js';
|
|
8
|
+
import { InMemoryEventStore } from '../shared/inMemoryEventStore.js';
|
|
9
|
+
/**
|
|
10
|
+
* This example server demonstrates backwards compatibility with both:
|
|
11
|
+
* 1. The deprecated HTTP+SSE transport (protocol version 2024-11-05)
|
|
12
|
+
* 2. The Streamable HTTP transport (protocol version 2025-03-26)
|
|
13
|
+
*
|
|
14
|
+
* It maintains a single MCP server instance but exposes two transport options:
|
|
15
|
+
* - /mcp: The new Streamable HTTP endpoint (supports GET/POST/DELETE)
|
|
16
|
+
* - /sse: The deprecated SSE endpoint for older clients (GET to establish stream)
|
|
17
|
+
* - /messages: The deprecated POST endpoint for older clients (POST to send messages)
|
|
18
|
+
*/
|
|
19
|
+
const server = new McpServer({
|
|
20
|
+
name: 'backwards-compatible-server',
|
|
21
|
+
version: '1.0.0',
|
|
22
|
+
}, { capabilities: { logging: {} } });
|
|
23
|
+
// Register a simple tool that sends notifications over time
|
|
24
|
+
server.tool('start-notification-stream', 'Starts sending periodic notifications for testing resumability', {
|
|
25
|
+
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
|
26
|
+
count: z.number().describe('Number of notifications to send (0 for 100)').default(50),
|
|
27
|
+
}, async ({ interval, count }, { sendNotification }) => {
|
|
28
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
29
|
+
let counter = 0;
|
|
30
|
+
while (count === 0 || counter < count) {
|
|
31
|
+
counter++;
|
|
32
|
+
try {
|
|
33
|
+
await sendNotification({
|
|
34
|
+
method: "notifications/message",
|
|
35
|
+
params: {
|
|
36
|
+
level: "info",
|
|
37
|
+
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error("Error sending notification:", error);
|
|
43
|
+
}
|
|
44
|
+
// Wait for the specified interval
|
|
45
|
+
await sleep(interval);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: 'text',
|
|
51
|
+
text: `Started sending periodic notifications every ${interval}ms`,
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
// Create Express application
|
|
57
|
+
const app = express();
|
|
58
|
+
app.use(express.json());
|
|
59
|
+
// Store transports by session ID
|
|
60
|
+
const transports = {};
|
|
61
|
+
//=============================================================================
|
|
62
|
+
// STREAMABLE HTTP TRANSPORT (PROTOCOL VERSION 2025-03-26)
|
|
63
|
+
//=============================================================================
|
|
64
|
+
// Handle all MCP Streamable HTTP requests (GET, POST, DELETE) on a single endpoint
|
|
65
|
+
app.all('/mcp', async (req, res) => {
|
|
66
|
+
console.log(`Received ${req.method} request to /mcp`);
|
|
67
|
+
try {
|
|
68
|
+
// Check for existing session ID
|
|
69
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
70
|
+
let transport;
|
|
71
|
+
if (sessionId && transports[sessionId]) {
|
|
72
|
+
// Check if the transport is of the correct type
|
|
73
|
+
const existingTransport = transports[sessionId];
|
|
74
|
+
if (existingTransport instanceof StreamableHTTPServerTransport) {
|
|
75
|
+
// Reuse existing transport
|
|
76
|
+
transport = existingTransport;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Transport exists but is not a StreamableHTTPServerTransport (could be SSEServerTransport)
|
|
80
|
+
res.status(400).json({
|
|
81
|
+
jsonrpc: '2.0',
|
|
82
|
+
error: {
|
|
83
|
+
code: -32000,
|
|
84
|
+
message: 'Bad Request: Session exists but uses a different transport protocol',
|
|
85
|
+
},
|
|
86
|
+
id: null,
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (!sessionId && req.method === 'POST' && isInitializeRequest(req.body)) {
|
|
92
|
+
const eventStore = new InMemoryEventStore();
|
|
93
|
+
transport = new StreamableHTTPServerTransport({
|
|
94
|
+
sessionIdGenerator: () => randomUUID(),
|
|
95
|
+
eventStore, // Enable resumability
|
|
96
|
+
onsessioninitialized: (sessionId) => {
|
|
97
|
+
// Store the transport by session ID when session is initialized
|
|
98
|
+
console.log(`StreamableHTTP session initialized with ID: ${sessionId}`);
|
|
99
|
+
transports[sessionId] = transport;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
// Set up onclose handler to clean up transport when closed
|
|
103
|
+
transport.onclose = () => {
|
|
104
|
+
const sid = transport.sessionId;
|
|
105
|
+
if (sid && transports[sid]) {
|
|
106
|
+
console.log(`Transport closed for session ${sid}, removing from transports map`);
|
|
107
|
+
delete transports[sid];
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
// Connect the transport to the MCP server
|
|
111
|
+
await server.connect(transport);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Invalid request - no session ID or not initialization request
|
|
115
|
+
res.status(400).json({
|
|
116
|
+
jsonrpc: '2.0',
|
|
117
|
+
error: {
|
|
118
|
+
code: -32000,
|
|
119
|
+
message: 'Bad Request: No valid session ID provided',
|
|
120
|
+
},
|
|
121
|
+
id: null,
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// Handle the request with the transport
|
|
126
|
+
await transport.handleRequest(req, res, req.body);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
console.error('Error handling MCP request:', error);
|
|
130
|
+
if (!res.headersSent) {
|
|
131
|
+
res.status(500).json({
|
|
132
|
+
jsonrpc: '2.0',
|
|
133
|
+
error: {
|
|
134
|
+
code: -32603,
|
|
135
|
+
message: 'Internal server error',
|
|
136
|
+
},
|
|
137
|
+
id: null,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
//=============================================================================
|
|
143
|
+
// DEPRECATED HTTP+SSE TRANSPORT (PROTOCOL VERSION 2024-11-05)
|
|
144
|
+
//=============================================================================
|
|
145
|
+
app.get('/sse', async (req, res) => {
|
|
146
|
+
console.log('Received GET request to /sse (deprecated SSE transport)');
|
|
147
|
+
const transport = new SSEServerTransport('/messages', res);
|
|
148
|
+
transports[transport.sessionId] = transport;
|
|
149
|
+
res.on("close", () => {
|
|
150
|
+
delete transports[transport.sessionId];
|
|
151
|
+
});
|
|
152
|
+
await server.connect(transport);
|
|
153
|
+
});
|
|
154
|
+
app.post("/messages", async (req, res) => {
|
|
155
|
+
const sessionId = req.query.sessionId;
|
|
156
|
+
let transport;
|
|
157
|
+
const existingTransport = transports[sessionId];
|
|
158
|
+
if (existingTransport instanceof SSEServerTransport) {
|
|
159
|
+
// Reuse existing transport
|
|
160
|
+
transport = existingTransport;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// Transport exists but is not a SSEServerTransport (could be StreamableHTTPServerTransport)
|
|
164
|
+
res.status(400).json({
|
|
165
|
+
jsonrpc: '2.0',
|
|
166
|
+
error: {
|
|
167
|
+
code: -32000,
|
|
168
|
+
message: 'Bad Request: Session exists but uses a different transport protocol',
|
|
169
|
+
},
|
|
170
|
+
id: null,
|
|
171
|
+
});
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (transport) {
|
|
175
|
+
await transport.handlePostMessage(req, res);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
res.status(400).send('No transport found for sessionId');
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// Start the server
|
|
182
|
+
const PORT = 3000;
|
|
183
|
+
app.listen(PORT, () => {
|
|
184
|
+
console.log(`Backwards compatible MCP server listening on port ${PORT}`);
|
|
185
|
+
console.log(`
|
|
186
|
+
==============================================
|
|
187
|
+
SUPPORTED TRANSPORT OPTIONS:
|
|
188
|
+
|
|
189
|
+
1. Streamable Http(Protocol version: 2025-03-26)
|
|
190
|
+
Endpoint: /mcp
|
|
191
|
+
Methods: GET, POST, DELETE
|
|
192
|
+
Usage:
|
|
193
|
+
- Initialize with POST to /mcp
|
|
194
|
+
- Establish SSE stream with GET to /mcp
|
|
195
|
+
- Send requests with POST to /mcp
|
|
196
|
+
- Terminate session with DELETE to /mcp
|
|
197
|
+
|
|
198
|
+
2. Http + SSE (Protocol version: 2024-11-05)
|
|
199
|
+
Endpoints: /sse (GET) and /messages (POST)
|
|
200
|
+
Usage:
|
|
201
|
+
- Establish SSE stream with GET to /sse
|
|
202
|
+
- Send requests with POST to /messages?sessionId=<id>
|
|
203
|
+
==============================================
|
|
204
|
+
`);
|
|
205
|
+
});
|
|
206
|
+
// Handle server shutdown
|
|
207
|
+
process.on('SIGINT', async () => {
|
|
208
|
+
console.log('Shutting down server...');
|
|
209
|
+
// Close all active transports to properly clean up resources
|
|
210
|
+
for (const sessionId in transports) {
|
|
211
|
+
try {
|
|
212
|
+
console.log(`Closing transport for session ${sessionId}`);
|
|
213
|
+
await transports[sessionId].close();
|
|
214
|
+
delete transports[sessionId];
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
console.error(`Error closing transport for session ${sessionId}:`, error);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
await server.close();
|
|
221
|
+
console.log('Server shutdown complete');
|
|
222
|
+
process.exit(0);
|
|
223
|
+
});
|
|
224
|
+
//# sourceMappingURL=sseAndStreamableHttpCompatibleServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sseAndStreamableHttpCompatibleServer.js","sourceRoot":"","sources":["../../../../src/examples/server/sseAndStreamableHttpCompatibleServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standaloneSseWithGetStreamableHttp.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/standaloneSseWithGetStreamableHttp.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { McpServer } from '../../server/mcp.js';
|
|
4
|
+
import { StreamableHTTPServerTransport } from '../../server/streamableHttp.js';
|
|
5
|
+
import { isInitializeRequest } from '../../types.js';
|
|
6
|
+
// Create an MCP server with implementation details
|
|
7
|
+
const server = new McpServer({
|
|
8
|
+
name: 'resource-list-changed-notification-server',
|
|
9
|
+
version: '1.0.0',
|
|
10
|
+
});
|
|
11
|
+
// Store transports by session ID to send notifications
|
|
12
|
+
const transports = {};
|
|
13
|
+
const addResource = (name, content) => {
|
|
14
|
+
const uri = `https://mcp-example.com/dynamic/${encodeURIComponent(name)}`;
|
|
15
|
+
server.resource(name, uri, { mimeType: 'text/plain', description: `Dynamic resource: ${name}` }, async () => {
|
|
16
|
+
return {
|
|
17
|
+
contents: [{ uri, text: content }],
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
addResource('example-resource', 'Initial content for example-resource');
|
|
22
|
+
const resourceChangeInterval = setInterval(() => {
|
|
23
|
+
const name = randomUUID();
|
|
24
|
+
addResource(name, `Content for ${name}`);
|
|
25
|
+
}, 5000); // Change resources every 5 seconds for testing
|
|
26
|
+
const app = express();
|
|
27
|
+
app.use(express.json());
|
|
28
|
+
app.post('/mcp', async (req, res) => {
|
|
29
|
+
console.log('Received MCP request:', req.body);
|
|
30
|
+
try {
|
|
31
|
+
// Check for existing session ID
|
|
32
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
33
|
+
let transport;
|
|
34
|
+
if (sessionId && transports[sessionId]) {
|
|
35
|
+
// Reuse existing transport
|
|
36
|
+
transport = transports[sessionId];
|
|
37
|
+
}
|
|
38
|
+
else if (!sessionId && isInitializeRequest(req.body)) {
|
|
39
|
+
// New initialization request
|
|
40
|
+
transport = new StreamableHTTPServerTransport({
|
|
41
|
+
sessionIdGenerator: () => randomUUID(),
|
|
42
|
+
onsessioninitialized: (sessionId) => {
|
|
43
|
+
// Store the transport by session ID when session is initialized
|
|
44
|
+
// This avoids race conditions where requests might come in before the session is stored
|
|
45
|
+
console.log(`Session initialized with ID: ${sessionId}`);
|
|
46
|
+
transports[sessionId] = transport;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
// Connect the transport to the MCP server
|
|
50
|
+
await server.connect(transport);
|
|
51
|
+
// Handle the request - the onsessioninitialized callback will store the transport
|
|
52
|
+
await transport.handleRequest(req, res, req.body);
|
|
53
|
+
return; // Already handled
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Invalid request - no session ID or not initialization request
|
|
57
|
+
res.status(400).json({
|
|
58
|
+
jsonrpc: '2.0',
|
|
59
|
+
error: {
|
|
60
|
+
code: -32000,
|
|
61
|
+
message: 'Bad Request: No valid session ID provided',
|
|
62
|
+
},
|
|
63
|
+
id: null,
|
|
64
|
+
});
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// Handle the request with existing transport
|
|
68
|
+
await transport.handleRequest(req, res, req.body);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error('Error handling MCP request:', error);
|
|
72
|
+
if (!res.headersSent) {
|
|
73
|
+
res.status(500).json({
|
|
74
|
+
jsonrpc: '2.0',
|
|
75
|
+
error: {
|
|
76
|
+
code: -32603,
|
|
77
|
+
message: 'Internal server error',
|
|
78
|
+
},
|
|
79
|
+
id: null,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// Handle GET requests for SSE streams (now using built-in support from StreamableHTTP)
|
|
85
|
+
app.get('/mcp', async (req, res) => {
|
|
86
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
87
|
+
if (!sessionId || !transports[sessionId]) {
|
|
88
|
+
res.status(400).send('Invalid or missing session ID');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
console.log(`Establishing SSE stream for session ${sessionId}`);
|
|
92
|
+
const transport = transports[sessionId];
|
|
93
|
+
await transport.handleRequest(req, res);
|
|
94
|
+
});
|
|
95
|
+
// Start the server
|
|
96
|
+
const PORT = 3000;
|
|
97
|
+
app.listen(PORT, () => {
|
|
98
|
+
console.log(`Server listening on port ${PORT}`);
|
|
99
|
+
});
|
|
100
|
+
// Handle server shutdown
|
|
101
|
+
process.on('SIGINT', async () => {
|
|
102
|
+
console.log('Shutting down server...');
|
|
103
|
+
clearInterval(resourceChangeInterval);
|
|
104
|
+
await server.close();
|
|
105
|
+
process.exit(0);
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=standaloneSseWithGetStreamableHttp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standaloneSseWithGetStreamableHttp.js","sourceRoot":"","sources":["../../../../src/examples/server/standaloneSseWithGetStreamableHttp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { JSONRPCMessage } from '../../types.js';
|
|
2
|
+
import { EventStore } from '../../server/streamableHttp.js';
|
|
3
|
+
/**
|
|
4
|
+
* Simple in-memory implementation of the EventStore interface for resumability
|
|
5
|
+
* This is primarily intended for examples and testing, not for production use
|
|
6
|
+
* where a persistent storage solution would be more appropriate.
|
|
7
|
+
*/
|
|
8
|
+
export declare class InMemoryEventStore implements EventStore {
|
|
9
|
+
private events;
|
|
10
|
+
/**
|
|
11
|
+
* Generates a unique event ID for a given stream ID
|
|
12
|
+
*/
|
|
13
|
+
private generateEventId;
|
|
14
|
+
/**
|
|
15
|
+
* Extracts the stream ID from an event ID
|
|
16
|
+
*/
|
|
17
|
+
private getStreamIdFromEventId;
|
|
18
|
+
/**
|
|
19
|
+
* Stores an event with a generated event ID
|
|
20
|
+
* Implements EventStore.storeEvent
|
|
21
|
+
*/
|
|
22
|
+
storeEvent(streamId: string, message: JSONRPCMessage): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Replays events that occurred after a specific event ID
|
|
25
|
+
* Implements EventStore.replayEventsAfter
|
|
26
|
+
*/
|
|
27
|
+
replayEventsAfter(lastEventId: string, { send }: {
|
|
28
|
+
send: (eventId: string, message: JSONRPCMessage) => Promise<void>;
|
|
29
|
+
}): Promise<string>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=inMemoryEventStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inMemoryEventStore.d.ts","sourceRoot":"","sources":["../../../../src/examples/shared/inMemoryEventStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAE5D;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,MAAM,CAAyE;IAEvF;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAK9B;;;OAGG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAM5E;;;OAGG;IACG,iBAAiB,CAAC,WAAW,EAAE,MAAM,EACzC,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GAC9E,OAAO,CAAC,MAAM,CAAC;CAkCnB"}
|