@modelcontextprotocol/server-everything 2025.12.18 → 2026.1.26
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 +9 -158
- package/dist/docs/architecture.md +44 -0
- package/dist/docs/extension.md +23 -0
- package/dist/docs/features.md +103 -0
- package/dist/docs/how-it-works.md +45 -0
- package/dist/docs/instructions.md +28 -0
- package/dist/docs/startup.md +73 -0
- package/dist/docs/structure.md +182 -0
- package/dist/index.js +19 -14
- package/dist/prompts/args.js +34 -0
- package/dist/prompts/completions.js +52 -0
- package/dist/prompts/index.js +15 -0
- package/dist/prompts/resource.js +60 -0
- package/dist/prompts/simple.js +23 -0
- package/dist/resources/files.js +83 -0
- package/dist/resources/index.js +33 -0
- package/dist/resources/session.js +44 -0
- package/dist/resources/subscriptions.js +125 -0
- package/dist/resources/templates.js +171 -0
- package/dist/server/index.js +93 -0
- package/dist/server/logging.js +64 -0
- package/dist/server/roots.js +65 -0
- package/dist/tools/echo.js +29 -0
- package/dist/tools/get-annotated-message.js +81 -0
- package/dist/tools/get-env.js +28 -0
- package/dist/tools/get-resource-links.js +62 -0
- package/dist/tools/get-resource-reference.js +74 -0
- package/dist/tools/get-roots-list.js +71 -0
- package/dist/tools/get-structured-content.js +72 -0
- package/dist/tools/get-sum.js +40 -0
- package/dist/tools/get-tiny-image.js +41 -0
- package/dist/tools/gzip-file-as-resource.js +182 -0
- package/dist/tools/index.js +50 -0
- package/dist/tools/simulate-research-query.js +249 -0
- package/dist/tools/toggle-simulated-logging.js +41 -0
- package/dist/tools/toggle-subscriber-updates.js +44 -0
- package/dist/tools/trigger-elicitation-request-async.js +202 -0
- package/dist/tools/trigger-elicitation-request.js +210 -0
- package/dist/tools/trigger-long-running-operation.js +59 -0
- package/dist/tools/trigger-sampling-request-async.js +168 -0
- package/dist/tools/trigger-sampling-request.js +71 -0
- package/dist/{sse.js → transports/sse.js} +25 -17
- package/dist/transports/stdio.js +27 -0
- package/dist/transports/streamableHttp.js +206 -0
- package/package.json +10 -7
- package/dist/everything.js +0 -978
- package/dist/instructions.md +0 -23
- package/dist/stdio.js +0 -23
- package/dist/streamableHttp.js +0 -174
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { StreamableHTTPServerTransport, } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { createServer } from "../server/index.js";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import cors from "cors";
|
|
6
|
+
// Simple in-memory event store for SSE resumability
|
|
7
|
+
class InMemoryEventStore {
|
|
8
|
+
events = new Map();
|
|
9
|
+
async storeEvent(streamId, message) {
|
|
10
|
+
const eventId = randomUUID();
|
|
11
|
+
this.events.set(eventId, { streamId, message });
|
|
12
|
+
return eventId;
|
|
13
|
+
}
|
|
14
|
+
async replayEventsAfter(lastEventId, { send }) {
|
|
15
|
+
const entries = Array.from(this.events.entries());
|
|
16
|
+
const startIndex = entries.findIndex(([id]) => id === lastEventId);
|
|
17
|
+
if (startIndex === -1)
|
|
18
|
+
return lastEventId;
|
|
19
|
+
let lastId = lastEventId;
|
|
20
|
+
for (let i = startIndex + 1; i < entries.length; i++) {
|
|
21
|
+
const [eventId, { message }] = entries[i];
|
|
22
|
+
await send(eventId, message);
|
|
23
|
+
lastId = eventId;
|
|
24
|
+
}
|
|
25
|
+
return lastId;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
console.log("Starting Streamable HTTP server...");
|
|
29
|
+
// Express app with permissive CORS for testing with Inspector direct connect mode
|
|
30
|
+
const app = express();
|
|
31
|
+
app.use(cors({
|
|
32
|
+
origin: "*", // use "*" with caution in production
|
|
33
|
+
methods: "GET,POST,DELETE",
|
|
34
|
+
preflightContinue: false,
|
|
35
|
+
optionsSuccessStatus: 204,
|
|
36
|
+
exposedHeaders: ["mcp-session-id", "last-event-id", "mcp-protocol-version"],
|
|
37
|
+
}));
|
|
38
|
+
// Map sessionId to server transport for each client
|
|
39
|
+
const transports = new Map();
|
|
40
|
+
// Handle POST requests for client messages
|
|
41
|
+
app.post("/mcp", async (req, res) => {
|
|
42
|
+
console.log("Received MCP POST request");
|
|
43
|
+
try {
|
|
44
|
+
// Check for existing session ID
|
|
45
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
46
|
+
let transport;
|
|
47
|
+
if (sessionId && transports.has(sessionId)) {
|
|
48
|
+
// Reuse existing transport
|
|
49
|
+
transport = transports.get(sessionId);
|
|
50
|
+
}
|
|
51
|
+
else if (!sessionId) {
|
|
52
|
+
const { server, cleanup } = createServer();
|
|
53
|
+
// New initialization request
|
|
54
|
+
const eventStore = new InMemoryEventStore();
|
|
55
|
+
transport = new StreamableHTTPServerTransport({
|
|
56
|
+
sessionIdGenerator: () => randomUUID(),
|
|
57
|
+
eventStore, // Enable resumability
|
|
58
|
+
onsessioninitialized: (sessionId) => {
|
|
59
|
+
// Store the transport by session ID when a session is initialized
|
|
60
|
+
// This avoids race conditions where requests might come in before the session is stored
|
|
61
|
+
console.log(`Session initialized with ID: ${sessionId}`);
|
|
62
|
+
transports.set(sessionId, transport);
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
// Set up onclose handler to clean up transport when closed
|
|
66
|
+
server.server.onclose = async () => {
|
|
67
|
+
const sid = transport.sessionId;
|
|
68
|
+
if (sid && transports.has(sid)) {
|
|
69
|
+
console.log(`Transport closed for session ${sid}, removing from transports map`);
|
|
70
|
+
transports.delete(sid);
|
|
71
|
+
cleanup(sid);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
// Connect the transport to the MCP server BEFORE handling the request
|
|
75
|
+
// so responses can flow back through the same transport
|
|
76
|
+
await server.connect(transport);
|
|
77
|
+
await transport.handleRequest(req, res);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Invalid request - no session ID or not initialization request
|
|
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
|
+
// Handle the request with existing transport - no need to reconnect
|
|
93
|
+
// The existing transport is already connected to the server
|
|
94
|
+
await transport.handleRequest(req, res);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.log("Error handling MCP request:", error);
|
|
98
|
+
if (!res.headersSent) {
|
|
99
|
+
res.status(500).json({
|
|
100
|
+
jsonrpc: "2.0",
|
|
101
|
+
error: {
|
|
102
|
+
code: -32603,
|
|
103
|
+
message: "Internal server error",
|
|
104
|
+
},
|
|
105
|
+
id: req?.body?.id,
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
// Handle GET requests for SSE streams
|
|
112
|
+
app.get("/mcp", async (req, res) => {
|
|
113
|
+
console.log("Received MCP GET request");
|
|
114
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
115
|
+
if (!sessionId || !transports.has(sessionId)) {
|
|
116
|
+
res.status(400).json({
|
|
117
|
+
jsonrpc: "2.0",
|
|
118
|
+
error: {
|
|
119
|
+
code: -32000,
|
|
120
|
+
message: "Bad Request: No valid session ID provided",
|
|
121
|
+
},
|
|
122
|
+
id: req?.body?.id,
|
|
123
|
+
});
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Check for Last-Event-ID header for resumability
|
|
127
|
+
const lastEventId = req.headers["last-event-id"];
|
|
128
|
+
if (lastEventId) {
|
|
129
|
+
console.log(`Client reconnecting with Last-Event-ID: ${lastEventId}`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
console.log(`Establishing new SSE stream for session ${sessionId}`);
|
|
133
|
+
}
|
|
134
|
+
const transport = transports.get(sessionId);
|
|
135
|
+
await transport.handleRequest(req, res);
|
|
136
|
+
});
|
|
137
|
+
// Handle DELETE requests for session termination
|
|
138
|
+
app.delete("/mcp", async (req, res) => {
|
|
139
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
140
|
+
if (!sessionId || !transports.has(sessionId)) {
|
|
141
|
+
res.status(400).json({
|
|
142
|
+
jsonrpc: "2.0",
|
|
143
|
+
error: {
|
|
144
|
+
code: -32000,
|
|
145
|
+
message: "Bad Request: No valid session ID provided",
|
|
146
|
+
},
|
|
147
|
+
id: req?.body?.id,
|
|
148
|
+
});
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
console.log(`Received session termination request for session ${sessionId}`);
|
|
152
|
+
try {
|
|
153
|
+
const transport = transports.get(sessionId);
|
|
154
|
+
await transport.handleRequest(req, res);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
console.log("Error handling session termination:", error);
|
|
158
|
+
if (!res.headersSent) {
|
|
159
|
+
res.status(500).json({
|
|
160
|
+
jsonrpc: "2.0",
|
|
161
|
+
error: {
|
|
162
|
+
code: -32603,
|
|
163
|
+
message: "Error handling session termination",
|
|
164
|
+
},
|
|
165
|
+
id: req?.body?.id,
|
|
166
|
+
});
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
// Start the server
|
|
172
|
+
const PORT = process.env.PORT || 3001;
|
|
173
|
+
const server = app.listen(PORT, () => {
|
|
174
|
+
console.error(`MCP Streamable HTTP Server listening on port ${PORT}`);
|
|
175
|
+
});
|
|
176
|
+
// Handle server errors
|
|
177
|
+
server.on("error", (err) => {
|
|
178
|
+
const code = typeof err === "object" && err !== null && "code" in err
|
|
179
|
+
? err.code
|
|
180
|
+
: undefined;
|
|
181
|
+
if (code === "EADDRINUSE") {
|
|
182
|
+
console.error(`Failed to start: Port ${PORT} is already in use. Set PORT to a free port or stop the conflicting process.`);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
console.error("HTTP server encountered an error while starting:", err);
|
|
186
|
+
}
|
|
187
|
+
// Ensure a non-zero exit so npm reports the failure instead of silently exiting
|
|
188
|
+
process.exit(1);
|
|
189
|
+
});
|
|
190
|
+
// Handle server shutdown
|
|
191
|
+
process.on("SIGINT", async () => {
|
|
192
|
+
console.log("Shutting down server...");
|
|
193
|
+
// Close all active transports to properly clean up resources
|
|
194
|
+
for (const sessionId in transports) {
|
|
195
|
+
try {
|
|
196
|
+
console.log(`Closing transport for session ${sessionId}`);
|
|
197
|
+
await transports.get(sessionId).close();
|
|
198
|
+
transports.delete(sessionId);
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
console.log(`Error closing transport for session ${sessionId}:`, error);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
console.log("Server shutdown complete");
|
|
205
|
+
process.exit(0);
|
|
206
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modelcontextprotocol/server-everything",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2026.1.26",
|
|
4
4
|
"description": "MCP server that exercises all the features of the MCP protocol",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"mcpName": "io.github.modelcontextprotocol/server-everything",
|
|
@@ -19,15 +19,17 @@
|
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"build": "tsc && shx cp
|
|
22
|
+
"build": "tsc && shx cp -r docs dist/ && shx chmod +x dist/*.js",
|
|
23
23
|
"prepare": "npm run build",
|
|
24
24
|
"watch": "tsc --watch",
|
|
25
|
-
"start": "node dist/index.js",
|
|
26
|
-
"start:sse": "node dist/
|
|
27
|
-
"start:streamableHttp": "node dist/
|
|
25
|
+
"start:stdio": "node dist/index.js stdio",
|
|
26
|
+
"start:sse": "node dist/index.js sse",
|
|
27
|
+
"start:streamableHttp": "node dist/index.js streamableHttp",
|
|
28
|
+
"prettier:fix": "prettier --write .",
|
|
29
|
+
"prettier:check": "prettier --check ."
|
|
28
30
|
},
|
|
29
31
|
"dependencies": {
|
|
30
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
31
33
|
"cors": "^2.8.5",
|
|
32
34
|
"express": "^5.2.1",
|
|
33
35
|
"jszip": "^3.10.1",
|
|
@@ -38,6 +40,7 @@
|
|
|
38
40
|
"@types/cors": "^2.8.19",
|
|
39
41
|
"@types/express": "^5.0.6",
|
|
40
42
|
"shx": "^0.3.4",
|
|
41
|
-
"typescript": "^5.6.2"
|
|
43
|
+
"typescript": "^5.6.2",
|
|
44
|
+
"prettier": "^2.8.8"
|
|
42
45
|
}
|
|
43
46
|
}
|