@modelcontextprotocol/server-everything 2026.1.14 → 2026.7.4
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 +35 -1
- package/dist/__tests__/prompts.test.js +131 -0
- package/dist/__tests__/registrations.test.js +121 -0
- package/dist/__tests__/resources.test.js +240 -0
- package/dist/__tests__/server.test.js +31 -0
- package/dist/__tests__/tools.test.js +904 -0
- package/dist/docs/features.md +55 -2
- package/dist/docs/structure.md +18 -6
- package/dist/resources/session.js +15 -1
- package/dist/server/index.js +21 -1
- package/dist/server/roots.js +1 -5
- package/dist/tools/echo.js +6 -0
- package/dist/tools/get-annotated-message.js +6 -0
- package/dist/tools/get-env.js +6 -0
- package/dist/tools/get-resource-links.js +6 -0
- package/dist/tools/get-resource-reference.js +6 -0
- package/dist/tools/get-roots-list.js +6 -0
- package/dist/tools/get-structured-content.js +6 -0
- package/dist/tools/get-sum.js +6 -0
- package/dist/tools/get-tiny-image.js +6 -0
- package/dist/tools/gzip-file-as-resource.js +6 -1
- package/dist/tools/index.js +10 -0
- package/dist/tools/simulate-research-query.js +248 -0
- package/dist/tools/toggle-simulated-logging.js +6 -0
- package/dist/tools/toggle-subscriber-updates.js +6 -0
- package/dist/tools/trigger-elicitation-request-async.js +206 -0
- package/dist/tools/trigger-elicitation-request.js +7 -1
- package/dist/tools/trigger-long-running-operation.js +6 -0
- package/dist/tools/trigger-sampling-request-async.js +172 -0
- package/dist/tools/trigger-sampling-request.js +6 -0
- package/dist/tools/trigger-url-elicitation.js +169 -0
- package/dist/transports/streamableHttp.js +23 -2
- package/dist/vitest.config.js +13 -0
- package/package.json +10 -8
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Tool input schema
|
|
3
|
+
const TriggerSamplingRequestAsyncSchema = z.object({
|
|
4
|
+
prompt: z.string().describe("The prompt to send to the LLM"),
|
|
5
|
+
maxTokens: z
|
|
6
|
+
.number()
|
|
7
|
+
.default(100)
|
|
8
|
+
.describe("Maximum number of tokens to generate"),
|
|
9
|
+
});
|
|
10
|
+
// Tool configuration
|
|
11
|
+
const name = "trigger-sampling-request-async";
|
|
12
|
+
const config = {
|
|
13
|
+
title: "Trigger Async Sampling Request Tool",
|
|
14
|
+
description: "Trigger an async sampling request that the CLIENT executes as a background task. " +
|
|
15
|
+
"Demonstrates bidirectional MCP tasks where the server sends a request and the client " +
|
|
16
|
+
"executes it asynchronously, allowing the server to poll for progress and results.",
|
|
17
|
+
inputSchema: TriggerSamplingRequestAsyncSchema,
|
|
18
|
+
annotations: {
|
|
19
|
+
readOnlyHint: false,
|
|
20
|
+
destructiveHint: false,
|
|
21
|
+
idempotentHint: false,
|
|
22
|
+
openWorldHint: true,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
// Poll interval in milliseconds
|
|
26
|
+
const POLL_INTERVAL = 1000;
|
|
27
|
+
// Maximum poll attempts before timeout
|
|
28
|
+
const MAX_POLL_ATTEMPTS = 60;
|
|
29
|
+
/**
|
|
30
|
+
* Registers the 'trigger-sampling-request-async' tool.
|
|
31
|
+
*
|
|
32
|
+
* This tool demonstrates bidirectional MCP tasks:
|
|
33
|
+
* - Server sends sampling request to client with task metadata
|
|
34
|
+
* - Client creates a task and returns CreateTaskResult
|
|
35
|
+
* - Server polls client's tasks/get endpoint for status
|
|
36
|
+
* - Server fetches final result from client's tasks/result endpoint
|
|
37
|
+
*
|
|
38
|
+
* @param {McpServer} server - The McpServer instance where the tool will be registered.
|
|
39
|
+
*/
|
|
40
|
+
export const registerTriggerSamplingRequestAsyncTool = (server) => {
|
|
41
|
+
// Check client capabilities
|
|
42
|
+
const clientCapabilities = server.server.getClientCapabilities() || {};
|
|
43
|
+
// Client must support sampling AND tasks.requests.sampling
|
|
44
|
+
const clientSupportsSampling = clientCapabilities.sampling !== undefined;
|
|
45
|
+
const clientTasksCapability = clientCapabilities.tasks;
|
|
46
|
+
const clientSupportsAsyncSampling = clientTasksCapability?.requests?.sampling?.createMessage !== undefined;
|
|
47
|
+
if (clientSupportsSampling && clientSupportsAsyncSampling) {
|
|
48
|
+
server.registerTool(name, config, async (args, extra) => {
|
|
49
|
+
const validatedArgs = TriggerSamplingRequestAsyncSchema.parse(args);
|
|
50
|
+
const { prompt, maxTokens } = validatedArgs;
|
|
51
|
+
// Create the sampling request WITH task metadata
|
|
52
|
+
// The params.task field signals to the client that this should be executed as a task
|
|
53
|
+
const request = {
|
|
54
|
+
method: "sampling/createMessage",
|
|
55
|
+
params: {
|
|
56
|
+
task: {
|
|
57
|
+
ttl: 300000, // 5 minutes
|
|
58
|
+
},
|
|
59
|
+
messages: [
|
|
60
|
+
{
|
|
61
|
+
role: "user",
|
|
62
|
+
content: {
|
|
63
|
+
type: "text",
|
|
64
|
+
text: `Resource ${name} context: ${prompt}`,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
systemPrompt: "You are a helpful test server.",
|
|
69
|
+
maxTokens,
|
|
70
|
+
temperature: 0.7,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
// Send the sampling request
|
|
74
|
+
// Client may return either:
|
|
75
|
+
// - CreateMessageResult (synchronous execution)
|
|
76
|
+
// - CreateTaskResult (task-based execution with { task } object)
|
|
77
|
+
const samplingResponse = await extra.sendRequest(request, z.union([
|
|
78
|
+
// CreateTaskResult - client created a task
|
|
79
|
+
z.object({
|
|
80
|
+
task: z.object({
|
|
81
|
+
taskId: z.string(),
|
|
82
|
+
status: z.string(),
|
|
83
|
+
pollInterval: z.number().optional(),
|
|
84
|
+
statusMessage: z.string().optional(),
|
|
85
|
+
}),
|
|
86
|
+
}),
|
|
87
|
+
// CreateMessageResult - synchronous execution
|
|
88
|
+
z.object({
|
|
89
|
+
role: z.string(),
|
|
90
|
+
content: z.any(),
|
|
91
|
+
model: z.string(),
|
|
92
|
+
stopReason: z.string().optional(),
|
|
93
|
+
}),
|
|
94
|
+
]));
|
|
95
|
+
// Check if client returned CreateTaskResult (has task object)
|
|
96
|
+
const isTaskResult = "task" in samplingResponse && samplingResponse.task;
|
|
97
|
+
if (!isTaskResult) {
|
|
98
|
+
// Client executed synchronously - return the direct response
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{
|
|
102
|
+
type: "text",
|
|
103
|
+
text: `[SYNC] Client executed synchronously:\n${JSON.stringify(samplingResponse, null, 2)}`,
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const taskId = samplingResponse.task.taskId;
|
|
109
|
+
const statusMessages = [];
|
|
110
|
+
statusMessages.push(`Task created: ${taskId}`);
|
|
111
|
+
// Poll for task completion
|
|
112
|
+
let attempts = 0;
|
|
113
|
+
let taskStatus = samplingResponse.task.status;
|
|
114
|
+
let taskStatusMessage;
|
|
115
|
+
while (taskStatus !== "completed" &&
|
|
116
|
+
taskStatus !== "failed" &&
|
|
117
|
+
taskStatus !== "cancelled" &&
|
|
118
|
+
attempts < MAX_POLL_ATTEMPTS) {
|
|
119
|
+
// Wait before polling
|
|
120
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
|
|
121
|
+
attempts++;
|
|
122
|
+
// Get task status from client
|
|
123
|
+
const pollResult = await extra.sendRequest({
|
|
124
|
+
method: "tasks/get",
|
|
125
|
+
params: { taskId },
|
|
126
|
+
}, z.looseObject({
|
|
127
|
+
status: z.string(),
|
|
128
|
+
statusMessage: z.string().optional(),
|
|
129
|
+
}));
|
|
130
|
+
taskStatus = pollResult.status;
|
|
131
|
+
taskStatusMessage = pollResult.statusMessage;
|
|
132
|
+
statusMessages.push(`Poll ${attempts}: ${taskStatus}${taskStatusMessage ? ` - ${taskStatusMessage}` : ""}`);
|
|
133
|
+
}
|
|
134
|
+
// Check for timeout
|
|
135
|
+
if (attempts >= MAX_POLL_ATTEMPTS) {
|
|
136
|
+
return {
|
|
137
|
+
content: [
|
|
138
|
+
{
|
|
139
|
+
type: "text",
|
|
140
|
+
text: `[TIMEOUT] Task timed out after ${MAX_POLL_ATTEMPTS} poll attempts\n\nProgress:\n${statusMessages.join("\n")}`,
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// Check for failure/cancellation
|
|
146
|
+
if (taskStatus === "failed" || taskStatus === "cancelled") {
|
|
147
|
+
return {
|
|
148
|
+
content: [
|
|
149
|
+
{
|
|
150
|
+
type: "text",
|
|
151
|
+
text: `[${taskStatus.toUpperCase()}] ${taskStatusMessage || "No message"}\n\nProgress:\n${statusMessages.join("\n")}`,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// Fetch the final result
|
|
157
|
+
const result = await extra.sendRequest({
|
|
158
|
+
method: "tasks/result",
|
|
159
|
+
params: { taskId },
|
|
160
|
+
}, z.any());
|
|
161
|
+
// Return the result with status history
|
|
162
|
+
return {
|
|
163
|
+
content: [
|
|
164
|
+
{
|
|
165
|
+
type: "text",
|
|
166
|
+
text: `[COMPLETED] Async sampling completed!\n\n**Progress:**\n${statusMessages.join("\n")}\n\n**Result:**\n${JSON.stringify(result, null, 2)}`,
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
@@ -14,6 +14,12 @@ const config = {
|
|
|
14
14
|
title: "Trigger Sampling Request Tool",
|
|
15
15
|
description: "Trigger a Request from the Server for LLM Sampling",
|
|
16
16
|
inputSchema: TriggerSamplingRequestSchema,
|
|
17
|
+
annotations: {
|
|
18
|
+
readOnlyHint: false,
|
|
19
|
+
destructiveHint: false,
|
|
20
|
+
idempotentHint: false,
|
|
21
|
+
openWorldHint: true,
|
|
22
|
+
},
|
|
17
23
|
};
|
|
18
24
|
/**
|
|
19
25
|
* Registers the 'trigger-sampling-request' tool.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { ElicitResultSchema, UrlElicitationRequiredError, } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
// Tool input schema
|
|
5
|
+
const TriggerUrlElicitationSchema = z.object({
|
|
6
|
+
url: z.string().url().describe("The URL the user should open"),
|
|
7
|
+
message: z
|
|
8
|
+
.string()
|
|
9
|
+
.default("Please open the link to complete this action.")
|
|
10
|
+
.describe("Message shown to the user before opening the URL"),
|
|
11
|
+
elicitationId: z
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Optional explicit elicitation ID. Defaults to a random UUID."),
|
|
15
|
+
errorPath: z
|
|
16
|
+
.boolean()
|
|
17
|
+
.default(false)
|
|
18
|
+
.describe("Controls which elicitation mechanism is used. " +
|
|
19
|
+
"When false (default), sends an elicitation/create request (request path). " +
|
|
20
|
+
"When true, throws a UrlElicitationRequiredError (MCP error code -32042) so the client handles " +
|
|
21
|
+
"the URL elicitation via the error path rather than waiting for a response. " +
|
|
22
|
+
"To clear the error, satisfy the prerequisite and retry this call with the same arguments; the " +
|
|
23
|
+
"retry ignores errorPath and proceeds, so the client does not loop on the same error."),
|
|
24
|
+
});
|
|
25
|
+
// Tool configuration
|
|
26
|
+
const name = "trigger-url-elicitation";
|
|
27
|
+
const config = {
|
|
28
|
+
title: "Trigger URL Elicitation Tool",
|
|
29
|
+
description: "Trigger a URL elicitation so the client can direct the user to a browser flow. " +
|
|
30
|
+
"Supports two mechanisms: the request path (elicitation/create, default) which awaits the user's " +
|
|
31
|
+
"response, and the error path (UrlElicitationRequiredError, -32042) which signals the client " +
|
|
32
|
+
"to handle URL elicitation via the error response. Set errorPath=true to use the error path.",
|
|
33
|
+
inputSchema: TriggerUrlElicitationSchema,
|
|
34
|
+
annotations: {
|
|
35
|
+
readOnlyHint: false,
|
|
36
|
+
destructiveHint: false,
|
|
37
|
+
idempotentHint: false,
|
|
38
|
+
openWorldHint: true,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Tracks requests for which an error-path prerequisite has already been issued,
|
|
43
|
+
* keyed by the stable inputs a client resends when it retries the original tool
|
|
44
|
+
* call (session + URL + caller-supplied elicitationId).
|
|
45
|
+
*
|
|
46
|
+
* When the client satisfies the prerequisite and retries the same call, the
|
|
47
|
+
* matching entry lets us recognize the retry, ignore `errorPath`, and proceed
|
|
48
|
+
* via the request path instead of re-throwing `UrlElicitationRequiredError` —
|
|
49
|
+
* which would otherwise loop forever (throw -> client satisfies prerequisite ->
|
|
50
|
+
* retry -> throw -> ...).
|
|
51
|
+
*
|
|
52
|
+
* Demo simplification: entries are only removed on a recognized retry, so a
|
|
53
|
+
* client that triggers the error path and never retries leaves its key behind.
|
|
54
|
+
* That is acceptable for this reference server; a production implementation
|
|
55
|
+
* serving many long-lived sessions should evict entries (e.g. a
|
|
56
|
+
* `Map<string, timestamp>` with TTL-based cleanup).
|
|
57
|
+
*/
|
|
58
|
+
const issuedErrorPathElicitations = new Set();
|
|
59
|
+
/**
|
|
60
|
+
* Test-only helper to reset the module-level error-path state between cases.
|
|
61
|
+
* Not part of the tool's public behavior.
|
|
62
|
+
*/
|
|
63
|
+
export const __resetIssuedErrorPathElicitations = () => issuedErrorPathElicitations.clear();
|
|
64
|
+
/**
|
|
65
|
+
* Registers the 'trigger-url-elicitation' tool.
|
|
66
|
+
*
|
|
67
|
+
* This tool only registers when the client advertises URL-mode elicitation
|
|
68
|
+
* capability (clientCapabilities.elicitation.url).
|
|
69
|
+
*
|
|
70
|
+
* Depending on the `errorPath` argument it either:
|
|
71
|
+
* - Sends an `elicitation/create` request and awaits the result (request path), or
|
|
72
|
+
* - Throws a `UrlElicitationRequiredError` (MCP error -32042) carrying a
|
|
73
|
+
* prerequisite elicitation for the client to handle (error path). When the
|
|
74
|
+
* client satisfies the prerequisite and retries the same call, the retry
|
|
75
|
+
* ignores `errorPath` and proceeds via the request path, so the client does
|
|
76
|
+
* not loop on the same error.
|
|
77
|
+
*
|
|
78
|
+
* @param {McpServer} server - The McpServer instance where the tool will be registered.
|
|
79
|
+
*/
|
|
80
|
+
export const registerTriggerUrlElicitationTool = (server) => {
|
|
81
|
+
const clientCapabilities = server.server.getClientCapabilities() || {};
|
|
82
|
+
const clientElicitationCapabilities = clientCapabilities.elicitation;
|
|
83
|
+
const clientSupportsUrlElicitation = clientElicitationCapabilities?.url !== undefined;
|
|
84
|
+
if (clientSupportsUrlElicitation) {
|
|
85
|
+
server.registerTool(name, config, async (args, extra) => {
|
|
86
|
+
const { url, message, elicitationId: requestedElicitationId, errorPath, } = args;
|
|
87
|
+
const elicitationId = requestedElicitationId ?? randomUUID();
|
|
88
|
+
const sessionId = extra.sessionId ?? "default";
|
|
89
|
+
// Key the one-shot error-path marker on inputs the client resends
|
|
90
|
+
// verbatim when it retries the original tool call. A real client retries
|
|
91
|
+
// with the *same* arguments and does NOT echo the prerequisite's
|
|
92
|
+
// (server-generated) elicitationId, so we must key on stable inputs:
|
|
93
|
+
// the session, the requested URL, and the caller-supplied elicitationId
|
|
94
|
+
// (if any). Keying on the resolved/random elicitationId would change on
|
|
95
|
+
// every call and never match, re-throwing the prerequisite forever.
|
|
96
|
+
const errorPathKey = `${sessionId}\u0000${url}\u0000${requestedElicitationId ?? ""}`;
|
|
97
|
+
const elicitationParams = {
|
|
98
|
+
mode: "url",
|
|
99
|
+
url,
|
|
100
|
+
message,
|
|
101
|
+
elicitationId,
|
|
102
|
+
};
|
|
103
|
+
// Error path: signal the client via UrlElicitationRequiredError (-32042)
|
|
104
|
+
// so it handles a prerequisite URL elicitation before this request can
|
|
105
|
+
// proceed. Two things keep the client from looping forever:
|
|
106
|
+
//
|
|
107
|
+
// 1. The prerequisite points at a *different* URL than the one that
|
|
108
|
+
// failed. Reusing the original `url` would make the client complete
|
|
109
|
+
// the prerequisite, retry, and hit the same -32042 error endlessly.
|
|
110
|
+
// 2. We remember that we issued a prerequisite for this request. When
|
|
111
|
+
// the client satisfies it and retries the same call, we recognize
|
|
112
|
+
// the retry, *ignore* errorPath, and fall through to the request
|
|
113
|
+
// path. Without this, the retry would re-enter the error path and
|
|
114
|
+
// re-request the prerequisite URL — another loop.
|
|
115
|
+
if (errorPath) {
|
|
116
|
+
if (issuedErrorPathElicitations.has(errorPathKey)) {
|
|
117
|
+
// Retry of a satisfied prerequisite: clear the one-shot marker and
|
|
118
|
+
// ignore errorPath, falling through to the request path below.
|
|
119
|
+
issuedErrorPathElicitations.delete(errorPathKey);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Originating call: record that we issued a prerequisite for this
|
|
123
|
+
// request, then signal the client via -32042.
|
|
124
|
+
issuedErrorPathElicitations.add(errorPathKey);
|
|
125
|
+
const prerequisiteElicitation = {
|
|
126
|
+
mode: "url",
|
|
127
|
+
url: "https://modelcontextprotocol.io",
|
|
128
|
+
message: "Open this link to satisfy the prerequisite, then retry the request.",
|
|
129
|
+
elicitationId: randomUUID(),
|
|
130
|
+
};
|
|
131
|
+
throw new UrlElicitationRequiredError([prerequisiteElicitation], "This request requires browser-based authorization.");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Request path: send elicitation/create and await the user's response
|
|
135
|
+
const elicitationResult = await extra.sendRequest({
|
|
136
|
+
method: "elicitation/create",
|
|
137
|
+
params: elicitationParams,
|
|
138
|
+
}, ElicitResultSchema, { timeout: 10 * 60 * 1000 /* 10 minutes */ });
|
|
139
|
+
// Handle different response actions
|
|
140
|
+
const content = [];
|
|
141
|
+
if (elicitationResult.action === "accept") {
|
|
142
|
+
content.push({
|
|
143
|
+
type: "text",
|
|
144
|
+
text: `✅ User completed the URL elicitation flow.\n` +
|
|
145
|
+
`Elicitation ID: ${elicitationId}\n` +
|
|
146
|
+
`URL: ${url}`,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else if (elicitationResult.action === "decline") {
|
|
150
|
+
content.push({
|
|
151
|
+
type: "text",
|
|
152
|
+
text: `❌ User declined to open the URL (Elicitation ID: ${elicitationId}).`,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
else if (elicitationResult.action === "cancel") {
|
|
156
|
+
content.push({
|
|
157
|
+
type: "text",
|
|
158
|
+
text: `⚠️ User cancelled the URL elicitation (Elicitation ID: ${elicitationId}).`,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
// Include raw result for debugging
|
|
162
|
+
content.push({
|
|
163
|
+
type: "text",
|
|
164
|
+
text: `\nRaw result: ${JSON.stringify(elicitationResult, null, 2)}`,
|
|
165
|
+
});
|
|
166
|
+
return { content };
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
};
|
|
@@ -1,9 +1,30 @@
|
|
|
1
|
-
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2
|
-
import { InMemoryEventStore } from "@modelcontextprotocol/sdk/examples/shared/inMemoryEventStore.js";
|
|
1
|
+
import { StreamableHTTPServerTransport, } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
3
2
|
import express from "express";
|
|
4
3
|
import { createServer } from "../server/index.js";
|
|
5
4
|
import { randomUUID } from "node:crypto";
|
|
6
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
|
+
}
|
|
7
28
|
console.log("Starting Streamable HTTP server...");
|
|
8
29
|
// Express app with permissive CORS for testing with Inspector direct connect mode
|
|
9
30
|
const app = express();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
export default defineConfig({
|
|
3
|
+
test: {
|
|
4
|
+
globals: true,
|
|
5
|
+
environment: 'node',
|
|
6
|
+
include: ['**/__tests__/**/*.test.ts'],
|
|
7
|
+
coverage: {
|
|
8
|
+
provider: 'v8',
|
|
9
|
+
include: ['**/*.ts'],
|
|
10
|
+
exclude: ['**/__tests__/**', '**/dist/**'],
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
});
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modelcontextprotocol/server-everything",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.7.4",
|
|
4
4
|
"description": "MCP server that exercises all the features of the MCP protocol",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"mcpName": "io.github.modelcontextprotocol/server-everything",
|
|
7
|
-
"author": "
|
|
7
|
+
"author": "Model Context Protocol a Series of LF Projects, LLC.",
|
|
8
8
|
"homepage": "https://modelcontextprotocol.io",
|
|
9
9
|
"bugs": "https://github.com/modelcontextprotocol/servers/issues",
|
|
10
10
|
"repository": {
|
|
@@ -26,21 +26,23 @@
|
|
|
26
26
|
"start:sse": "node dist/index.js sse",
|
|
27
27
|
"start:streamableHttp": "node dist/index.js streamableHttp",
|
|
28
28
|
"prettier:fix": "prettier --write .",
|
|
29
|
-
"prettier:check": "prettier --check ."
|
|
29
|
+
"prettier:check": "prettier --check .",
|
|
30
|
+
"test": "vitest run --coverage"
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
33
34
|
"cors": "^2.8.5",
|
|
34
35
|
"express": "^5.2.1",
|
|
35
36
|
"jszip": "^3.10.1",
|
|
36
|
-
"zod": "^
|
|
37
|
-
"zod-to-json-schema": "^3.23.5"
|
|
37
|
+
"zod": "^4.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/cors": "^2.8.19",
|
|
41
41
|
"@types/express": "^5.0.6",
|
|
42
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
43
|
+
"prettier": "^2.8.8",
|
|
42
44
|
"shx": "^0.3.4",
|
|
43
45
|
"typescript": "^5.6.2",
|
|
44
|
-
"
|
|
46
|
+
"vitest": "^4.1.8"
|
|
45
47
|
}
|
|
46
48
|
}
|