@modelcontextprotocol/server-everything 2025.5.12 → 2025.7.29

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
@@ -27,24 +27,24 @@ This MCP server attempts to exercise all the features of the MCP protocol. It is
27
27
  - Returns: Completion message with duration and steps
28
28
  - Sends progress notifications during execution
29
29
 
30
- 4. `sampleLLM`
30
+ 4. `printEnv`
31
+ - Prints all environment variables
32
+ - Useful for debugging MCP server configuration
33
+ - No inputs required
34
+ - Returns: JSON string of all environment variables
35
+
36
+ 5. `sampleLLM`
31
37
  - Demonstrates LLM sampling capability using MCP sampling feature
32
38
  - Inputs:
33
39
  - `prompt` (string): The prompt to send to the LLM
34
40
  - `maxTokens` (number, default: 100): Maximum tokens to generate
35
41
  - Returns: Generated LLM response
36
42
 
37
- 5. `getTinyImage`
43
+ 6. `getTinyImage`
38
44
  - Returns a small test image
39
45
  - No inputs required
40
46
  - Returns: Base64 encoded PNG image data
41
47
 
42
- 6. `printEnv`
43
- - Prints all environment variables
44
- - Useful for debugging MCP server configuration
45
- - No inputs required
46
- - Returns: JSON string of all environment variables
47
-
48
48
  7. `annotatedMessage`
49
49
  - Demonstrates how annotations can be used to provide metadata about content
50
50
  - Inputs:
@@ -72,6 +72,23 @@ This MCP server attempts to exercise all the features of the MCP protocol. It is
72
72
  - Embedded resource with `type: "resource"`
73
73
  - Text instruction for using the resource URI
74
74
 
75
+ 9. `startElicitation`
76
+ - Initiates an elicitation (interaction) within the MCP client.
77
+ - Inputs:
78
+ - `color` (string): Favorite color
79
+ - `number` (number, 1-100): Favorite number
80
+ - `pets` (enum): Favorite pet
81
+ - Returns: Confirmation of the elicitation demo with selection summary.
82
+
83
+ 10. `structuredContent`
84
+ - Demonstrates a tool returning structured content using the example in the specification
85
+ - Provides an output schema to allow testing of client SHOULD advisory to validate the result using the schema
86
+ - Inputs:
87
+ - `location` (string): A location or ZIP code, mock data is returned regardless of value
88
+ - Returns: a response with
89
+ - `structuredContent` field conformant to the output schema
90
+ - A backward compatible Text Content field, a SHOULD advisory in the specification
91
+
75
92
  ### Resources
76
93
 
77
94
  The server provides 100 test resources in two formats:
@@ -2,7 +2,14 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
2
  import { CallToolRequestSchema, CompleteRequestSchema, CreateMessageResultSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, SetLevelRequestSchema, SubscribeRequestSchema, ToolSchema, UnsubscribeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
3
3
  import { z } from "zod";
4
4
  import { zodToJsonSchema } from "zod-to-json-schema";
5
+ import { readFileSync } from "fs";
6
+ import { fileURLToPath } from "url";
7
+ import { dirname, join } from "path";
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const instructions = readFileSync(join(__dirname, "instructions.md"), "utf-8");
5
11
  const ToolInputSchema = ToolSchema.shape.inputSchema;
12
+ const ToolOutputSchema = ToolSchema.shape.outputSchema;
6
13
  /* Input schemas for tools implemented in this server */
7
14
  const EchoSchema = z.object({
8
15
  message: z.string().describe("Message to echo"),
@@ -16,7 +23,10 @@ const LongRunningOperationSchema = z.object({
16
23
  .number()
17
24
  .default(10)
18
25
  .describe("Duration of the operation in seconds"),
19
- steps: z.number().default(5).describe("Number of steps in the operation"),
26
+ steps: z
27
+ .number()
28
+ .default(5)
29
+ .describe("Number of steps in the operation"),
20
30
  });
21
31
  const PrintEnvSchema = z.object({});
22
32
  const SampleLLMSchema = z.object({
@@ -26,12 +36,6 @@ const SampleLLMSchema = z.object({
26
36
  .default(100)
27
37
  .describe("Maximum number of tokens to generate"),
28
38
  });
29
- // Example completion values
30
- const EXAMPLE_COMPLETIONS = {
31
- style: ["casual", "formal", "technical", "friendly"],
32
- temperature: ["0", "0.5", "0.7", "1.0"],
33
- resourceId: ["1", "2", "3", "4", "5"],
34
- };
35
39
  const GetTinyImageSchema = z.object({});
36
40
  const AnnotatedMessageSchema = z.object({
37
41
  messageType: z
@@ -49,6 +53,35 @@ const GetResourceReferenceSchema = z.object({
49
53
  .max(100)
50
54
  .describe("ID of the resource to reference (1-100)"),
51
55
  });
56
+ const ElicitationSchema = z.object({});
57
+ const GetResourceLinksSchema = z.object({
58
+ count: z
59
+ .number()
60
+ .min(1)
61
+ .max(10)
62
+ .default(3)
63
+ .describe("Number of resource links to return (1-10)"),
64
+ });
65
+ const StructuredContentSchema = {
66
+ input: z.object({
67
+ location: z
68
+ .string()
69
+ .trim()
70
+ .min(1)
71
+ .describe("City name or zip code"),
72
+ }),
73
+ output: z.object({
74
+ temperature: z
75
+ .number()
76
+ .describe("Temperature in celsius"),
77
+ conditions: z
78
+ .string()
79
+ .describe("Weather conditions description"),
80
+ humidity: z
81
+ .number()
82
+ .describe("Humidity percentage"),
83
+ })
84
+ };
52
85
  var ToolName;
53
86
  (function (ToolName) {
54
87
  ToolName["ECHO"] = "echo";
@@ -59,6 +92,9 @@ var ToolName;
59
92
  ToolName["GET_TINY_IMAGE"] = "getTinyImage";
60
93
  ToolName["ANNOTATED_MESSAGE"] = "annotatedMessage";
61
94
  ToolName["GET_RESOURCE_REFERENCE"] = "getResourceReference";
95
+ ToolName["ELICITATION"] = "startElicitation";
96
+ ToolName["GET_RESOURCE_LINKS"] = "getResourceLinks";
97
+ ToolName["STRUCTURED_CONTENT"] = "structuredContent";
62
98
  })(ToolName || (ToolName = {}));
63
99
  var PromptName;
64
100
  (function (PromptName) {
@@ -66,9 +102,16 @@ var PromptName;
66
102
  PromptName["COMPLEX"] = "complex_prompt";
67
103
  PromptName["RESOURCE"] = "resource_prompt";
68
104
  })(PromptName || (PromptName = {}));
105
+ // Example completion values
106
+ const EXAMPLE_COMPLETIONS = {
107
+ style: ["casual", "formal", "technical", "friendly"],
108
+ temperature: ["0", "0.5", "0.7", "1.0"],
109
+ resourceId: ["1", "2", "3", "4", "5"],
110
+ };
69
111
  export const createServer = () => {
70
112
  const server = new Server({
71
113
  name: "example-servers/everything",
114
+ title: "Everything Example Server",
72
115
  version: "1.0.0",
73
116
  }, {
74
117
  capabilities: {
@@ -77,7 +120,9 @@ export const createServer = () => {
77
120
  tools: {},
78
121
  logging: {},
79
122
  completions: {},
123
+ elicitation: {},
80
124
  },
125
+ instructions
81
126
  });
82
127
  let subscriptions = new Set();
83
128
  let subsUpdateInterval;
@@ -120,9 +165,9 @@ export const createServer = () => {
120
165
  // Set up update interval for stderr messages
121
166
  stdErrUpdateInterval = setInterval(() => {
122
167
  const shortTimestamp = new Date().toLocaleTimeString([], {
123
- hour: '2-digit',
124
- minute: '2-digit',
125
- second: '2-digit'
168
+ hour: "2-digit",
169
+ minute: "2-digit",
170
+ second: "2-digit"
126
171
  });
127
172
  server.notification({
128
173
  method: "notifications/stderr",
@@ -151,6 +196,16 @@ export const createServer = () => {
151
196
  };
152
197
  return await server.request(request, CreateMessageResultSchema);
153
198
  };
199
+ const requestElicitation = async (message, requestedSchema) => {
200
+ const request = {
201
+ method: 'elicitation/create',
202
+ params: {
203
+ message,
204
+ requestedSchema
205
+ }
206
+ };
207
+ return await server.request(request, z.any());
208
+ };
154
209
  const ALL_RESOURCES = Array.from({ length: 100 }, (_, i) => {
155
210
  const uri = `test://static/resource/${i + 1}`;
156
211
  if (i % 2 === 0) {
@@ -347,16 +402,16 @@ export const createServer = () => {
347
402
  description: "Adds two numbers",
348
403
  inputSchema: zodToJsonSchema(AddSchema),
349
404
  },
350
- {
351
- name: ToolName.PRINT_ENV,
352
- description: "Prints all environment variables, helpful for debugging MCP server configuration",
353
- inputSchema: zodToJsonSchema(PrintEnvSchema),
354
- },
355
405
  {
356
406
  name: ToolName.LONG_RUNNING_OPERATION,
357
407
  description: "Demonstrates a long running operation with progress updates",
358
408
  inputSchema: zodToJsonSchema(LongRunningOperationSchema),
359
409
  },
410
+ {
411
+ name: ToolName.PRINT_ENV,
412
+ description: "Prints all environment variables, helpful for debugging MCP server configuration",
413
+ inputSchema: zodToJsonSchema(PrintEnvSchema),
414
+ },
360
415
  {
361
416
  name: ToolName.SAMPLE_LLM,
362
417
  description: "Samples from an LLM using MCP's sampling feature",
@@ -377,6 +432,22 @@ export const createServer = () => {
377
432
  description: "Returns a resource reference that can be used by MCP clients",
378
433
  inputSchema: zodToJsonSchema(GetResourceReferenceSchema),
379
434
  },
435
+ {
436
+ name: ToolName.ELICITATION,
437
+ description: "Demonstrates the Elicitation feature by asking the user to provide information about their favorite color, number, and pets.",
438
+ inputSchema: zodToJsonSchema(ElicitationSchema),
439
+ },
440
+ {
441
+ name: ToolName.GET_RESOURCE_LINKS,
442
+ description: "Returns multiple resource links that reference different types of resources",
443
+ inputSchema: zodToJsonSchema(GetResourceLinksSchema),
444
+ },
445
+ {
446
+ name: ToolName.STRUCTURED_CONTENT,
447
+ description: "Returns structured content along with an output schema for client data validation",
448
+ inputSchema: zodToJsonSchema(StructuredContentSchema.input),
449
+ outputSchema: zodToJsonSchema(StructuredContentSchema.output),
450
+ },
380
451
  ];
381
452
  return { tools };
382
453
  });
@@ -467,31 +538,6 @@ export const createServer = () => {
467
538
  ],
468
539
  };
469
540
  }
470
- if (name === ToolName.GET_RESOURCE_REFERENCE) {
471
- const validatedArgs = GetResourceReferenceSchema.parse(args);
472
- const resourceId = validatedArgs.resourceId;
473
- const resourceIndex = resourceId - 1;
474
- if (resourceIndex < 0 || resourceIndex >= ALL_RESOURCES.length) {
475
- throw new Error(`Resource with ID ${resourceId} does not exist`);
476
- }
477
- const resource = ALL_RESOURCES[resourceIndex];
478
- return {
479
- content: [
480
- {
481
- type: "text",
482
- text: `Returning resource reference for Resource ${resourceId}:`,
483
- },
484
- {
485
- type: "resource",
486
- resource: resource,
487
- },
488
- {
489
- type: "text",
490
- text: `You can access this resource using the URI: ${resource.uri}`,
491
- },
492
- ],
493
- };
494
- }
495
541
  if (name === ToolName.ANNOTATED_MESSAGE) {
496
542
  const { messageType, includeImage } = AnnotatedMessageSchema.parse(args);
497
543
  const content = [];
@@ -540,6 +586,119 @@ export const createServer = () => {
540
586
  }
541
587
  return { content };
542
588
  }
589
+ if (name === ToolName.GET_RESOURCE_REFERENCE) {
590
+ const validatedArgs = GetResourceReferenceSchema.parse(args);
591
+ const resourceId = validatedArgs.resourceId;
592
+ const resourceIndex = resourceId - 1;
593
+ if (resourceIndex < 0 || resourceIndex >= ALL_RESOURCES.length) {
594
+ throw new Error(`Resource with ID ${resourceId} does not exist`);
595
+ }
596
+ const resource = ALL_RESOURCES[resourceIndex];
597
+ return {
598
+ content: [
599
+ {
600
+ type: "text",
601
+ text: `Returning resource reference for Resource ${resourceId}:`,
602
+ },
603
+ {
604
+ type: "resource",
605
+ resource: resource,
606
+ },
607
+ {
608
+ type: "text",
609
+ text: `You can access this resource using the URI: ${resource.uri}`,
610
+ },
611
+ ],
612
+ };
613
+ }
614
+ if (name === ToolName.ELICITATION) {
615
+ ElicitationSchema.parse(args);
616
+ const elicitationResult = await requestElicitation('What are your favorite things?', {
617
+ type: 'object',
618
+ properties: {
619
+ color: { type: 'string', description: 'Favorite color' },
620
+ number: { type: 'integer', description: 'Favorite number', minimum: 1, maximum: 100 },
621
+ pets: {
622
+ type: 'string',
623
+ enum: ['cats', 'dogs', 'birds', 'fish', 'reptiles'],
624
+ description: 'Favorite pets'
625
+ },
626
+ }
627
+ });
628
+ // Handle different response actions
629
+ const content = [];
630
+ if (elicitationResult.action === 'accept' && elicitationResult.content) {
631
+ content.push({
632
+ type: "text",
633
+ text: `✅ User provided their favorite things!`,
634
+ });
635
+ // Only access elicitationResult.content when action is accept
636
+ const { color, number, pets } = elicitationResult.content;
637
+ content.push({
638
+ type: "text",
639
+ text: `Their favorites are:\n- Color: ${color || 'not specified'}\n- Number: ${number || 'not specified'}\n- Pets: ${pets || 'not specified'}`,
640
+ });
641
+ }
642
+ else if (elicitationResult.action === 'decline') {
643
+ content.push({
644
+ type: "text",
645
+ text: `❌ User declined to provide their favorite things.`,
646
+ });
647
+ }
648
+ else if (elicitationResult.action === 'cancel') {
649
+ content.push({
650
+ type: "text",
651
+ text: `⚠️ User cancelled the elicitation dialog.`,
652
+ });
653
+ }
654
+ // Include raw result for debugging
655
+ content.push({
656
+ type: "text",
657
+ text: `\nRaw result: ${JSON.stringify(elicitationResult, null, 2)}`,
658
+ });
659
+ return { content };
660
+ }
661
+ if (name === ToolName.GET_RESOURCE_LINKS) {
662
+ const { count } = GetResourceLinksSchema.parse(args);
663
+ const content = [];
664
+ // Add intro text
665
+ content.push({
666
+ type: "text",
667
+ text: `Here are ${count} resource links to resources available in this server (see full output in tool response if your client does not support resource_link yet):`,
668
+ });
669
+ // Return resource links to actual resources from ALL_RESOURCES
670
+ const actualCount = Math.min(count, ALL_RESOURCES.length);
671
+ for (let i = 0; i < actualCount; i++) {
672
+ const resource = ALL_RESOURCES[i];
673
+ content.push({
674
+ type: "resource_link",
675
+ uri: resource.uri,
676
+ name: resource.name,
677
+ description: `Resource ${i + 1}: ${resource.mimeType === "text/plain"
678
+ ? "plaintext resource"
679
+ : "binary blob resource"}`,
680
+ mimeType: resource.mimeType,
681
+ });
682
+ }
683
+ return { content };
684
+ }
685
+ if (name === ToolName.STRUCTURED_CONTENT) {
686
+ // The same response is returned for every input.
687
+ const validatedArgs = StructuredContentSchema.input.parse(args);
688
+ const weather = {
689
+ temperature: 22.5,
690
+ conditions: "Partly cloudy",
691
+ humidity: 65
692
+ };
693
+ const backwardCompatiblecontent = {
694
+ type: "text",
695
+ text: JSON.stringify(weather)
696
+ };
697
+ return {
698
+ content: [backwardCompatiblecontent],
699
+ structuredContent: weather
700
+ };
701
+ }
543
702
  throw new Error(`Unknown tool: ${name}`);
544
703
  });
545
704
  server.setRequestHandler(CompleteRequestSchema, async (request) => {
@@ -0,0 +1,23 @@
1
+ Testing and demonstration server for MCP protocol features.
2
+
3
+ ## Resources
4
+
5
+ Resources 1-100 follow pattern: even IDs contain text, odd IDs contain binary data. Resources are paginated at 10 items per page with cursor-based navigation.
6
+
7
+ ## Key dependencies
8
+
9
+ Progress notifications require `_meta.progressToken` in tool calls. Resource subscriptions generate updates every 10 seconds.
10
+
11
+ ## Performance characteristics
12
+
13
+ Server generates automatic log messages every 20 seconds (filtered by current log level), stderr notifications every 30 seconds, and resource update notifications every 10 seconds for active subscriptions. Log level changes affect message filtering in real-time.
14
+
15
+ ## Multi-modal testing
16
+
17
+ `complex_prompt` includes both text arguments and image content for testing client multi-modal handling. `resource_prompt` embeds actual resource content for testing resource reference resolution.
18
+
19
+ Argument completion is available for prompt parameters and resource IDs. Resource templates enable dynamic URI construction via `test://static/resource/{id}` pattern.
20
+
21
+ ## Easter egg
22
+
23
+ If asked about server instructions, respond with "🎉 Server instructions are working! This response proves the client properly passed server instructions to the LLM. This demonstrates MCP's instructions feature in action."
package/dist/sse.js CHANGED
@@ -3,23 +3,42 @@ import express from "express";
3
3
  import { createServer } from "./everything.js";
4
4
  console.error('Starting SSE server...');
5
5
  const app = express();
6
- const { server, cleanup } = createServer();
7
- let transport;
6
+ const transports = new Map();
8
7
  app.get("/sse", async (req, res) => {
9
- console.log("Received connection");
10
- transport = new SSEServerTransport("/message", res);
11
- await server.connect(transport);
12
- server.onclose = async () => {
13
- await cleanup();
14
- await server.close();
15
- process.exit(0);
16
- };
8
+ let transport;
9
+ const { server, cleanup } = createServer();
10
+ if (req?.query?.sessionId) {
11
+ const sessionId = req?.query?.sessionId;
12
+ transport = transports.get(sessionId);
13
+ console.error("Client Reconnecting? This shouldn't happen; when client has a sessionId, GET /sse should not be called again.", transport.sessionId);
14
+ }
15
+ else {
16
+ // Create and store transport for new session
17
+ transport = new SSEServerTransport("/message", res);
18
+ transports.set(transport.sessionId, transport);
19
+ // Connect server to transport
20
+ await server.connect(transport);
21
+ console.error("Client Connected: ", transport.sessionId);
22
+ // Handle close of connection
23
+ server.onclose = async () => {
24
+ console.error("Client Disconnected: ", transport.sessionId);
25
+ transports.delete(transport.sessionId);
26
+ await cleanup();
27
+ };
28
+ }
17
29
  });
18
30
  app.post("/message", async (req, res) => {
19
- console.log("Received message");
20
- await transport.handlePostMessage(req, res);
31
+ const sessionId = req?.query?.sessionId;
32
+ const transport = transports.get(sessionId);
33
+ if (transport) {
34
+ console.error("Client Message from", sessionId);
35
+ await transport.handlePostMessage(req, res);
36
+ }
37
+ else {
38
+ console.error(`No transport found for sessionId ${sessionId}`);
39
+ }
21
40
  });
22
41
  const PORT = process.env.PORT || 3001;
23
42
  app.listen(PORT, () => {
24
- console.log(`Server is running on port ${PORT}`);
43
+ console.error(`Server is running on port ${PORT}`);
25
44
  });
@@ -5,19 +5,19 @@ import { createServer } from "./everything.js";
5
5
  import { randomUUID } from 'node:crypto';
6
6
  console.error('Starting Streamable HTTP server...');
7
7
  const app = express();
8
- const { server, cleanup } = createServer();
9
- const transports = {};
8
+ const transports = new Map();
10
9
  app.post('/mcp', async (req, res) => {
11
- console.log('Received MCP POST request');
10
+ console.error('Received MCP POST request');
12
11
  try {
13
12
  // Check for existing session ID
14
13
  const sessionId = req.headers['mcp-session-id'];
15
14
  let transport;
16
- if (sessionId && transports[sessionId]) {
15
+ if (sessionId && transports.has(sessionId)) {
17
16
  // Reuse existing transport
18
- transport = transports[sessionId];
17
+ transport = transports.get(sessionId);
19
18
  }
20
19
  else if (!sessionId) {
20
+ const { server, cleanup } = createServer();
21
21
  // New initialization request
22
22
  const eventStore = new InMemoryEventStore();
23
23
  transport = new StreamableHTTPServerTransport({
@@ -26,16 +26,17 @@ app.post('/mcp', async (req, res) => {
26
26
  onsessioninitialized: (sessionId) => {
27
27
  // Store the transport by session ID when session is initialized
28
28
  // This avoids race conditions where requests might come in before the session is stored
29
- console.log(`Session initialized with ID: ${sessionId}`);
30
- transports[sessionId] = transport;
29
+ console.error(`Session initialized with ID: ${sessionId}`);
30
+ transports.set(sessionId, transport);
31
31
  }
32
32
  });
33
33
  // Set up onclose handler to clean up transport when closed
34
- transport.onclose = () => {
34
+ server.onclose = async () => {
35
35
  const sid = transport.sessionId;
36
- if (sid && transports[sid]) {
37
- console.log(`Transport closed for session ${sid}, removing from transports map`);
38
- delete transports[sid];
36
+ if (sid && transports.has(sid)) {
37
+ console.error(`Transport closed for session ${sid}, removing from transports map`);
38
+ transports.delete(sid);
39
+ await cleanup();
39
40
  }
40
41
  };
41
42
  // Connect the transport to the MCP server BEFORE handling the request
@@ -77,9 +78,9 @@ app.post('/mcp', async (req, res) => {
77
78
  });
78
79
  // Handle GET requests for SSE streams (using built-in support from StreamableHTTP)
79
80
  app.get('/mcp', async (req, res) => {
80
- console.log('Received MCP GET request');
81
+ console.error('Received MCP GET request');
81
82
  const sessionId = req.headers['mcp-session-id'];
82
- if (!sessionId || !transports[sessionId]) {
83
+ if (!sessionId || !transports.has(sessionId)) {
83
84
  res.status(400).json({
84
85
  jsonrpc: '2.0',
85
86
  error: {
@@ -93,18 +94,18 @@ app.get('/mcp', async (req, res) => {
93
94
  // Check for Last-Event-ID header for resumability
94
95
  const lastEventId = req.headers['last-event-id'];
95
96
  if (lastEventId) {
96
- console.log(`Client reconnecting with Last-Event-ID: ${lastEventId}`);
97
+ console.error(`Client reconnecting with Last-Event-ID: ${lastEventId}`);
97
98
  }
98
99
  else {
99
- console.log(`Establishing new SSE stream for session ${sessionId}`);
100
+ console.error(`Establishing new SSE stream for session ${sessionId}`);
100
101
  }
101
- const transport = transports[sessionId];
102
+ const transport = transports.get(sessionId);
102
103
  await transport.handleRequest(req, res);
103
104
  });
104
105
  // Handle DELETE requests for session termination (according to MCP spec)
105
106
  app.delete('/mcp', async (req, res) => {
106
107
  const sessionId = req.headers['mcp-session-id'];
107
- if (!sessionId || !transports[sessionId]) {
108
+ if (!sessionId || !transports.has(sessionId)) {
108
109
  res.status(400).json({
109
110
  jsonrpc: '2.0',
110
111
  error: {
@@ -115,9 +116,9 @@ app.delete('/mcp', async (req, res) => {
115
116
  });
116
117
  return;
117
118
  }
118
- console.log(`Received session termination request for session ${sessionId}`);
119
+ console.error(`Received session termination request for session ${sessionId}`);
119
120
  try {
120
- const transport = transports[sessionId];
121
+ const transport = transports.get(sessionId);
121
122
  await transport.handleRequest(req, res);
122
123
  }
123
124
  catch (error) {
@@ -138,24 +139,22 @@ app.delete('/mcp', async (req, res) => {
138
139
  // Start the server
139
140
  const PORT = process.env.PORT || 3001;
140
141
  app.listen(PORT, () => {
141
- console.log(`MCP Streamable HTTP Server listening on port ${PORT}`);
142
+ console.error(`MCP Streamable HTTP Server listening on port ${PORT}`);
142
143
  });
143
144
  // Handle server shutdown
144
145
  process.on('SIGINT', async () => {
145
- console.log('Shutting down server...');
146
+ console.error('Shutting down server...');
146
147
  // Close all active transports to properly clean up resources
147
148
  for (const sessionId in transports) {
148
149
  try {
149
- console.log(`Closing transport for session ${sessionId}`);
150
- await transports[sessionId].close();
151
- delete transports[sessionId];
150
+ console.error(`Closing transport for session ${sessionId}`);
151
+ await transports.get(sessionId).close();
152
+ transports.delete(sessionId);
152
153
  }
153
154
  catch (error) {
154
155
  console.error(`Error closing transport for session ${sessionId}:`, error);
155
156
  }
156
157
  }
157
- await cleanup();
158
- await server.close();
159
- console.log('Server shutdown complete');
158
+ console.error('Server shutdown complete');
160
159
  process.exit(0);
161
160
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelcontextprotocol/server-everything",
3
- "version": "2025.5.12",
3
+ "version": "2025.7.29",
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)",
@@ -14,7 +14,7 @@
14
14
  "dist"
15
15
  ],
16
16
  "scripts": {
17
- "build": "tsc && shx chmod +x dist/*.js",
17
+ "build": "tsc && shx cp instructions.md dist/ && shx chmod +x dist/*.js",
18
18
  "prepare": "npm run build",
19
19
  "watch": "tsc --watch",
20
20
  "start": "node dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "start:streamableHttp": "node dist/streamableHttp.js"
23
23
  },
24
24
  "dependencies": {
25
- "@modelcontextprotocol/sdk": "^1.11.0",
25
+ "@modelcontextprotocol/sdk": "^1.12.0",
26
26
  "express": "^4.21.1",
27
27
  "zod": "^3.23.8",
28
28
  "zod-to-json-schema": "^3.23.5"