@modelcontextprotocol/server-everything 2025.4.25 → 2025.4.28

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 CHANGED
@@ -126,7 +126,7 @@ The server sends random-leveled log messages every 15 seconds, e.g.:
126
126
  }
127
127
  ```
128
128
 
129
- ## Usage with Claude Desktop
129
+ ## Usage with Claude Desktop (uses [stdio Transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#stdio))
130
130
 
131
131
  Add to your `claude_desktop_config.json`:
132
132
 
@@ -172,3 +172,19 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace
172
172
  }
173
173
  }
174
174
  ```
175
+
176
+ ## Run with [HTTP+SSE Transport](https://modelcontextprotocol.io/specification/2024-11-05/basic/transports#http-with-sse) (deprecated as of [2025-03-26](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports))
177
+
178
+ ```shell
179
+ cd src/everything
180
+ npm install
181
+ npm run start:sse
182
+ ```
183
+
184
+ ## Run with [Streamable HTTP Transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http)
185
+
186
+ ```shell
187
+ cd src/everything
188
+ npm install
189
+ npm run start:streamableHttp
190
+ ```
@@ -0,0 +1,160 @@
1
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
2
+ import { InMemoryEventStore } from '@modelcontextprotocol/sdk/examples/shared/inMemoryEventStore.js';
3
+ import express from "express";
4
+ import { createServer } from "./everything.js";
5
+ import { randomUUID } from 'node:crypto';
6
+ const app = express();
7
+ const { server, cleanup } = createServer();
8
+ const transports = {};
9
+ app.post('/mcp', async (req, res) => {
10
+ console.log('Received MCP POST request');
11
+ try {
12
+ // Check for existing session ID
13
+ const sessionId = req.headers['mcp-session-id'];
14
+ let transport;
15
+ if (sessionId && transports[sessionId]) {
16
+ // Reuse existing transport
17
+ transport = transports[sessionId];
18
+ }
19
+ else if (!sessionId) {
20
+ // New initialization request
21
+ const eventStore = new InMemoryEventStore();
22
+ transport = new StreamableHTTPServerTransport({
23
+ sessionIdGenerator: () => randomUUID(),
24
+ eventStore, // Enable resumability
25
+ onsessioninitialized: (sessionId) => {
26
+ // Store the transport by session ID when session is initialized
27
+ // This avoids race conditions where requests might come in before the session is stored
28
+ console.log(`Session initialized with ID: ${sessionId}`);
29
+ transports[sessionId] = transport;
30
+ }
31
+ });
32
+ // Set up onclose handler to clean up transport when closed
33
+ transport.onclose = () => {
34
+ const sid = transport.sessionId;
35
+ if (sid && transports[sid]) {
36
+ console.log(`Transport closed for session ${sid}, removing from transports map`);
37
+ delete transports[sid];
38
+ }
39
+ };
40
+ // Connect the transport to the MCP server BEFORE handling the request
41
+ // so responses can flow back through the same transport
42
+ await server.connect(transport);
43
+ await transport.handleRequest(req, res);
44
+ return; // Already handled
45
+ }
46
+ else {
47
+ // Invalid request - no session ID or not initialization request
48
+ res.status(400).json({
49
+ jsonrpc: '2.0',
50
+ error: {
51
+ code: -32000,
52
+ message: 'Bad Request: No valid session ID provided',
53
+ },
54
+ id: req?.body?.id,
55
+ });
56
+ return;
57
+ }
58
+ // Handle the request with existing transport - no need to reconnect
59
+ // The existing transport is already connected to the server
60
+ await transport.handleRequest(req, res);
61
+ }
62
+ catch (error) {
63
+ console.error('Error handling MCP request:', error);
64
+ if (!res.headersSent) {
65
+ res.status(500).json({
66
+ jsonrpc: '2.0',
67
+ error: {
68
+ code: -32603,
69
+ message: 'Internal server error',
70
+ },
71
+ id: req?.body?.id,
72
+ });
73
+ return;
74
+ }
75
+ }
76
+ });
77
+ // Handle GET requests for SSE streams (using built-in support from StreamableHTTP)
78
+ app.get('/mcp', async (req, res) => {
79
+ console.log('Received MCP GET request');
80
+ const sessionId = req.headers['mcp-session-id'];
81
+ if (!sessionId || !transports[sessionId]) {
82
+ res.status(400).json({
83
+ jsonrpc: '2.0',
84
+ error: {
85
+ code: -32000,
86
+ message: 'Bad Request: No valid session ID provided',
87
+ },
88
+ id: req?.body?.id,
89
+ });
90
+ return;
91
+ }
92
+ // Check for Last-Event-ID header for resumability
93
+ const lastEventId = req.headers['last-event-id'];
94
+ if (lastEventId) {
95
+ console.log(`Client reconnecting with Last-Event-ID: ${lastEventId}`);
96
+ }
97
+ else {
98
+ console.log(`Establishing new SSE stream for session ${sessionId}`);
99
+ }
100
+ const transport = transports[sessionId];
101
+ await transport.handleRequest(req, res);
102
+ });
103
+ // Handle DELETE requests for session termination (according to MCP spec)
104
+ app.delete('/mcp', async (req, res) => {
105
+ const sessionId = req.headers['mcp-session-id'];
106
+ if (!sessionId || !transports[sessionId]) {
107
+ res.status(400).json({
108
+ jsonrpc: '2.0',
109
+ error: {
110
+ code: -32000,
111
+ message: 'Bad Request: No valid session ID provided',
112
+ },
113
+ id: req?.body?.id,
114
+ });
115
+ return;
116
+ }
117
+ console.log(`Received session termination request for session ${sessionId}`);
118
+ try {
119
+ const transport = transports[sessionId];
120
+ await transport.handleRequest(req, res);
121
+ }
122
+ catch (error) {
123
+ console.error('Error handling session termination:', error);
124
+ if (!res.headersSent) {
125
+ res.status(500).json({
126
+ jsonrpc: '2.0',
127
+ error: {
128
+ code: -32603,
129
+ message: 'Error handling session termination',
130
+ },
131
+ id: req?.body?.id,
132
+ });
133
+ return;
134
+ }
135
+ }
136
+ });
137
+ // Start the server
138
+ const PORT = process.env.PORT || 3001;
139
+ app.listen(PORT, () => {
140
+ console.log(`MCP Streamable HTTP Server listening on port ${PORT}`);
141
+ });
142
+ // Handle server shutdown
143
+ process.on('SIGINT', async () => {
144
+ console.log('Shutting down server...');
145
+ // Close all active transports to properly clean up resources
146
+ for (const sessionId in transports) {
147
+ try {
148
+ console.log(`Closing transport for session ${sessionId}`);
149
+ await transports[sessionId].close();
150
+ delete transports[sessionId];
151
+ }
152
+ catch (error) {
153
+ console.error(`Error closing transport for session ${sessionId}:`, error);
154
+ }
155
+ }
156
+ await cleanup();
157
+ await server.close();
158
+ console.log('Server shutdown complete');
159
+ process.exit(0);
160
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelcontextprotocol/server-everything",
3
- "version": "2025.4.25",
3
+ "version": "2025.4.28",
4
4
  "description": "MCP server that exercises all the features of the MCP protocol",
5
5
  "license": "MIT",
6
6
  "author": "Anthropic, PBC (https://anthropic.com)",
@@ -18,10 +18,11 @@
18
18
  "prepare": "npm run build",
19
19
  "watch": "tsc --watch",
20
20
  "start": "node dist/index.js",
21
- "start:sse": "node dist/sse.js"
21
+ "start:sse": "node dist/sse.js",
22
+ "start:streamableHttp": "node dist/streamableHttp.js"
22
23
  },
23
24
  "dependencies": {
24
- "@modelcontextprotocol/sdk": "^1.9.0",
25
+ "@modelcontextprotocol/sdk": "^1.10.1",
25
26
  "express": "^4.21.1",
26
27
  "zod": "^3.23.8",
27
28
  "zod-to-json-schema": "^3.23.5"