kfc-code-cli 0.0.1-alpha.2 → 0.0.1-alpha.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 +1 -1
- package/dist/main.mjs +3549 -3862
- package/dist/{multipart-parser-CetGDzPt.mjs → multipart-parser-OI2tZKyS.mjs} +1 -1
- package/dist/session-event-bus-Baiz630d.mjs +106 -0
- package/dist/{src-CzEfkVXq.mjs → src-CL9dVeBV.mjs} +2 -2
- package/package.json +4 -2
- package/dist/client-CdbQcqne.mjs +0 -2007
- package/dist/open-KsP3qi4-.mjs +0 -466
- package/dist/stdio-S3GL8wYq.mjs +0 -584
- package/dist/streamableHttp-D_Fc3kFI.mjs +0 -1530
- package/dist/types-CdOcSyeC.mjs +0 -1244
- /package/dist/{dist-CKY8wJId.mjs → dist-CsQLzhCC.mjs} +0 -0
- /package/dist/{from-BNWSEQzV.mjs → from-BG79vaL9.mjs} +0 -0
package/dist/client-CdbQcqne.mjs
DELETED
|
@@ -1,2007 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { a as __toESM, t as __commonJSMin } from "./chunk-pPjepVcp.mjs";
|
|
3
|
-
import { n as require_codegen, t as require_ajv } from "./main.mjs";
|
|
4
|
-
import { A as ProgressNotificationSchema, B as isJSONRPCNotification, C as ListResourceTemplatesResultSchema, D as ListToolsResultSchema, E as ListTasksResultSchema, F as SUPPORTED_PROTOCOL_VERSIONS, H as isJSONRPCResultResponse, I as TaskStatusNotificationSchema, L as ToolListChangedNotificationSchema, M as RELATED_TASK_META_KEY, N as ReadResourceResultSchema, O as McpError, P as ResourceListChangedNotificationSchema, S as ListPromptsResultSchema, T as ListTasksRequestSchema, U as isTaskAugmentedRequestParams, V as isJSONRPCRequest, _ as GetTaskResultSchema, a as CompleteResultSchema, b as LATEST_PROTOCOL_VERSION, c as CreateMessageResultWithToolsSchema, d as ElicitResultSchema, f as EmptyResultSchema, g as GetTaskRequestSchema, h as GetTaskPayloadRequestSchema, i as CancelledNotificationSchema, j as PromptListChangedNotificationSchema, k as PingRequestSchema, l as CreateTaskResultSchema, m as GetPromptResultSchema, n as CancelTaskRequestSchema, o as CreateMessageRequestSchema, p as ErrorCode, r as CancelTaskResultSchema, s as CreateMessageResultSchema, t as CallToolResultSchema, u as ElicitRequestSchema, v as InitializeResultSchema, w as ListResourcesResultSchema, x as ListChangedOptionsBaseSchema, z as isJSONRPCErrorResponse } from "./types-CdOcSyeC.mjs";
|
|
5
|
-
import "zod/v3";
|
|
6
|
-
import * as z4mini from "zod/v4-mini";
|
|
7
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
8
|
-
function isZ4Schema(s) {
|
|
9
|
-
return !!s._zod;
|
|
10
|
-
}
|
|
11
|
-
function safeParse(schema, data) {
|
|
12
|
-
if (isZ4Schema(schema)) return z4mini.safeParse(schema, data);
|
|
13
|
-
return schema.safeParse(data);
|
|
14
|
-
}
|
|
15
|
-
function getObjectShape(schema) {
|
|
16
|
-
if (!schema) return void 0;
|
|
17
|
-
let rawShape;
|
|
18
|
-
if (isZ4Schema(schema)) rawShape = schema._zod?.def?.shape;
|
|
19
|
-
else rawShape = schema.shape;
|
|
20
|
-
if (!rawShape) return void 0;
|
|
21
|
-
if (typeof rawShape === "function") try {
|
|
22
|
-
return rawShape();
|
|
23
|
-
} catch {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
return rawShape;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Gets the literal value from a schema, if it's a literal schema.
|
|
30
|
-
* Works with both Zod v3 and v4.
|
|
31
|
-
* Returns undefined if the schema is not a literal or the value cannot be determined.
|
|
32
|
-
*/
|
|
33
|
-
function getLiteralValue(schema) {
|
|
34
|
-
if (isZ4Schema(schema)) {
|
|
35
|
-
const def = schema._zod?.def;
|
|
36
|
-
if (def) {
|
|
37
|
-
if (def.value !== void 0) return def.value;
|
|
38
|
-
if (Array.isArray(def.values) && def.values.length > 0) return def.values[0];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const def = schema._def;
|
|
42
|
-
if (def) {
|
|
43
|
-
if (def.value !== void 0) return def.value;
|
|
44
|
-
if (Array.isArray(def.values) && def.values.length > 0) return def.values[0];
|
|
45
|
-
}
|
|
46
|
-
const directValue = schema.value;
|
|
47
|
-
if (directValue !== void 0) return directValue;
|
|
48
|
-
}
|
|
49
|
-
//#endregion
|
|
50
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
|
|
51
|
-
/**
|
|
52
|
-
* Experimental task interfaces for MCP SDK.
|
|
53
|
-
* WARNING: These APIs are experimental and may change without notice.
|
|
54
|
-
*/
|
|
55
|
-
/**
|
|
56
|
-
* Checks if a task status represents a terminal state.
|
|
57
|
-
* Terminal states are those where the task has finished and will not change.
|
|
58
|
-
*
|
|
59
|
-
* @param status - The task status to check
|
|
60
|
-
* @returns True if the status is terminal (completed, failed, or cancelled)
|
|
61
|
-
* @experimental
|
|
62
|
-
*/
|
|
63
|
-
function isTerminal(status) {
|
|
64
|
-
return status === "completed" || status === "failed" || status === "cancelled";
|
|
65
|
-
}
|
|
66
|
-
//#endregion
|
|
67
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
|
|
68
|
-
function getMethodLiteral(schema) {
|
|
69
|
-
const methodSchema = getObjectShape(schema)?.method;
|
|
70
|
-
if (!methodSchema) throw new Error("Schema is missing a method literal");
|
|
71
|
-
const value = getLiteralValue(methodSchema);
|
|
72
|
-
if (typeof value !== "string") throw new Error("Schema method literal must be a string");
|
|
73
|
-
return value;
|
|
74
|
-
}
|
|
75
|
-
function parseWithCompat(schema, data) {
|
|
76
|
-
const result = safeParse(schema, data);
|
|
77
|
-
if (!result.success) throw result.error;
|
|
78
|
-
return result.data;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Implements MCP protocol framing on top of a pluggable transport, including
|
|
82
|
-
* features like request/response linking, notifications, and progress.
|
|
83
|
-
*/
|
|
84
|
-
var Protocol = class {
|
|
85
|
-
constructor(_options) {
|
|
86
|
-
this._options = _options;
|
|
87
|
-
this._requestMessageId = 0;
|
|
88
|
-
this._requestHandlers = /* @__PURE__ */ new Map();
|
|
89
|
-
this._requestHandlerAbortControllers = /* @__PURE__ */ new Map();
|
|
90
|
-
this._notificationHandlers = /* @__PURE__ */ new Map();
|
|
91
|
-
this._responseHandlers = /* @__PURE__ */ new Map();
|
|
92
|
-
this._progressHandlers = /* @__PURE__ */ new Map();
|
|
93
|
-
this._timeoutInfo = /* @__PURE__ */ new Map();
|
|
94
|
-
this._pendingDebouncedNotifications = /* @__PURE__ */ new Set();
|
|
95
|
-
this._taskProgressTokens = /* @__PURE__ */ new Map();
|
|
96
|
-
this._requestResolvers = /* @__PURE__ */ new Map();
|
|
97
|
-
this.setNotificationHandler(CancelledNotificationSchema, (notification) => {
|
|
98
|
-
this._oncancel(notification);
|
|
99
|
-
});
|
|
100
|
-
this.setNotificationHandler(ProgressNotificationSchema, (notification) => {
|
|
101
|
-
this._onprogress(notification);
|
|
102
|
-
});
|
|
103
|
-
this.setRequestHandler(PingRequestSchema, (_request) => ({}));
|
|
104
|
-
this._taskStore = _options?.taskStore;
|
|
105
|
-
this._taskMessageQueue = _options?.taskMessageQueue;
|
|
106
|
-
if (this._taskStore) {
|
|
107
|
-
this.setRequestHandler(GetTaskRequestSchema, async (request, extra) => {
|
|
108
|
-
const task = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
109
|
-
if (!task) throw new McpError(ErrorCode.InvalidParams, "Failed to retrieve task: Task not found");
|
|
110
|
-
return { ...task };
|
|
111
|
-
});
|
|
112
|
-
this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
|
|
113
|
-
const handleTaskResult = async () => {
|
|
114
|
-
const taskId = request.params.taskId;
|
|
115
|
-
if (this._taskMessageQueue) {
|
|
116
|
-
let queuedMessage;
|
|
117
|
-
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
118
|
-
if (queuedMessage.type === "response" || queuedMessage.type === "error") {
|
|
119
|
-
const message = queuedMessage.message;
|
|
120
|
-
const requestId = message.id;
|
|
121
|
-
const resolver = this._requestResolvers.get(requestId);
|
|
122
|
-
if (resolver) {
|
|
123
|
-
this._requestResolvers.delete(requestId);
|
|
124
|
-
if (queuedMessage.type === "response") resolver(message);
|
|
125
|
-
else {
|
|
126
|
-
const errorMessage = message;
|
|
127
|
-
resolver(new McpError(errorMessage.error.code, errorMessage.error.message, errorMessage.error.data));
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
const messageType = queuedMessage.type === "response" ? "Response" : "Error";
|
|
131
|
-
this._onerror(/* @__PURE__ */ new Error(`${messageType} handler missing for request ${requestId}`));
|
|
132
|
-
}
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
await this._transport?.send(queuedMessage.message, { relatedRequestId: extra.requestId });
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
const task = await this._taskStore.getTask(taskId, extra.sessionId);
|
|
139
|
-
if (!task) throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
140
|
-
if (!isTerminal(task.status)) {
|
|
141
|
-
await this._waitForTaskUpdate(taskId, extra.signal);
|
|
142
|
-
return await handleTaskResult();
|
|
143
|
-
}
|
|
144
|
-
if (isTerminal(task.status)) {
|
|
145
|
-
const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
|
|
146
|
-
this._clearTaskQueue(taskId);
|
|
147
|
-
return {
|
|
148
|
-
...result,
|
|
149
|
-
_meta: {
|
|
150
|
-
...result._meta,
|
|
151
|
-
[RELATED_TASK_META_KEY]: { taskId }
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
return await handleTaskResult();
|
|
156
|
-
};
|
|
157
|
-
return await handleTaskResult();
|
|
158
|
-
});
|
|
159
|
-
this.setRequestHandler(ListTasksRequestSchema, async (request, extra) => {
|
|
160
|
-
try {
|
|
161
|
-
const { tasks, nextCursor } = await this._taskStore.listTasks(request.params?.cursor, extra.sessionId);
|
|
162
|
-
return {
|
|
163
|
-
tasks,
|
|
164
|
-
nextCursor,
|
|
165
|
-
_meta: {}
|
|
166
|
-
};
|
|
167
|
-
} catch (error) {
|
|
168
|
-
throw new McpError(ErrorCode.InvalidParams, `Failed to list tasks: ${error instanceof Error ? error.message : String(error)}`);
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
this.setRequestHandler(CancelTaskRequestSchema, async (request, extra) => {
|
|
172
|
-
try {
|
|
173
|
-
const task = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
174
|
-
if (!task) throw new McpError(ErrorCode.InvalidParams, `Task not found: ${request.params.taskId}`);
|
|
175
|
-
if (isTerminal(task.status)) throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
|
|
176
|
-
await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
|
|
177
|
-
this._clearTaskQueue(request.params.taskId);
|
|
178
|
-
const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
179
|
-
if (!cancelledTask) throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
|
|
180
|
-
return {
|
|
181
|
-
_meta: {},
|
|
182
|
-
...cancelledTask
|
|
183
|
-
};
|
|
184
|
-
} catch (error) {
|
|
185
|
-
if (error instanceof McpError) throw error;
|
|
186
|
-
throw new McpError(ErrorCode.InvalidRequest, `Failed to cancel task: ${error instanceof Error ? error.message : String(error)}`);
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
async _oncancel(notification) {
|
|
192
|
-
if (!notification.params.requestId) return;
|
|
193
|
-
this._requestHandlerAbortControllers.get(notification.params.requestId)?.abort(notification.params.reason);
|
|
194
|
-
}
|
|
195
|
-
_setupTimeout(messageId, timeout, maxTotalTimeout, onTimeout, resetTimeoutOnProgress = false) {
|
|
196
|
-
this._timeoutInfo.set(messageId, {
|
|
197
|
-
timeoutId: setTimeout(onTimeout, timeout),
|
|
198
|
-
startTime: Date.now(),
|
|
199
|
-
timeout,
|
|
200
|
-
maxTotalTimeout,
|
|
201
|
-
resetTimeoutOnProgress,
|
|
202
|
-
onTimeout
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
_resetTimeout(messageId) {
|
|
206
|
-
const info = this._timeoutInfo.get(messageId);
|
|
207
|
-
if (!info) return false;
|
|
208
|
-
const totalElapsed = Date.now() - info.startTime;
|
|
209
|
-
if (info.maxTotalTimeout && totalElapsed >= info.maxTotalTimeout) {
|
|
210
|
-
this._timeoutInfo.delete(messageId);
|
|
211
|
-
throw McpError.fromError(ErrorCode.RequestTimeout, "Maximum total timeout exceeded", {
|
|
212
|
-
maxTotalTimeout: info.maxTotalTimeout,
|
|
213
|
-
totalElapsed
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
clearTimeout(info.timeoutId);
|
|
217
|
-
info.timeoutId = setTimeout(info.onTimeout, info.timeout);
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
_cleanupTimeout(messageId) {
|
|
221
|
-
const info = this._timeoutInfo.get(messageId);
|
|
222
|
-
if (info) {
|
|
223
|
-
clearTimeout(info.timeoutId);
|
|
224
|
-
this._timeoutInfo.delete(messageId);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Attaches to the given transport, starts it, and starts listening for messages.
|
|
229
|
-
*
|
|
230
|
-
* The Protocol object assumes ownership of the Transport, replacing any callbacks that have already been set, and expects that it is the only user of the Transport instance going forward.
|
|
231
|
-
*/
|
|
232
|
-
async connect(transport) {
|
|
233
|
-
if (this._transport) throw new Error("Already connected to a transport. Call close() before connecting to a new transport, or use a separate Protocol instance per connection.");
|
|
234
|
-
this._transport = transport;
|
|
235
|
-
const _onclose = this.transport?.onclose;
|
|
236
|
-
this._transport.onclose = () => {
|
|
237
|
-
_onclose?.();
|
|
238
|
-
this._onclose();
|
|
239
|
-
};
|
|
240
|
-
const _onerror = this.transport?.onerror;
|
|
241
|
-
this._transport.onerror = (error) => {
|
|
242
|
-
_onerror?.(error);
|
|
243
|
-
this._onerror(error);
|
|
244
|
-
};
|
|
245
|
-
const _onmessage = this._transport?.onmessage;
|
|
246
|
-
this._transport.onmessage = (message, extra) => {
|
|
247
|
-
_onmessage?.(message, extra);
|
|
248
|
-
if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) this._onresponse(message);
|
|
249
|
-
else if (isJSONRPCRequest(message)) this._onrequest(message, extra);
|
|
250
|
-
else if (isJSONRPCNotification(message)) this._onnotification(message);
|
|
251
|
-
else this._onerror(/* @__PURE__ */ new Error(`Unknown message type: ${JSON.stringify(message)}`));
|
|
252
|
-
};
|
|
253
|
-
await this._transport.start();
|
|
254
|
-
}
|
|
255
|
-
_onclose() {
|
|
256
|
-
const responseHandlers = this._responseHandlers;
|
|
257
|
-
this._responseHandlers = /* @__PURE__ */ new Map();
|
|
258
|
-
this._progressHandlers.clear();
|
|
259
|
-
this._taskProgressTokens.clear();
|
|
260
|
-
this._pendingDebouncedNotifications.clear();
|
|
261
|
-
for (const info of this._timeoutInfo.values()) clearTimeout(info.timeoutId);
|
|
262
|
-
this._timeoutInfo.clear();
|
|
263
|
-
for (const controller of this._requestHandlerAbortControllers.values()) controller.abort();
|
|
264
|
-
this._requestHandlerAbortControllers.clear();
|
|
265
|
-
const error = McpError.fromError(ErrorCode.ConnectionClosed, "Connection closed");
|
|
266
|
-
this._transport = void 0;
|
|
267
|
-
this.onclose?.();
|
|
268
|
-
for (const handler of responseHandlers.values()) handler(error);
|
|
269
|
-
}
|
|
270
|
-
_onerror(error) {
|
|
271
|
-
this.onerror?.(error);
|
|
272
|
-
}
|
|
273
|
-
_onnotification(notification) {
|
|
274
|
-
const handler = this._notificationHandlers.get(notification.method) ?? this.fallbackNotificationHandler;
|
|
275
|
-
if (handler === void 0) return;
|
|
276
|
-
Promise.resolve().then(() => handler(notification)).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Uncaught error in notification handler: ${error}`)));
|
|
277
|
-
}
|
|
278
|
-
_onrequest(request, extra) {
|
|
279
|
-
const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
|
|
280
|
-
const capturedTransport = this._transport;
|
|
281
|
-
const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
|
|
282
|
-
if (handler === void 0) {
|
|
283
|
-
const errorResponse = {
|
|
284
|
-
jsonrpc: "2.0",
|
|
285
|
-
id: request.id,
|
|
286
|
-
error: {
|
|
287
|
-
code: ErrorCode.MethodNotFound,
|
|
288
|
-
message: "Method not found"
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
if (relatedTaskId && this._taskMessageQueue) this._enqueueTaskMessage(relatedTaskId, {
|
|
292
|
-
type: "error",
|
|
293
|
-
message: errorResponse,
|
|
294
|
-
timestamp: Date.now()
|
|
295
|
-
}, capturedTransport?.sessionId).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Failed to enqueue error response: ${error}`)));
|
|
296
|
-
else capturedTransport?.send(errorResponse).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Failed to send an error response: ${error}`)));
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
const abortController = new AbortController();
|
|
300
|
-
this._requestHandlerAbortControllers.set(request.id, abortController);
|
|
301
|
-
const taskCreationParams = isTaskAugmentedRequestParams(request.params) ? request.params.task : void 0;
|
|
302
|
-
const taskStore = this._taskStore ? this.requestTaskStore(request, capturedTransport?.sessionId) : void 0;
|
|
303
|
-
const fullExtra = {
|
|
304
|
-
signal: abortController.signal,
|
|
305
|
-
sessionId: capturedTransport?.sessionId,
|
|
306
|
-
_meta: request.params?._meta,
|
|
307
|
-
sendNotification: async (notification) => {
|
|
308
|
-
if (abortController.signal.aborted) return;
|
|
309
|
-
const notificationOptions = { relatedRequestId: request.id };
|
|
310
|
-
if (relatedTaskId) notificationOptions.relatedTask = { taskId: relatedTaskId };
|
|
311
|
-
await this.notification(notification, notificationOptions);
|
|
312
|
-
},
|
|
313
|
-
sendRequest: async (r, resultSchema, options) => {
|
|
314
|
-
if (abortController.signal.aborted) throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
|
|
315
|
-
const requestOptions = {
|
|
316
|
-
...options,
|
|
317
|
-
relatedRequestId: request.id
|
|
318
|
-
};
|
|
319
|
-
if (relatedTaskId && !requestOptions.relatedTask) requestOptions.relatedTask = { taskId: relatedTaskId };
|
|
320
|
-
const effectiveTaskId = requestOptions.relatedTask?.taskId ?? relatedTaskId;
|
|
321
|
-
if (effectiveTaskId && taskStore) await taskStore.updateTaskStatus(effectiveTaskId, "input_required");
|
|
322
|
-
return await this.request(r, resultSchema, requestOptions);
|
|
323
|
-
},
|
|
324
|
-
authInfo: extra?.authInfo,
|
|
325
|
-
requestId: request.id,
|
|
326
|
-
requestInfo: extra?.requestInfo,
|
|
327
|
-
taskId: relatedTaskId,
|
|
328
|
-
taskStore,
|
|
329
|
-
taskRequestedTtl: taskCreationParams?.ttl,
|
|
330
|
-
closeSSEStream: extra?.closeSSEStream,
|
|
331
|
-
closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
|
|
332
|
-
};
|
|
333
|
-
Promise.resolve().then(() => {
|
|
334
|
-
if (taskCreationParams) this.assertTaskHandlerCapability(request.method);
|
|
335
|
-
}).then(() => handler(request, fullExtra)).then(async (result) => {
|
|
336
|
-
if (abortController.signal.aborted) return;
|
|
337
|
-
const response = {
|
|
338
|
-
result,
|
|
339
|
-
jsonrpc: "2.0",
|
|
340
|
-
id: request.id
|
|
341
|
-
};
|
|
342
|
-
if (relatedTaskId && this._taskMessageQueue) await this._enqueueTaskMessage(relatedTaskId, {
|
|
343
|
-
type: "response",
|
|
344
|
-
message: response,
|
|
345
|
-
timestamp: Date.now()
|
|
346
|
-
}, capturedTransport?.sessionId);
|
|
347
|
-
else await capturedTransport?.send(response);
|
|
348
|
-
}, async (error) => {
|
|
349
|
-
if (abortController.signal.aborted) return;
|
|
350
|
-
const errorResponse = {
|
|
351
|
-
jsonrpc: "2.0",
|
|
352
|
-
id: request.id,
|
|
353
|
-
error: {
|
|
354
|
-
code: Number.isSafeInteger(error["code"]) ? error["code"] : ErrorCode.InternalError,
|
|
355
|
-
message: error.message ?? "Internal error",
|
|
356
|
-
...error["data"] !== void 0 && { data: error["data"] }
|
|
357
|
-
}
|
|
358
|
-
};
|
|
359
|
-
if (relatedTaskId && this._taskMessageQueue) await this._enqueueTaskMessage(relatedTaskId, {
|
|
360
|
-
type: "error",
|
|
361
|
-
message: errorResponse,
|
|
362
|
-
timestamp: Date.now()
|
|
363
|
-
}, capturedTransport?.sessionId);
|
|
364
|
-
else await capturedTransport?.send(errorResponse);
|
|
365
|
-
}).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Failed to send response: ${error}`))).finally(() => {
|
|
366
|
-
if (this._requestHandlerAbortControllers.get(request.id) === abortController) this._requestHandlerAbortControllers.delete(request.id);
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
_onprogress(notification) {
|
|
370
|
-
const { progressToken, ...params } = notification.params;
|
|
371
|
-
const messageId = Number(progressToken);
|
|
372
|
-
const handler = this._progressHandlers.get(messageId);
|
|
373
|
-
if (!handler) {
|
|
374
|
-
this._onerror(/* @__PURE__ */ new Error(`Received a progress notification for an unknown token: ${JSON.stringify(notification)}`));
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
const responseHandler = this._responseHandlers.get(messageId);
|
|
378
|
-
const timeoutInfo = this._timeoutInfo.get(messageId);
|
|
379
|
-
if (timeoutInfo && responseHandler && timeoutInfo.resetTimeoutOnProgress) try {
|
|
380
|
-
this._resetTimeout(messageId);
|
|
381
|
-
} catch (error) {
|
|
382
|
-
this._responseHandlers.delete(messageId);
|
|
383
|
-
this._progressHandlers.delete(messageId);
|
|
384
|
-
this._cleanupTimeout(messageId);
|
|
385
|
-
responseHandler(error);
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
handler(params);
|
|
389
|
-
}
|
|
390
|
-
_onresponse(response) {
|
|
391
|
-
const messageId = Number(response.id);
|
|
392
|
-
const resolver = this._requestResolvers.get(messageId);
|
|
393
|
-
if (resolver) {
|
|
394
|
-
this._requestResolvers.delete(messageId);
|
|
395
|
-
if (isJSONRPCResultResponse(response)) resolver(response);
|
|
396
|
-
else resolver(new McpError(response.error.code, response.error.message, response.error.data));
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
const handler = this._responseHandlers.get(messageId);
|
|
400
|
-
if (handler === void 0) {
|
|
401
|
-
this._onerror(/* @__PURE__ */ new Error(`Received a response for an unknown message ID: ${JSON.stringify(response)}`));
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
this._responseHandlers.delete(messageId);
|
|
405
|
-
this._cleanupTimeout(messageId);
|
|
406
|
-
let isTaskResponse = false;
|
|
407
|
-
if (isJSONRPCResultResponse(response) && response.result && typeof response.result === "object") {
|
|
408
|
-
const result = response.result;
|
|
409
|
-
if (result.task && typeof result.task === "object") {
|
|
410
|
-
const task = result.task;
|
|
411
|
-
if (typeof task.taskId === "string") {
|
|
412
|
-
isTaskResponse = true;
|
|
413
|
-
this._taskProgressTokens.set(task.taskId, messageId);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
if (!isTaskResponse) this._progressHandlers.delete(messageId);
|
|
418
|
-
if (isJSONRPCResultResponse(response)) handler(response);
|
|
419
|
-
else handler(McpError.fromError(response.error.code, response.error.message, response.error.data));
|
|
420
|
-
}
|
|
421
|
-
get transport() {
|
|
422
|
-
return this._transport;
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* Closes the connection.
|
|
426
|
-
*/
|
|
427
|
-
async close() {
|
|
428
|
-
await this._transport?.close();
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Sends a request and returns an AsyncGenerator that yields response messages.
|
|
432
|
-
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
433
|
-
*
|
|
434
|
-
* @example
|
|
435
|
-
* ```typescript
|
|
436
|
-
* const stream = protocol.requestStream(request, resultSchema, options);
|
|
437
|
-
* for await (const message of stream) {
|
|
438
|
-
* switch (message.type) {
|
|
439
|
-
* case 'taskCreated':
|
|
440
|
-
* console.log('Task created:', message.task.taskId);
|
|
441
|
-
* break;
|
|
442
|
-
* case 'taskStatus':
|
|
443
|
-
* console.log('Task status:', message.task.status);
|
|
444
|
-
* break;
|
|
445
|
-
* case 'result':
|
|
446
|
-
* console.log('Final result:', message.result);
|
|
447
|
-
* break;
|
|
448
|
-
* case 'error':
|
|
449
|
-
* console.error('Error:', message.error);
|
|
450
|
-
* break;
|
|
451
|
-
* }
|
|
452
|
-
* }
|
|
453
|
-
* ```
|
|
454
|
-
*
|
|
455
|
-
* @experimental Use `client.experimental.tasks.requestStream()` to access this method.
|
|
456
|
-
*/
|
|
457
|
-
async *requestStream(request, resultSchema, options) {
|
|
458
|
-
const { task } = options ?? {};
|
|
459
|
-
if (!task) {
|
|
460
|
-
try {
|
|
461
|
-
yield {
|
|
462
|
-
type: "result",
|
|
463
|
-
result: await this.request(request, resultSchema, options)
|
|
464
|
-
};
|
|
465
|
-
} catch (error) {
|
|
466
|
-
yield {
|
|
467
|
-
type: "error",
|
|
468
|
-
error: error instanceof McpError ? error : new McpError(ErrorCode.InternalError, String(error))
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
let taskId;
|
|
474
|
-
try {
|
|
475
|
-
const createResult = await this.request(request, CreateTaskResultSchema, options);
|
|
476
|
-
if (createResult.task) {
|
|
477
|
-
taskId = createResult.task.taskId;
|
|
478
|
-
yield {
|
|
479
|
-
type: "taskCreated",
|
|
480
|
-
task: createResult.task
|
|
481
|
-
};
|
|
482
|
-
} else throw new McpError(ErrorCode.InternalError, "Task creation did not return a task");
|
|
483
|
-
while (true) {
|
|
484
|
-
const task = await this.getTask({ taskId }, options);
|
|
485
|
-
yield {
|
|
486
|
-
type: "taskStatus",
|
|
487
|
-
task
|
|
488
|
-
};
|
|
489
|
-
if (isTerminal(task.status)) {
|
|
490
|
-
if (task.status === "completed") yield {
|
|
491
|
-
type: "result",
|
|
492
|
-
result: await this.getTaskResult({ taskId }, resultSchema, options)
|
|
493
|
-
};
|
|
494
|
-
else if (task.status === "failed") yield {
|
|
495
|
-
type: "error",
|
|
496
|
-
error: new McpError(ErrorCode.InternalError, `Task ${taskId} failed`)
|
|
497
|
-
};
|
|
498
|
-
else if (task.status === "cancelled") yield {
|
|
499
|
-
type: "error",
|
|
500
|
-
error: new McpError(ErrorCode.InternalError, `Task ${taskId} was cancelled`)
|
|
501
|
-
};
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
if (task.status === "input_required") {
|
|
505
|
-
yield {
|
|
506
|
-
type: "result",
|
|
507
|
-
result: await this.getTaskResult({ taskId }, resultSchema, options)
|
|
508
|
-
};
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
const pollInterval = task.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
512
|
-
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
513
|
-
options?.signal?.throwIfAborted();
|
|
514
|
-
}
|
|
515
|
-
} catch (error) {
|
|
516
|
-
yield {
|
|
517
|
-
type: "error",
|
|
518
|
-
error: error instanceof McpError ? error : new McpError(ErrorCode.InternalError, String(error))
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* Sends a request and waits for a response.
|
|
524
|
-
*
|
|
525
|
-
* Do not use this method to emit notifications! Use notification() instead.
|
|
526
|
-
*/
|
|
527
|
-
request(request, resultSchema, options) {
|
|
528
|
-
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
529
|
-
return new Promise((resolve, reject) => {
|
|
530
|
-
const earlyReject = (error) => {
|
|
531
|
-
reject(error);
|
|
532
|
-
};
|
|
533
|
-
if (!this._transport) {
|
|
534
|
-
earlyReject(/* @__PURE__ */ new Error("Not connected"));
|
|
535
|
-
return;
|
|
536
|
-
}
|
|
537
|
-
if (this._options?.enforceStrictCapabilities === true) try {
|
|
538
|
-
this.assertCapabilityForMethod(request.method);
|
|
539
|
-
if (task) this.assertTaskCapability(request.method);
|
|
540
|
-
} catch (e) {
|
|
541
|
-
earlyReject(e);
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
options?.signal?.throwIfAborted();
|
|
545
|
-
const messageId = this._requestMessageId++;
|
|
546
|
-
const jsonrpcRequest = {
|
|
547
|
-
...request,
|
|
548
|
-
jsonrpc: "2.0",
|
|
549
|
-
id: messageId
|
|
550
|
-
};
|
|
551
|
-
if (options?.onprogress) {
|
|
552
|
-
this._progressHandlers.set(messageId, options.onprogress);
|
|
553
|
-
jsonrpcRequest.params = {
|
|
554
|
-
...request.params,
|
|
555
|
-
_meta: {
|
|
556
|
-
...request.params?._meta || {},
|
|
557
|
-
progressToken: messageId
|
|
558
|
-
}
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
if (task) jsonrpcRequest.params = {
|
|
562
|
-
...jsonrpcRequest.params,
|
|
563
|
-
task
|
|
564
|
-
};
|
|
565
|
-
if (relatedTask) jsonrpcRequest.params = {
|
|
566
|
-
...jsonrpcRequest.params,
|
|
567
|
-
_meta: {
|
|
568
|
-
...jsonrpcRequest.params?._meta || {},
|
|
569
|
-
[RELATED_TASK_META_KEY]: relatedTask
|
|
570
|
-
}
|
|
571
|
-
};
|
|
572
|
-
const cancel = (reason) => {
|
|
573
|
-
this._responseHandlers.delete(messageId);
|
|
574
|
-
this._progressHandlers.delete(messageId);
|
|
575
|
-
this._cleanupTimeout(messageId);
|
|
576
|
-
this._transport?.send({
|
|
577
|
-
jsonrpc: "2.0",
|
|
578
|
-
method: "notifications/cancelled",
|
|
579
|
-
params: {
|
|
580
|
-
requestId: messageId,
|
|
581
|
-
reason: String(reason)
|
|
582
|
-
}
|
|
583
|
-
}, {
|
|
584
|
-
relatedRequestId,
|
|
585
|
-
resumptionToken,
|
|
586
|
-
onresumptiontoken
|
|
587
|
-
}).catch((error) => this._onerror(/* @__PURE__ */ new Error(`Failed to send cancellation: ${error}`)));
|
|
588
|
-
reject(reason instanceof McpError ? reason : new McpError(ErrorCode.RequestTimeout, String(reason)));
|
|
589
|
-
};
|
|
590
|
-
this._responseHandlers.set(messageId, (response) => {
|
|
591
|
-
if (options?.signal?.aborted) return;
|
|
592
|
-
if (response instanceof Error) return reject(response);
|
|
593
|
-
try {
|
|
594
|
-
const parseResult = safeParse(resultSchema, response.result);
|
|
595
|
-
if (!parseResult.success) reject(parseResult.error);
|
|
596
|
-
else resolve(parseResult.data);
|
|
597
|
-
} catch (error) {
|
|
598
|
-
reject(error);
|
|
599
|
-
}
|
|
600
|
-
});
|
|
601
|
-
options?.signal?.addEventListener("abort", () => {
|
|
602
|
-
cancel(options?.signal?.reason);
|
|
603
|
-
});
|
|
604
|
-
const timeout = options?.timeout ?? 6e4;
|
|
605
|
-
const timeoutHandler = () => cancel(McpError.fromError(ErrorCode.RequestTimeout, "Request timed out", { timeout }));
|
|
606
|
-
this._setupTimeout(messageId, timeout, options?.maxTotalTimeout, timeoutHandler, options?.resetTimeoutOnProgress ?? false);
|
|
607
|
-
const relatedTaskId = relatedTask?.taskId;
|
|
608
|
-
if (relatedTaskId) {
|
|
609
|
-
const responseResolver = (response) => {
|
|
610
|
-
const handler = this._responseHandlers.get(messageId);
|
|
611
|
-
if (handler) handler(response);
|
|
612
|
-
else this._onerror(/* @__PURE__ */ new Error(`Response handler missing for side-channeled request ${messageId}`));
|
|
613
|
-
};
|
|
614
|
-
this._requestResolvers.set(messageId, responseResolver);
|
|
615
|
-
this._enqueueTaskMessage(relatedTaskId, {
|
|
616
|
-
type: "request",
|
|
617
|
-
message: jsonrpcRequest,
|
|
618
|
-
timestamp: Date.now()
|
|
619
|
-
}).catch((error) => {
|
|
620
|
-
this._cleanupTimeout(messageId);
|
|
621
|
-
reject(error);
|
|
622
|
-
});
|
|
623
|
-
} else this._transport.send(jsonrpcRequest, {
|
|
624
|
-
relatedRequestId,
|
|
625
|
-
resumptionToken,
|
|
626
|
-
onresumptiontoken
|
|
627
|
-
}).catch((error) => {
|
|
628
|
-
this._cleanupTimeout(messageId);
|
|
629
|
-
reject(error);
|
|
630
|
-
});
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
/**
|
|
634
|
-
* Gets the current status of a task.
|
|
635
|
-
*
|
|
636
|
-
* @experimental Use `client.experimental.tasks.getTask()` to access this method.
|
|
637
|
-
*/
|
|
638
|
-
async getTask(params, options) {
|
|
639
|
-
return this.request({
|
|
640
|
-
method: "tasks/get",
|
|
641
|
-
params
|
|
642
|
-
}, GetTaskResultSchema, options);
|
|
643
|
-
}
|
|
644
|
-
/**
|
|
645
|
-
* Retrieves the result of a completed task.
|
|
646
|
-
*
|
|
647
|
-
* @experimental Use `client.experimental.tasks.getTaskResult()` to access this method.
|
|
648
|
-
*/
|
|
649
|
-
async getTaskResult(params, resultSchema, options) {
|
|
650
|
-
return this.request({
|
|
651
|
-
method: "tasks/result",
|
|
652
|
-
params
|
|
653
|
-
}, resultSchema, options);
|
|
654
|
-
}
|
|
655
|
-
/**
|
|
656
|
-
* Lists tasks, optionally starting from a pagination cursor.
|
|
657
|
-
*
|
|
658
|
-
* @experimental Use `client.experimental.tasks.listTasks()` to access this method.
|
|
659
|
-
*/
|
|
660
|
-
async listTasks(params, options) {
|
|
661
|
-
return this.request({
|
|
662
|
-
method: "tasks/list",
|
|
663
|
-
params
|
|
664
|
-
}, ListTasksResultSchema, options);
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* Cancels a specific task.
|
|
668
|
-
*
|
|
669
|
-
* @experimental Use `client.experimental.tasks.cancelTask()` to access this method.
|
|
670
|
-
*/
|
|
671
|
-
async cancelTask(params, options) {
|
|
672
|
-
return this.request({
|
|
673
|
-
method: "tasks/cancel",
|
|
674
|
-
params
|
|
675
|
-
}, CancelTaskResultSchema, options);
|
|
676
|
-
}
|
|
677
|
-
/**
|
|
678
|
-
* Emits a notification, which is a one-way message that does not expect a response.
|
|
679
|
-
*/
|
|
680
|
-
async notification(notification, options) {
|
|
681
|
-
if (!this._transport) throw new Error("Not connected");
|
|
682
|
-
this.assertNotificationCapability(notification.method);
|
|
683
|
-
const relatedTaskId = options?.relatedTask?.taskId;
|
|
684
|
-
if (relatedTaskId) {
|
|
685
|
-
const jsonrpcNotification = {
|
|
686
|
-
...notification,
|
|
687
|
-
jsonrpc: "2.0",
|
|
688
|
-
params: {
|
|
689
|
-
...notification.params,
|
|
690
|
-
_meta: {
|
|
691
|
-
...notification.params?._meta || {},
|
|
692
|
-
[RELATED_TASK_META_KEY]: options.relatedTask
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
};
|
|
696
|
-
await this._enqueueTaskMessage(relatedTaskId, {
|
|
697
|
-
type: "notification",
|
|
698
|
-
message: jsonrpcNotification,
|
|
699
|
-
timestamp: Date.now()
|
|
700
|
-
});
|
|
701
|
-
return;
|
|
702
|
-
}
|
|
703
|
-
if ((this._options?.debouncedNotificationMethods ?? []).includes(notification.method) && !notification.params && !options?.relatedRequestId && !options?.relatedTask) {
|
|
704
|
-
if (this._pendingDebouncedNotifications.has(notification.method)) return;
|
|
705
|
-
this._pendingDebouncedNotifications.add(notification.method);
|
|
706
|
-
Promise.resolve().then(() => {
|
|
707
|
-
this._pendingDebouncedNotifications.delete(notification.method);
|
|
708
|
-
if (!this._transport) return;
|
|
709
|
-
let jsonrpcNotification = {
|
|
710
|
-
...notification,
|
|
711
|
-
jsonrpc: "2.0"
|
|
712
|
-
};
|
|
713
|
-
if (options?.relatedTask) jsonrpcNotification = {
|
|
714
|
-
...jsonrpcNotification,
|
|
715
|
-
params: {
|
|
716
|
-
...jsonrpcNotification.params,
|
|
717
|
-
_meta: {
|
|
718
|
-
...jsonrpcNotification.params?._meta || {},
|
|
719
|
-
[RELATED_TASK_META_KEY]: options.relatedTask
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
};
|
|
723
|
-
this._transport?.send(jsonrpcNotification, options).catch((error) => this._onerror(error));
|
|
724
|
-
});
|
|
725
|
-
return;
|
|
726
|
-
}
|
|
727
|
-
let jsonrpcNotification = {
|
|
728
|
-
...notification,
|
|
729
|
-
jsonrpc: "2.0"
|
|
730
|
-
};
|
|
731
|
-
if (options?.relatedTask) jsonrpcNotification = {
|
|
732
|
-
...jsonrpcNotification,
|
|
733
|
-
params: {
|
|
734
|
-
...jsonrpcNotification.params,
|
|
735
|
-
_meta: {
|
|
736
|
-
...jsonrpcNotification.params?._meta || {},
|
|
737
|
-
[RELATED_TASK_META_KEY]: options.relatedTask
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
};
|
|
741
|
-
await this._transport.send(jsonrpcNotification, options);
|
|
742
|
-
}
|
|
743
|
-
/**
|
|
744
|
-
* Registers a handler to invoke when this protocol object receives a request with the given method.
|
|
745
|
-
*
|
|
746
|
-
* Note that this will replace any previous request handler for the same method.
|
|
747
|
-
*/
|
|
748
|
-
setRequestHandler(requestSchema, handler) {
|
|
749
|
-
const method = getMethodLiteral(requestSchema);
|
|
750
|
-
this.assertRequestHandlerCapability(method);
|
|
751
|
-
this._requestHandlers.set(method, (request, extra) => {
|
|
752
|
-
const parsed = parseWithCompat(requestSchema, request);
|
|
753
|
-
return Promise.resolve(handler(parsed, extra));
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
/**
|
|
757
|
-
* Removes the request handler for the given method.
|
|
758
|
-
*/
|
|
759
|
-
removeRequestHandler(method) {
|
|
760
|
-
this._requestHandlers.delete(method);
|
|
761
|
-
}
|
|
762
|
-
/**
|
|
763
|
-
* Asserts that a request handler has not already been set for the given method, in preparation for a new one being automatically installed.
|
|
764
|
-
*/
|
|
765
|
-
assertCanSetRequestHandler(method) {
|
|
766
|
-
if (this._requestHandlers.has(method)) throw new Error(`A request handler for ${method} already exists, which would be overridden`);
|
|
767
|
-
}
|
|
768
|
-
/**
|
|
769
|
-
* Registers a handler to invoke when this protocol object receives a notification with the given method.
|
|
770
|
-
*
|
|
771
|
-
* Note that this will replace any previous notification handler for the same method.
|
|
772
|
-
*/
|
|
773
|
-
setNotificationHandler(notificationSchema, handler) {
|
|
774
|
-
const method = getMethodLiteral(notificationSchema);
|
|
775
|
-
this._notificationHandlers.set(method, (notification) => {
|
|
776
|
-
const parsed = parseWithCompat(notificationSchema, notification);
|
|
777
|
-
return Promise.resolve(handler(parsed));
|
|
778
|
-
});
|
|
779
|
-
}
|
|
780
|
-
/**
|
|
781
|
-
* Removes the notification handler for the given method.
|
|
782
|
-
*/
|
|
783
|
-
removeNotificationHandler(method) {
|
|
784
|
-
this._notificationHandlers.delete(method);
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Cleans up the progress handler associated with a task.
|
|
788
|
-
* This should be called when a task reaches a terminal status.
|
|
789
|
-
*/
|
|
790
|
-
_cleanupTaskProgressHandler(taskId) {
|
|
791
|
-
const progressToken = this._taskProgressTokens.get(taskId);
|
|
792
|
-
if (progressToken !== void 0) {
|
|
793
|
-
this._progressHandlers.delete(progressToken);
|
|
794
|
-
this._taskProgressTokens.delete(taskId);
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
/**
|
|
798
|
-
* Enqueues a task-related message for side-channel delivery via tasks/result.
|
|
799
|
-
* @param taskId The task ID to associate the message with
|
|
800
|
-
* @param message The message to enqueue
|
|
801
|
-
* @param sessionId Optional session ID for binding the operation to a specific session
|
|
802
|
-
* @throws Error if taskStore is not configured or if enqueue fails (e.g., queue overflow)
|
|
803
|
-
*
|
|
804
|
-
* Note: If enqueue fails, it's the TaskMessageQueue implementation's responsibility to handle
|
|
805
|
-
* the error appropriately (e.g., by failing the task, logging, etc.). The Protocol layer
|
|
806
|
-
* simply propagates the error.
|
|
807
|
-
*/
|
|
808
|
-
async _enqueueTaskMessage(taskId, message, sessionId) {
|
|
809
|
-
if (!this._taskStore || !this._taskMessageQueue) throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
810
|
-
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
811
|
-
await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
|
|
812
|
-
}
|
|
813
|
-
/**
|
|
814
|
-
* Clears the message queue for a task and rejects any pending request resolvers.
|
|
815
|
-
* @param taskId The task ID whose queue should be cleared
|
|
816
|
-
* @param sessionId Optional session ID for binding the operation to a specific session
|
|
817
|
-
*/
|
|
818
|
-
async _clearTaskQueue(taskId, sessionId) {
|
|
819
|
-
if (this._taskMessageQueue) {
|
|
820
|
-
const messages = await this._taskMessageQueue.dequeueAll(taskId, sessionId);
|
|
821
|
-
for (const message of messages) if (message.type === "request" && isJSONRPCRequest(message.message)) {
|
|
822
|
-
const requestId = message.message.id;
|
|
823
|
-
const resolver = this._requestResolvers.get(requestId);
|
|
824
|
-
if (resolver) {
|
|
825
|
-
resolver(new McpError(ErrorCode.InternalError, "Task cancelled or completed"));
|
|
826
|
-
this._requestResolvers.delete(requestId);
|
|
827
|
-
} else this._onerror(/* @__PURE__ */ new Error(`Resolver missing for request ${requestId} during task ${taskId} cleanup`));
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* Waits for a task update (new messages or status change) with abort signal support.
|
|
833
|
-
* Uses polling to check for updates at the task's configured poll interval.
|
|
834
|
-
* @param taskId The task ID to wait for
|
|
835
|
-
* @param signal Abort signal to cancel the wait
|
|
836
|
-
* @returns Promise that resolves when an update occurs or rejects if aborted
|
|
837
|
-
*/
|
|
838
|
-
async _waitForTaskUpdate(taskId, signal) {
|
|
839
|
-
let interval = this._options?.defaultTaskPollInterval ?? 1e3;
|
|
840
|
-
try {
|
|
841
|
-
const task = await this._taskStore?.getTask(taskId);
|
|
842
|
-
if (task?.pollInterval) interval = task.pollInterval;
|
|
843
|
-
} catch {}
|
|
844
|
-
return new Promise((resolve, reject) => {
|
|
845
|
-
if (signal.aborted) {
|
|
846
|
-
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
849
|
-
const timeoutId = setTimeout(resolve, interval);
|
|
850
|
-
signal.addEventListener("abort", () => {
|
|
851
|
-
clearTimeout(timeoutId);
|
|
852
|
-
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
853
|
-
}, { once: true });
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
requestTaskStore(request, sessionId) {
|
|
857
|
-
const taskStore = this._taskStore;
|
|
858
|
-
if (!taskStore) throw new Error("No task store configured");
|
|
859
|
-
return {
|
|
860
|
-
createTask: async (taskParams) => {
|
|
861
|
-
if (!request) throw new Error("No request provided");
|
|
862
|
-
return await taskStore.createTask(taskParams, request.id, {
|
|
863
|
-
method: request.method,
|
|
864
|
-
params: request.params
|
|
865
|
-
}, sessionId);
|
|
866
|
-
},
|
|
867
|
-
getTask: async (taskId) => {
|
|
868
|
-
const task = await taskStore.getTask(taskId, sessionId);
|
|
869
|
-
if (!task) throw new McpError(ErrorCode.InvalidParams, "Failed to retrieve task: Task not found");
|
|
870
|
-
return task;
|
|
871
|
-
},
|
|
872
|
-
storeTaskResult: async (taskId, status, result) => {
|
|
873
|
-
await taskStore.storeTaskResult(taskId, status, result, sessionId);
|
|
874
|
-
const task = await taskStore.getTask(taskId, sessionId);
|
|
875
|
-
if (task) {
|
|
876
|
-
const notification = TaskStatusNotificationSchema.parse({
|
|
877
|
-
method: "notifications/tasks/status",
|
|
878
|
-
params: task
|
|
879
|
-
});
|
|
880
|
-
await this.notification(notification);
|
|
881
|
-
if (isTerminal(task.status)) this._cleanupTaskProgressHandler(taskId);
|
|
882
|
-
}
|
|
883
|
-
},
|
|
884
|
-
getTaskResult: (taskId) => {
|
|
885
|
-
return taskStore.getTaskResult(taskId, sessionId);
|
|
886
|
-
},
|
|
887
|
-
updateTaskStatus: async (taskId, status, statusMessage) => {
|
|
888
|
-
const task = await taskStore.getTask(taskId, sessionId);
|
|
889
|
-
if (!task) throw new McpError(ErrorCode.InvalidParams, `Task "${taskId}" not found - it may have been cleaned up`);
|
|
890
|
-
if (isTerminal(task.status)) throw new McpError(ErrorCode.InvalidParams, `Cannot update task "${taskId}" from terminal status "${task.status}" to "${status}". Terminal states (completed, failed, cancelled) cannot transition to other states.`);
|
|
891
|
-
await taskStore.updateTaskStatus(taskId, status, statusMessage, sessionId);
|
|
892
|
-
const updatedTask = await taskStore.getTask(taskId, sessionId);
|
|
893
|
-
if (updatedTask) {
|
|
894
|
-
const notification = TaskStatusNotificationSchema.parse({
|
|
895
|
-
method: "notifications/tasks/status",
|
|
896
|
-
params: updatedTask
|
|
897
|
-
});
|
|
898
|
-
await this.notification(notification);
|
|
899
|
-
if (isTerminal(updatedTask.status)) this._cleanupTaskProgressHandler(taskId);
|
|
900
|
-
}
|
|
901
|
-
},
|
|
902
|
-
listTasks: (cursor) => {
|
|
903
|
-
return taskStore.listTasks(cursor, sessionId);
|
|
904
|
-
}
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
};
|
|
908
|
-
function isPlainObject(value) {
|
|
909
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
910
|
-
}
|
|
911
|
-
function mergeCapabilities(base, additional) {
|
|
912
|
-
const result = { ...base };
|
|
913
|
-
for (const key in additional) {
|
|
914
|
-
const k = key;
|
|
915
|
-
const addValue = additional[k];
|
|
916
|
-
if (addValue === void 0) continue;
|
|
917
|
-
const baseValue = result[k];
|
|
918
|
-
if (isPlainObject(baseValue) && isPlainObject(addValue)) result[k] = {
|
|
919
|
-
...baseValue,
|
|
920
|
-
...addValue
|
|
921
|
-
};
|
|
922
|
-
else result[k] = addValue;
|
|
923
|
-
}
|
|
924
|
-
return result;
|
|
925
|
-
}
|
|
926
|
-
//#endregion
|
|
927
|
-
//#region ../../node_modules/.pnpm/ajv-formats@3.0.1_ajv@8.18.0/node_modules/ajv-formats/dist/formats.js
|
|
928
|
-
var require_formats = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
929
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
930
|
-
exports.formatNames = exports.fastFormats = exports.fullFormats = void 0;
|
|
931
|
-
function fmtDef(validate, compare) {
|
|
932
|
-
return {
|
|
933
|
-
validate,
|
|
934
|
-
compare
|
|
935
|
-
};
|
|
936
|
-
}
|
|
937
|
-
exports.fullFormats = {
|
|
938
|
-
date: fmtDef(date, compareDate),
|
|
939
|
-
time: fmtDef(getTime(true), compareTime),
|
|
940
|
-
"date-time": fmtDef(getDateTime(true), compareDateTime),
|
|
941
|
-
"iso-time": fmtDef(getTime(), compareIsoTime),
|
|
942
|
-
"iso-date-time": fmtDef(getDateTime(), compareIsoDateTime),
|
|
943
|
-
duration: /^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?|(\d+W)?)$/,
|
|
944
|
-
uri,
|
|
945
|
-
"uri-reference": /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i,
|
|
946
|
-
"uri-template": /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i,
|
|
947
|
-
url: /^(?:https?|ftp):\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)(?:\.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu,
|
|
948
|
-
email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
|
|
949
|
-
hostname: /^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i,
|
|
950
|
-
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/,
|
|
951
|
-
ipv6: /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i,
|
|
952
|
-
regex,
|
|
953
|
-
uuid: /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,
|
|
954
|
-
"json-pointer": /^(?:\/(?:[^~/]|~0|~1)*)*$/,
|
|
955
|
-
"json-pointer-uri-fragment": /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i,
|
|
956
|
-
"relative-json-pointer": /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/,
|
|
957
|
-
byte,
|
|
958
|
-
int32: {
|
|
959
|
-
type: "number",
|
|
960
|
-
validate: validateInt32
|
|
961
|
-
},
|
|
962
|
-
int64: {
|
|
963
|
-
type: "number",
|
|
964
|
-
validate: validateInt64
|
|
965
|
-
},
|
|
966
|
-
float: {
|
|
967
|
-
type: "number",
|
|
968
|
-
validate: validateNumber
|
|
969
|
-
},
|
|
970
|
-
double: {
|
|
971
|
-
type: "number",
|
|
972
|
-
validate: validateNumber
|
|
973
|
-
},
|
|
974
|
-
password: true,
|
|
975
|
-
binary: true
|
|
976
|
-
};
|
|
977
|
-
exports.fastFormats = {
|
|
978
|
-
...exports.fullFormats,
|
|
979
|
-
date: fmtDef(/^\d\d\d\d-[0-1]\d-[0-3]\d$/, compareDate),
|
|
980
|
-
time: fmtDef(/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i, compareTime),
|
|
981
|
-
"date-time": fmtDef(/^\d\d\d\d-[0-1]\d-[0-3]\dt(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i, compareDateTime),
|
|
982
|
-
"iso-time": fmtDef(/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i, compareIsoTime),
|
|
983
|
-
"iso-date-time": fmtDef(/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i, compareIsoDateTime),
|
|
984
|
-
uri: /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/)?[^\s]*$/i,
|
|
985
|
-
"uri-reference": /^(?:(?:[a-z][a-z0-9+\-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,
|
|
986
|
-
email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i
|
|
987
|
-
};
|
|
988
|
-
exports.formatNames = Object.keys(exports.fullFormats);
|
|
989
|
-
function isLeapYear(year) {
|
|
990
|
-
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
991
|
-
}
|
|
992
|
-
const DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
|
993
|
-
const DAYS = [
|
|
994
|
-
0,
|
|
995
|
-
31,
|
|
996
|
-
28,
|
|
997
|
-
31,
|
|
998
|
-
30,
|
|
999
|
-
31,
|
|
1000
|
-
30,
|
|
1001
|
-
31,
|
|
1002
|
-
31,
|
|
1003
|
-
30,
|
|
1004
|
-
31,
|
|
1005
|
-
30,
|
|
1006
|
-
31
|
|
1007
|
-
];
|
|
1008
|
-
function date(str) {
|
|
1009
|
-
const matches = DATE.exec(str);
|
|
1010
|
-
if (!matches) return false;
|
|
1011
|
-
const year = +matches[1];
|
|
1012
|
-
const month = +matches[2];
|
|
1013
|
-
const day = +matches[3];
|
|
1014
|
-
return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && isLeapYear(year) ? 29 : DAYS[month]);
|
|
1015
|
-
}
|
|
1016
|
-
function compareDate(d1, d2) {
|
|
1017
|
-
if (!(d1 && d2)) return void 0;
|
|
1018
|
-
if (d1 > d2) return 1;
|
|
1019
|
-
if (d1 < d2) return -1;
|
|
1020
|
-
return 0;
|
|
1021
|
-
}
|
|
1022
|
-
const TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
|
|
1023
|
-
function getTime(strictTimeZone) {
|
|
1024
|
-
return function time(str) {
|
|
1025
|
-
const matches = TIME.exec(str);
|
|
1026
|
-
if (!matches) return false;
|
|
1027
|
-
const hr = +matches[1];
|
|
1028
|
-
const min = +matches[2];
|
|
1029
|
-
const sec = +matches[3];
|
|
1030
|
-
const tz = matches[4];
|
|
1031
|
-
const tzSign = matches[5] === "-" ? -1 : 1;
|
|
1032
|
-
const tzH = +(matches[6] || 0);
|
|
1033
|
-
const tzM = +(matches[7] || 0);
|
|
1034
|
-
if (tzH > 23 || tzM > 59 || strictTimeZone && !tz) return false;
|
|
1035
|
-
if (hr <= 23 && min <= 59 && sec < 60) return true;
|
|
1036
|
-
const utcMin = min - tzM * tzSign;
|
|
1037
|
-
const utcHr = hr - tzH * tzSign - (utcMin < 0 ? 1 : 0);
|
|
1038
|
-
return (utcHr === 23 || utcHr === -1) && (utcMin === 59 || utcMin === -1) && sec < 61;
|
|
1039
|
-
};
|
|
1040
|
-
}
|
|
1041
|
-
function compareTime(s1, s2) {
|
|
1042
|
-
if (!(s1 && s2)) return void 0;
|
|
1043
|
-
const t1 = (/* @__PURE__ */ new Date("2020-01-01T" + s1)).valueOf();
|
|
1044
|
-
const t2 = (/* @__PURE__ */ new Date("2020-01-01T" + s2)).valueOf();
|
|
1045
|
-
if (!(t1 && t2)) return void 0;
|
|
1046
|
-
return t1 - t2;
|
|
1047
|
-
}
|
|
1048
|
-
function compareIsoTime(t1, t2) {
|
|
1049
|
-
if (!(t1 && t2)) return void 0;
|
|
1050
|
-
const a1 = TIME.exec(t1);
|
|
1051
|
-
const a2 = TIME.exec(t2);
|
|
1052
|
-
if (!(a1 && a2)) return void 0;
|
|
1053
|
-
t1 = a1[1] + a1[2] + a1[3];
|
|
1054
|
-
t2 = a2[1] + a2[2] + a2[3];
|
|
1055
|
-
if (t1 > t2) return 1;
|
|
1056
|
-
if (t1 < t2) return -1;
|
|
1057
|
-
return 0;
|
|
1058
|
-
}
|
|
1059
|
-
const DATE_TIME_SEPARATOR = /t|\s/i;
|
|
1060
|
-
function getDateTime(strictTimeZone) {
|
|
1061
|
-
const time = getTime(strictTimeZone);
|
|
1062
|
-
return function date_time(str) {
|
|
1063
|
-
const dateTime = str.split(DATE_TIME_SEPARATOR);
|
|
1064
|
-
return dateTime.length === 2 && date(dateTime[0]) && time(dateTime[1]);
|
|
1065
|
-
};
|
|
1066
|
-
}
|
|
1067
|
-
function compareDateTime(dt1, dt2) {
|
|
1068
|
-
if (!(dt1 && dt2)) return void 0;
|
|
1069
|
-
const d1 = new Date(dt1).valueOf();
|
|
1070
|
-
const d2 = new Date(dt2).valueOf();
|
|
1071
|
-
if (!(d1 && d2)) return void 0;
|
|
1072
|
-
return d1 - d2;
|
|
1073
|
-
}
|
|
1074
|
-
function compareIsoDateTime(dt1, dt2) {
|
|
1075
|
-
if (!(dt1 && dt2)) return void 0;
|
|
1076
|
-
const [d1, t1] = dt1.split(DATE_TIME_SEPARATOR);
|
|
1077
|
-
const [d2, t2] = dt2.split(DATE_TIME_SEPARATOR);
|
|
1078
|
-
const res = compareDate(d1, d2);
|
|
1079
|
-
if (res === void 0) return void 0;
|
|
1080
|
-
return res || compareTime(t1, t2);
|
|
1081
|
-
}
|
|
1082
|
-
const NOT_URI_FRAGMENT = /\/|:/;
|
|
1083
|
-
const URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
|
|
1084
|
-
function uri(str) {
|
|
1085
|
-
return NOT_URI_FRAGMENT.test(str) && URI.test(str);
|
|
1086
|
-
}
|
|
1087
|
-
const BYTE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gm;
|
|
1088
|
-
function byte(str) {
|
|
1089
|
-
BYTE.lastIndex = 0;
|
|
1090
|
-
return BYTE.test(str);
|
|
1091
|
-
}
|
|
1092
|
-
const MIN_INT32 = -(2 ** 31);
|
|
1093
|
-
const MAX_INT32 = 2 ** 31 - 1;
|
|
1094
|
-
function validateInt32(value) {
|
|
1095
|
-
return Number.isInteger(value) && value <= MAX_INT32 && value >= MIN_INT32;
|
|
1096
|
-
}
|
|
1097
|
-
function validateInt64(value) {
|
|
1098
|
-
return Number.isInteger(value);
|
|
1099
|
-
}
|
|
1100
|
-
function validateNumber() {
|
|
1101
|
-
return true;
|
|
1102
|
-
}
|
|
1103
|
-
const Z_ANCHOR = /[^\\]\\Z/;
|
|
1104
|
-
function regex(str) {
|
|
1105
|
-
if (Z_ANCHOR.test(str)) return false;
|
|
1106
|
-
try {
|
|
1107
|
-
new RegExp(str);
|
|
1108
|
-
return true;
|
|
1109
|
-
} catch (e) {
|
|
1110
|
-
return false;
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
}));
|
|
1114
|
-
//#endregion
|
|
1115
|
-
//#region ../../node_modules/.pnpm/ajv-formats@3.0.1_ajv@8.18.0/node_modules/ajv-formats/dist/limit.js
|
|
1116
|
-
var require_limit = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
1117
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1118
|
-
exports.formatLimitDefinition = void 0;
|
|
1119
|
-
const ajv_1 = require_ajv();
|
|
1120
|
-
const codegen_1 = require_codegen();
|
|
1121
|
-
const ops = codegen_1.operators;
|
|
1122
|
-
const KWDs = {
|
|
1123
|
-
formatMaximum: {
|
|
1124
|
-
okStr: "<=",
|
|
1125
|
-
ok: ops.LTE,
|
|
1126
|
-
fail: ops.GT
|
|
1127
|
-
},
|
|
1128
|
-
formatMinimum: {
|
|
1129
|
-
okStr: ">=",
|
|
1130
|
-
ok: ops.GTE,
|
|
1131
|
-
fail: ops.LT
|
|
1132
|
-
},
|
|
1133
|
-
formatExclusiveMaximum: {
|
|
1134
|
-
okStr: "<",
|
|
1135
|
-
ok: ops.LT,
|
|
1136
|
-
fail: ops.GTE
|
|
1137
|
-
},
|
|
1138
|
-
formatExclusiveMinimum: {
|
|
1139
|
-
okStr: ">",
|
|
1140
|
-
ok: ops.GT,
|
|
1141
|
-
fail: ops.LTE
|
|
1142
|
-
}
|
|
1143
|
-
};
|
|
1144
|
-
exports.formatLimitDefinition = {
|
|
1145
|
-
keyword: Object.keys(KWDs),
|
|
1146
|
-
type: "string",
|
|
1147
|
-
schemaType: "string",
|
|
1148
|
-
$data: true,
|
|
1149
|
-
error: {
|
|
1150
|
-
message: ({ keyword, schemaCode }) => (0, codegen_1.str)`should be ${KWDs[keyword].okStr} ${schemaCode}`,
|
|
1151
|
-
params: ({ keyword, schemaCode }) => (0, codegen_1._)`{comparison: ${KWDs[keyword].okStr}, limit: ${schemaCode}}`
|
|
1152
|
-
},
|
|
1153
|
-
code(cxt) {
|
|
1154
|
-
const { gen, data, schemaCode, keyword, it } = cxt;
|
|
1155
|
-
const { opts, self } = it;
|
|
1156
|
-
if (!opts.validateFormats) return;
|
|
1157
|
-
const fCxt = new ajv_1.KeywordCxt(it, self.RULES.all.format.definition, "format");
|
|
1158
|
-
if (fCxt.$data) validate$DataFormat();
|
|
1159
|
-
else validateFormat();
|
|
1160
|
-
function validate$DataFormat() {
|
|
1161
|
-
const fmts = gen.scopeValue("formats", {
|
|
1162
|
-
ref: self.formats,
|
|
1163
|
-
code: opts.code.formats
|
|
1164
|
-
});
|
|
1165
|
-
const fmt = gen.const("fmt", (0, codegen_1._)`${fmts}[${fCxt.schemaCode}]`);
|
|
1166
|
-
cxt.fail$data((0, codegen_1.or)((0, codegen_1._)`typeof ${fmt} != "object"`, (0, codegen_1._)`${fmt} instanceof RegExp`, (0, codegen_1._)`typeof ${fmt}.compare != "function"`, compareCode(fmt)));
|
|
1167
|
-
}
|
|
1168
|
-
function validateFormat() {
|
|
1169
|
-
const format = fCxt.schema;
|
|
1170
|
-
const fmtDef = self.formats[format];
|
|
1171
|
-
if (!fmtDef || fmtDef === true) return;
|
|
1172
|
-
if (typeof fmtDef != "object" || fmtDef instanceof RegExp || typeof fmtDef.compare != "function") throw new Error(`"${keyword}": format "${format}" does not define "compare" function`);
|
|
1173
|
-
const fmt = gen.scopeValue("formats", {
|
|
1174
|
-
key: format,
|
|
1175
|
-
ref: fmtDef,
|
|
1176
|
-
code: opts.code.formats ? (0, codegen_1._)`${opts.code.formats}${(0, codegen_1.getProperty)(format)}` : void 0
|
|
1177
|
-
});
|
|
1178
|
-
cxt.fail$data(compareCode(fmt));
|
|
1179
|
-
}
|
|
1180
|
-
function compareCode(fmt) {
|
|
1181
|
-
return (0, codegen_1._)`${fmt}.compare(${data}, ${schemaCode}) ${KWDs[keyword].fail} 0`;
|
|
1182
|
-
}
|
|
1183
|
-
},
|
|
1184
|
-
dependencies: ["format"]
|
|
1185
|
-
};
|
|
1186
|
-
const formatLimitPlugin = (ajv) => {
|
|
1187
|
-
ajv.addKeyword(exports.formatLimitDefinition);
|
|
1188
|
-
return ajv;
|
|
1189
|
-
};
|
|
1190
|
-
exports.default = formatLimitPlugin;
|
|
1191
|
-
}));
|
|
1192
|
-
//#endregion
|
|
1193
|
-
//#region ../../node_modules/.pnpm/ajv-formats@3.0.1_ajv@8.18.0/node_modules/ajv-formats/dist/index.js
|
|
1194
|
-
var require_dist = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1195
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1196
|
-
const formats_1 = require_formats();
|
|
1197
|
-
const limit_1 = require_limit();
|
|
1198
|
-
const codegen_1 = require_codegen();
|
|
1199
|
-
const fullName = new codegen_1.Name("fullFormats");
|
|
1200
|
-
const fastName = new codegen_1.Name("fastFormats");
|
|
1201
|
-
const formatsPlugin = (ajv, opts = { keywords: true }) => {
|
|
1202
|
-
if (Array.isArray(opts)) {
|
|
1203
|
-
addFormats(ajv, opts, formats_1.fullFormats, fullName);
|
|
1204
|
-
return ajv;
|
|
1205
|
-
}
|
|
1206
|
-
const [formats, exportName] = opts.mode === "fast" ? [formats_1.fastFormats, fastName] : [formats_1.fullFormats, fullName];
|
|
1207
|
-
addFormats(ajv, opts.formats || formats_1.formatNames, formats, exportName);
|
|
1208
|
-
if (opts.keywords) (0, limit_1.default)(ajv);
|
|
1209
|
-
return ajv;
|
|
1210
|
-
};
|
|
1211
|
-
formatsPlugin.get = (name, mode = "full") => {
|
|
1212
|
-
const f = (mode === "fast" ? formats_1.fastFormats : formats_1.fullFormats)[name];
|
|
1213
|
-
if (!f) throw new Error(`Unknown format "${name}"`);
|
|
1214
|
-
return f;
|
|
1215
|
-
};
|
|
1216
|
-
function addFormats(ajv, list, fs, exportName) {
|
|
1217
|
-
var _a;
|
|
1218
|
-
var _b;
|
|
1219
|
-
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 || (_b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`);
|
|
1220
|
-
for (const f of list) ajv.addFormat(f, fs[f]);
|
|
1221
|
-
}
|
|
1222
|
-
module.exports = exports = formatsPlugin;
|
|
1223
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1224
|
-
exports.default = formatsPlugin;
|
|
1225
|
-
}));
|
|
1226
|
-
//#endregion
|
|
1227
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
|
|
1228
|
-
var import_ajv = /* @__PURE__ */ __toESM(require_ajv(), 1);
|
|
1229
|
-
var import_dist = /* @__PURE__ */ __toESM(require_dist(), 1);
|
|
1230
|
-
function createDefaultAjvInstance() {
|
|
1231
|
-
const ajv = new import_ajv.default({
|
|
1232
|
-
strict: false,
|
|
1233
|
-
validateFormats: true,
|
|
1234
|
-
validateSchema: false,
|
|
1235
|
-
allErrors: true
|
|
1236
|
-
});
|
|
1237
|
-
(0, import_dist.default)(ajv);
|
|
1238
|
-
return ajv;
|
|
1239
|
-
}
|
|
1240
|
-
/**
|
|
1241
|
-
* @example
|
|
1242
|
-
* ```typescript
|
|
1243
|
-
* // Use with default AJV instance (recommended)
|
|
1244
|
-
* import { AjvJsonSchemaValidator } from '@modelcontextprotocol/sdk/validation/ajv';
|
|
1245
|
-
* const validator = new AjvJsonSchemaValidator();
|
|
1246
|
-
*
|
|
1247
|
-
* // Use with custom AJV instance
|
|
1248
|
-
* import { Ajv } from 'ajv';
|
|
1249
|
-
* const ajv = new Ajv({ strict: true, allErrors: true });
|
|
1250
|
-
* const validator = new AjvJsonSchemaValidator(ajv);
|
|
1251
|
-
* ```
|
|
1252
|
-
*/
|
|
1253
|
-
var AjvJsonSchemaValidator = class {
|
|
1254
|
-
/**
|
|
1255
|
-
* Create an AJV validator
|
|
1256
|
-
*
|
|
1257
|
-
* @param ajv - Optional pre-configured AJV instance. If not provided, a default instance will be created.
|
|
1258
|
-
*
|
|
1259
|
-
* @example
|
|
1260
|
-
* ```typescript
|
|
1261
|
-
* // Use default configuration (recommended for most cases)
|
|
1262
|
-
* import { AjvJsonSchemaValidator } from '@modelcontextprotocol/sdk/validation/ajv';
|
|
1263
|
-
* const validator = new AjvJsonSchemaValidator();
|
|
1264
|
-
*
|
|
1265
|
-
* // Or provide custom AJV instance for advanced configuration
|
|
1266
|
-
* import { Ajv } from 'ajv';
|
|
1267
|
-
* import addFormats from 'ajv-formats';
|
|
1268
|
-
*
|
|
1269
|
-
* const ajv = new Ajv({ validateFormats: true });
|
|
1270
|
-
* addFormats(ajv);
|
|
1271
|
-
* const validator = new AjvJsonSchemaValidator(ajv);
|
|
1272
|
-
* ```
|
|
1273
|
-
*/
|
|
1274
|
-
constructor(ajv) {
|
|
1275
|
-
this._ajv = ajv ?? createDefaultAjvInstance();
|
|
1276
|
-
}
|
|
1277
|
-
/**
|
|
1278
|
-
* Create a validator for the given JSON Schema
|
|
1279
|
-
*
|
|
1280
|
-
* The validator is compiled once and can be reused multiple times.
|
|
1281
|
-
* If the schema has an $id, it will be cached by AJV automatically.
|
|
1282
|
-
*
|
|
1283
|
-
* @param schema - Standard JSON Schema object
|
|
1284
|
-
* @returns A validator function that validates input data
|
|
1285
|
-
*/
|
|
1286
|
-
getValidator(schema) {
|
|
1287
|
-
const ajvValidator = "$id" in schema && typeof schema.$id === "string" ? this._ajv.getSchema(schema.$id) ?? this._ajv.compile(schema) : this._ajv.compile(schema);
|
|
1288
|
-
return (input) => {
|
|
1289
|
-
if (ajvValidator(input)) return {
|
|
1290
|
-
valid: true,
|
|
1291
|
-
data: input,
|
|
1292
|
-
errorMessage: void 0
|
|
1293
|
-
};
|
|
1294
|
-
else return {
|
|
1295
|
-
valid: false,
|
|
1296
|
-
data: void 0,
|
|
1297
|
-
errorMessage: this._ajv.errorsText(ajvValidator.errors)
|
|
1298
|
-
};
|
|
1299
|
-
};
|
|
1300
|
-
}
|
|
1301
|
-
};
|
|
1302
|
-
//#endregion
|
|
1303
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/client.js
|
|
1304
|
-
/**
|
|
1305
|
-
* Experimental client task features for MCP SDK.
|
|
1306
|
-
* WARNING: These APIs are experimental and may change without notice.
|
|
1307
|
-
*
|
|
1308
|
-
* @experimental
|
|
1309
|
-
*/
|
|
1310
|
-
/**
|
|
1311
|
-
* Experimental task features for MCP clients.
|
|
1312
|
-
*
|
|
1313
|
-
* Access via `client.experimental.tasks`:
|
|
1314
|
-
* ```typescript
|
|
1315
|
-
* const stream = client.experimental.tasks.callToolStream({ name: 'tool', arguments: {} });
|
|
1316
|
-
* const task = await client.experimental.tasks.getTask(taskId);
|
|
1317
|
-
* ```
|
|
1318
|
-
*
|
|
1319
|
-
* @experimental
|
|
1320
|
-
*/
|
|
1321
|
-
var ExperimentalClientTasks = class {
|
|
1322
|
-
constructor(_client) {
|
|
1323
|
-
this._client = _client;
|
|
1324
|
-
}
|
|
1325
|
-
/**
|
|
1326
|
-
* Calls a tool and returns an AsyncGenerator that yields response messages.
|
|
1327
|
-
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
1328
|
-
*
|
|
1329
|
-
* This method provides streaming access to tool execution, allowing you to
|
|
1330
|
-
* observe intermediate task status updates for long-running tool calls.
|
|
1331
|
-
* Automatically validates structured output if the tool has an outputSchema.
|
|
1332
|
-
*
|
|
1333
|
-
* @example
|
|
1334
|
-
* ```typescript
|
|
1335
|
-
* const stream = client.experimental.tasks.callToolStream({ name: 'myTool', arguments: {} });
|
|
1336
|
-
* for await (const message of stream) {
|
|
1337
|
-
* switch (message.type) {
|
|
1338
|
-
* case 'taskCreated':
|
|
1339
|
-
* console.log('Tool execution started:', message.task.taskId);
|
|
1340
|
-
* break;
|
|
1341
|
-
* case 'taskStatus':
|
|
1342
|
-
* console.log('Tool status:', message.task.status);
|
|
1343
|
-
* break;
|
|
1344
|
-
* case 'result':
|
|
1345
|
-
* console.log('Tool result:', message.result);
|
|
1346
|
-
* break;
|
|
1347
|
-
* case 'error':
|
|
1348
|
-
* console.error('Tool error:', message.error);
|
|
1349
|
-
* break;
|
|
1350
|
-
* }
|
|
1351
|
-
* }
|
|
1352
|
-
* ```
|
|
1353
|
-
*
|
|
1354
|
-
* @param params - Tool call parameters (name and arguments)
|
|
1355
|
-
* @param resultSchema - Zod schema for validating the result (defaults to CallToolResultSchema)
|
|
1356
|
-
* @param options - Optional request options (timeout, signal, task creation params, etc.)
|
|
1357
|
-
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
1358
|
-
*
|
|
1359
|
-
* @experimental
|
|
1360
|
-
*/
|
|
1361
|
-
async *callToolStream(params, resultSchema = CallToolResultSchema, options) {
|
|
1362
|
-
const clientInternal = this._client;
|
|
1363
|
-
const optionsWithTask = {
|
|
1364
|
-
...options,
|
|
1365
|
-
task: options?.task ?? (clientInternal.isToolTask(params.name) ? {} : void 0)
|
|
1366
|
-
};
|
|
1367
|
-
const stream = clientInternal.requestStream({
|
|
1368
|
-
method: "tools/call",
|
|
1369
|
-
params
|
|
1370
|
-
}, resultSchema, optionsWithTask);
|
|
1371
|
-
const validator = clientInternal.getToolOutputValidator(params.name);
|
|
1372
|
-
for await (const message of stream) {
|
|
1373
|
-
if (message.type === "result" && validator) {
|
|
1374
|
-
const result = message.result;
|
|
1375
|
-
if (!result.structuredContent && !result.isError) {
|
|
1376
|
-
yield {
|
|
1377
|
-
type: "error",
|
|
1378
|
-
error: new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`)
|
|
1379
|
-
};
|
|
1380
|
-
return;
|
|
1381
|
-
}
|
|
1382
|
-
if (result.structuredContent) try {
|
|
1383
|
-
const validationResult = validator(result.structuredContent);
|
|
1384
|
-
if (!validationResult.valid) {
|
|
1385
|
-
yield {
|
|
1386
|
-
type: "error",
|
|
1387
|
-
error: new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`)
|
|
1388
|
-
};
|
|
1389
|
-
return;
|
|
1390
|
-
}
|
|
1391
|
-
} catch (error) {
|
|
1392
|
-
if (error instanceof McpError) {
|
|
1393
|
-
yield {
|
|
1394
|
-
type: "error",
|
|
1395
|
-
error
|
|
1396
|
-
};
|
|
1397
|
-
return;
|
|
1398
|
-
}
|
|
1399
|
-
yield {
|
|
1400
|
-
type: "error",
|
|
1401
|
-
error: new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error instanceof Error ? error.message : String(error)}`)
|
|
1402
|
-
};
|
|
1403
|
-
return;
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
yield message;
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
/**
|
|
1410
|
-
* Gets the current status of a task.
|
|
1411
|
-
*
|
|
1412
|
-
* @param taskId - The task identifier
|
|
1413
|
-
* @param options - Optional request options
|
|
1414
|
-
* @returns The task status
|
|
1415
|
-
*
|
|
1416
|
-
* @experimental
|
|
1417
|
-
*/
|
|
1418
|
-
async getTask(taskId, options) {
|
|
1419
|
-
return this._client.getTask({ taskId }, options);
|
|
1420
|
-
}
|
|
1421
|
-
/**
|
|
1422
|
-
* Retrieves the result of a completed task.
|
|
1423
|
-
*
|
|
1424
|
-
* @param taskId - The task identifier
|
|
1425
|
-
* @param resultSchema - Zod schema for validating the result
|
|
1426
|
-
* @param options - Optional request options
|
|
1427
|
-
* @returns The task result
|
|
1428
|
-
*
|
|
1429
|
-
* @experimental
|
|
1430
|
-
*/
|
|
1431
|
-
async getTaskResult(taskId, resultSchema, options) {
|
|
1432
|
-
return this._client.getTaskResult({ taskId }, resultSchema, options);
|
|
1433
|
-
}
|
|
1434
|
-
/**
|
|
1435
|
-
* Lists tasks with optional pagination.
|
|
1436
|
-
*
|
|
1437
|
-
* @param cursor - Optional pagination cursor
|
|
1438
|
-
* @param options - Optional request options
|
|
1439
|
-
* @returns List of tasks with optional next cursor
|
|
1440
|
-
*
|
|
1441
|
-
* @experimental
|
|
1442
|
-
*/
|
|
1443
|
-
async listTasks(cursor, options) {
|
|
1444
|
-
return this._client.listTasks(cursor ? { cursor } : void 0, options);
|
|
1445
|
-
}
|
|
1446
|
-
/**
|
|
1447
|
-
* Cancels a running task.
|
|
1448
|
-
*
|
|
1449
|
-
* @param taskId - The task identifier
|
|
1450
|
-
* @param options - Optional request options
|
|
1451
|
-
*
|
|
1452
|
-
* @experimental
|
|
1453
|
-
*/
|
|
1454
|
-
async cancelTask(taskId, options) {
|
|
1455
|
-
return this._client.cancelTask({ taskId }, options);
|
|
1456
|
-
}
|
|
1457
|
-
/**
|
|
1458
|
-
* Sends a request and returns an AsyncGenerator that yields response messages.
|
|
1459
|
-
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
1460
|
-
*
|
|
1461
|
-
* This method provides streaming access to request processing, allowing you to
|
|
1462
|
-
* observe intermediate task status updates for task-augmented requests.
|
|
1463
|
-
*
|
|
1464
|
-
* @param request - The request to send
|
|
1465
|
-
* @param resultSchema - Zod schema for validating the result
|
|
1466
|
-
* @param options - Optional request options (timeout, signal, task creation params, etc.)
|
|
1467
|
-
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
1468
|
-
*
|
|
1469
|
-
* @experimental
|
|
1470
|
-
*/
|
|
1471
|
-
requestStream(request, resultSchema, options) {
|
|
1472
|
-
return this._client.requestStream(request, resultSchema, options);
|
|
1473
|
-
}
|
|
1474
|
-
};
|
|
1475
|
-
//#endregion
|
|
1476
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
1477
|
-
/**
|
|
1478
|
-
* Experimental task capability assertion helpers.
|
|
1479
|
-
* WARNING: These APIs are experimental and may change without notice.
|
|
1480
|
-
*
|
|
1481
|
-
* @experimental
|
|
1482
|
-
*/
|
|
1483
|
-
/**
|
|
1484
|
-
* Asserts that task creation is supported for tools/call.
|
|
1485
|
-
* Used by Client.assertTaskCapability and Server.assertTaskHandlerCapability.
|
|
1486
|
-
*
|
|
1487
|
-
* @param requests - The task requests capability object
|
|
1488
|
-
* @param method - The method being checked
|
|
1489
|
-
* @param entityName - 'Server' or 'Client' for error messages
|
|
1490
|
-
* @throws Error if the capability is not supported
|
|
1491
|
-
*
|
|
1492
|
-
* @experimental
|
|
1493
|
-
*/
|
|
1494
|
-
function assertToolsCallTaskCapability(requests, method, entityName) {
|
|
1495
|
-
if (!requests) throw new Error(`${entityName} does not support task creation (required for ${method})`);
|
|
1496
|
-
switch (method) {
|
|
1497
|
-
case "tools/call":
|
|
1498
|
-
if (!requests.tools?.call) throw new Error(`${entityName} does not support task creation for tools/call (required for ${method})`);
|
|
1499
|
-
break;
|
|
1500
|
-
default: break;
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
/**
|
|
1504
|
-
* Asserts that task creation is supported for sampling/createMessage or elicitation/create.
|
|
1505
|
-
* Used by Server.assertTaskCapability and Client.assertTaskHandlerCapability.
|
|
1506
|
-
*
|
|
1507
|
-
* @param requests - The task requests capability object
|
|
1508
|
-
* @param method - The method being checked
|
|
1509
|
-
* @param entityName - 'Server' or 'Client' for error messages
|
|
1510
|
-
* @throws Error if the capability is not supported
|
|
1511
|
-
*
|
|
1512
|
-
* @experimental
|
|
1513
|
-
*/
|
|
1514
|
-
function assertClientRequestTaskCapability(requests, method, entityName) {
|
|
1515
|
-
if (!requests) throw new Error(`${entityName} does not support task creation (required for ${method})`);
|
|
1516
|
-
switch (method) {
|
|
1517
|
-
case "sampling/createMessage":
|
|
1518
|
-
if (!requests.sampling?.createMessage) throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${method})`);
|
|
1519
|
-
break;
|
|
1520
|
-
case "elicitation/create":
|
|
1521
|
-
if (!requests.elicitation?.create) throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${method})`);
|
|
1522
|
-
break;
|
|
1523
|
-
default: break;
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
//#endregion
|
|
1527
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js
|
|
1528
|
-
/**
|
|
1529
|
-
* Elicitation default application helper. Applies defaults to the data based on the schema.
|
|
1530
|
-
*
|
|
1531
|
-
* @param schema - The schema to apply defaults to.
|
|
1532
|
-
* @param data - The data to apply defaults to.
|
|
1533
|
-
*/
|
|
1534
|
-
function applyElicitationDefaults(schema, data) {
|
|
1535
|
-
if (!schema || data === null || typeof data !== "object") return;
|
|
1536
|
-
if (schema.type === "object" && schema.properties && typeof schema.properties === "object") {
|
|
1537
|
-
const obj = data;
|
|
1538
|
-
const props = schema.properties;
|
|
1539
|
-
for (const key of Object.keys(props)) {
|
|
1540
|
-
const propSchema = props[key];
|
|
1541
|
-
if (obj[key] === void 0 && Object.prototype.hasOwnProperty.call(propSchema, "default")) obj[key] = propSchema.default;
|
|
1542
|
-
if (obj[key] !== void 0) applyElicitationDefaults(propSchema, obj[key]);
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
if (Array.isArray(schema.anyOf)) {
|
|
1546
|
-
for (const sub of schema.anyOf) if (typeof sub !== "boolean") applyElicitationDefaults(sub, data);
|
|
1547
|
-
}
|
|
1548
|
-
if (Array.isArray(schema.oneOf)) {
|
|
1549
|
-
for (const sub of schema.oneOf) if (typeof sub !== "boolean") applyElicitationDefaults(sub, data);
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
/**
|
|
1553
|
-
* Determines which elicitation modes are supported based on declared client capabilities.
|
|
1554
|
-
*
|
|
1555
|
-
* According to the spec:
|
|
1556
|
-
* - An empty elicitation capability object defaults to form mode support (backwards compatibility)
|
|
1557
|
-
* - URL mode is only supported if explicitly declared
|
|
1558
|
-
*
|
|
1559
|
-
* @param capabilities - The client's elicitation capabilities
|
|
1560
|
-
* @returns An object indicating which modes are supported
|
|
1561
|
-
*/
|
|
1562
|
-
function getSupportedElicitationModes(capabilities) {
|
|
1563
|
-
if (!capabilities) return {
|
|
1564
|
-
supportsFormMode: false,
|
|
1565
|
-
supportsUrlMode: false
|
|
1566
|
-
};
|
|
1567
|
-
const hasFormCapability = capabilities.form !== void 0;
|
|
1568
|
-
const hasUrlCapability = capabilities.url !== void 0;
|
|
1569
|
-
return {
|
|
1570
|
-
supportsFormMode: hasFormCapability || !hasFormCapability && !hasUrlCapability,
|
|
1571
|
-
supportsUrlMode: hasUrlCapability
|
|
1572
|
-
};
|
|
1573
|
-
}
|
|
1574
|
-
/**
|
|
1575
|
-
* An MCP client on top of a pluggable transport.
|
|
1576
|
-
*
|
|
1577
|
-
* The client will automatically begin the initialization flow with the server when connect() is called.
|
|
1578
|
-
*
|
|
1579
|
-
* To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters:
|
|
1580
|
-
*
|
|
1581
|
-
* ```typescript
|
|
1582
|
-
* // Custom schemas
|
|
1583
|
-
* const CustomRequestSchema = RequestSchema.extend({...})
|
|
1584
|
-
* const CustomNotificationSchema = NotificationSchema.extend({...})
|
|
1585
|
-
* const CustomResultSchema = ResultSchema.extend({...})
|
|
1586
|
-
*
|
|
1587
|
-
* // Type aliases
|
|
1588
|
-
* type CustomRequest = z.infer<typeof CustomRequestSchema>
|
|
1589
|
-
* type CustomNotification = z.infer<typeof CustomNotificationSchema>
|
|
1590
|
-
* type CustomResult = z.infer<typeof CustomResultSchema>
|
|
1591
|
-
*
|
|
1592
|
-
* // Create typed client
|
|
1593
|
-
* const client = new Client<CustomRequest, CustomNotification, CustomResult>({
|
|
1594
|
-
* name: "CustomClient",
|
|
1595
|
-
* version: "1.0.0"
|
|
1596
|
-
* })
|
|
1597
|
-
* ```
|
|
1598
|
-
*/
|
|
1599
|
-
var Client = class extends Protocol {
|
|
1600
|
-
/**
|
|
1601
|
-
* Initializes this client with the given name and version information.
|
|
1602
|
-
*/
|
|
1603
|
-
constructor(_clientInfo, options) {
|
|
1604
|
-
super(options);
|
|
1605
|
-
this._clientInfo = _clientInfo;
|
|
1606
|
-
this._cachedToolOutputValidators = /* @__PURE__ */ new Map();
|
|
1607
|
-
this._cachedKnownTaskTools = /* @__PURE__ */ new Set();
|
|
1608
|
-
this._cachedRequiredTaskTools = /* @__PURE__ */ new Set();
|
|
1609
|
-
this._listChangedDebounceTimers = /* @__PURE__ */ new Map();
|
|
1610
|
-
this._capabilities = options?.capabilities ?? {};
|
|
1611
|
-
this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
|
|
1612
|
-
if (options?.listChanged) this._pendingListChangedConfig = options.listChanged;
|
|
1613
|
-
}
|
|
1614
|
-
/**
|
|
1615
|
-
* Set up handlers for list changed notifications based on config and server capabilities.
|
|
1616
|
-
* This should only be called after initialization when server capabilities are known.
|
|
1617
|
-
* Handlers are silently skipped if the server doesn't advertise the corresponding listChanged capability.
|
|
1618
|
-
* @internal
|
|
1619
|
-
*/
|
|
1620
|
-
_setupListChangedHandlers(config) {
|
|
1621
|
-
if (config.tools && this._serverCapabilities?.tools?.listChanged) this._setupListChangedHandler("tools", ToolListChangedNotificationSchema, config.tools, async () => {
|
|
1622
|
-
return (await this.listTools()).tools;
|
|
1623
|
-
});
|
|
1624
|
-
if (config.prompts && this._serverCapabilities?.prompts?.listChanged) this._setupListChangedHandler("prompts", PromptListChangedNotificationSchema, config.prompts, async () => {
|
|
1625
|
-
return (await this.listPrompts()).prompts;
|
|
1626
|
-
});
|
|
1627
|
-
if (config.resources && this._serverCapabilities?.resources?.listChanged) this._setupListChangedHandler("resources", ResourceListChangedNotificationSchema, config.resources, async () => {
|
|
1628
|
-
return (await this.listResources()).resources;
|
|
1629
|
-
});
|
|
1630
|
-
}
|
|
1631
|
-
/**
|
|
1632
|
-
* Access experimental features.
|
|
1633
|
-
*
|
|
1634
|
-
* WARNING: These APIs are experimental and may change without notice.
|
|
1635
|
-
*
|
|
1636
|
-
* @experimental
|
|
1637
|
-
*/
|
|
1638
|
-
get experimental() {
|
|
1639
|
-
if (!this._experimental) this._experimental = { tasks: new ExperimentalClientTasks(this) };
|
|
1640
|
-
return this._experimental;
|
|
1641
|
-
}
|
|
1642
|
-
/**
|
|
1643
|
-
* Registers new capabilities. This can only be called before connecting to a transport.
|
|
1644
|
-
*
|
|
1645
|
-
* The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
|
|
1646
|
-
*/
|
|
1647
|
-
registerCapabilities(capabilities) {
|
|
1648
|
-
if (this.transport) throw new Error("Cannot register capabilities after connecting to transport");
|
|
1649
|
-
this._capabilities = mergeCapabilities(this._capabilities, capabilities);
|
|
1650
|
-
}
|
|
1651
|
-
/**
|
|
1652
|
-
* Override request handler registration to enforce client-side validation for elicitation.
|
|
1653
|
-
*/
|
|
1654
|
-
setRequestHandler(requestSchema, handler) {
|
|
1655
|
-
const methodSchema = getObjectShape(requestSchema)?.method;
|
|
1656
|
-
if (!methodSchema) throw new Error("Schema is missing a method literal");
|
|
1657
|
-
let methodValue;
|
|
1658
|
-
if (isZ4Schema(methodSchema)) {
|
|
1659
|
-
const v4Schema = methodSchema;
|
|
1660
|
-
methodValue = (v4Schema._zod?.def)?.value ?? v4Schema.value;
|
|
1661
|
-
} else {
|
|
1662
|
-
const v3Schema = methodSchema;
|
|
1663
|
-
methodValue = v3Schema._def?.value ?? v3Schema.value;
|
|
1664
|
-
}
|
|
1665
|
-
if (typeof methodValue !== "string") throw new Error("Schema method literal must be a string");
|
|
1666
|
-
const method = methodValue;
|
|
1667
|
-
if (method === "elicitation/create") {
|
|
1668
|
-
const wrappedHandler = async (request, extra) => {
|
|
1669
|
-
const validatedRequest = safeParse(ElicitRequestSchema, request);
|
|
1670
|
-
if (!validatedRequest.success) {
|
|
1671
|
-
const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
1672
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage}`);
|
|
1673
|
-
}
|
|
1674
|
-
const { params } = validatedRequest.data;
|
|
1675
|
-
params.mode = params.mode ?? "form";
|
|
1676
|
-
const { supportsFormMode, supportsUrlMode } = getSupportedElicitationModes(this._capabilities.elicitation);
|
|
1677
|
-
if (params.mode === "form" && !supportsFormMode) throw new McpError(ErrorCode.InvalidParams, "Client does not support form-mode elicitation requests");
|
|
1678
|
-
if (params.mode === "url" && !supportsUrlMode) throw new McpError(ErrorCode.InvalidParams, "Client does not support URL-mode elicitation requests");
|
|
1679
|
-
const result = await Promise.resolve(handler(request, extra));
|
|
1680
|
-
if (params.task) {
|
|
1681
|
-
const taskValidationResult = safeParse(CreateTaskResultSchema, result);
|
|
1682
|
-
if (!taskValidationResult.success) {
|
|
1683
|
-
const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
|
|
1684
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
|
|
1685
|
-
}
|
|
1686
|
-
return taskValidationResult.data;
|
|
1687
|
-
}
|
|
1688
|
-
const validationResult = safeParse(ElicitResultSchema, result);
|
|
1689
|
-
if (!validationResult.success) {
|
|
1690
|
-
const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
|
|
1691
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation result: ${errorMessage}`);
|
|
1692
|
-
}
|
|
1693
|
-
const validatedResult = validationResult.data;
|
|
1694
|
-
const requestedSchema = params.mode === "form" ? params.requestedSchema : void 0;
|
|
1695
|
-
if (params.mode === "form" && validatedResult.action === "accept" && validatedResult.content && requestedSchema) {
|
|
1696
|
-
if (this._capabilities.elicitation?.form?.applyDefaults) try {
|
|
1697
|
-
applyElicitationDefaults(requestedSchema, validatedResult.content);
|
|
1698
|
-
} catch {}
|
|
1699
|
-
}
|
|
1700
|
-
return validatedResult;
|
|
1701
|
-
};
|
|
1702
|
-
return super.setRequestHandler(requestSchema, wrappedHandler);
|
|
1703
|
-
}
|
|
1704
|
-
if (method === "sampling/createMessage") {
|
|
1705
|
-
const wrappedHandler = async (request, extra) => {
|
|
1706
|
-
const validatedRequest = safeParse(CreateMessageRequestSchema, request);
|
|
1707
|
-
if (!validatedRequest.success) {
|
|
1708
|
-
const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
1709
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage}`);
|
|
1710
|
-
}
|
|
1711
|
-
const { params } = validatedRequest.data;
|
|
1712
|
-
const result = await Promise.resolve(handler(request, extra));
|
|
1713
|
-
if (params.task) {
|
|
1714
|
-
const taskValidationResult = safeParse(CreateTaskResultSchema, result);
|
|
1715
|
-
if (!taskValidationResult.success) {
|
|
1716
|
-
const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
|
|
1717
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
|
|
1718
|
-
}
|
|
1719
|
-
return taskValidationResult.data;
|
|
1720
|
-
}
|
|
1721
|
-
const validationResult = safeParse(params.tools || params.toolChoice ? CreateMessageResultWithToolsSchema : CreateMessageResultSchema, result);
|
|
1722
|
-
if (!validationResult.success) {
|
|
1723
|
-
const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
|
|
1724
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid sampling result: ${errorMessage}`);
|
|
1725
|
-
}
|
|
1726
|
-
return validationResult.data;
|
|
1727
|
-
};
|
|
1728
|
-
return super.setRequestHandler(requestSchema, wrappedHandler);
|
|
1729
|
-
}
|
|
1730
|
-
return super.setRequestHandler(requestSchema, handler);
|
|
1731
|
-
}
|
|
1732
|
-
assertCapability(capability, method) {
|
|
1733
|
-
if (!this._serverCapabilities?.[capability]) throw new Error(`Server does not support ${capability} (required for ${method})`);
|
|
1734
|
-
}
|
|
1735
|
-
async connect(transport, options) {
|
|
1736
|
-
await super.connect(transport);
|
|
1737
|
-
if (transport.sessionId !== void 0) return;
|
|
1738
|
-
try {
|
|
1739
|
-
const result = await this.request({
|
|
1740
|
-
method: "initialize",
|
|
1741
|
-
params: {
|
|
1742
|
-
protocolVersion: LATEST_PROTOCOL_VERSION,
|
|
1743
|
-
capabilities: this._capabilities,
|
|
1744
|
-
clientInfo: this._clientInfo
|
|
1745
|
-
}
|
|
1746
|
-
}, InitializeResultSchema, options);
|
|
1747
|
-
if (result === void 0) throw new Error(`Server sent invalid initialize result: ${result}`);
|
|
1748
|
-
if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) throw new Error(`Server's protocol version is not supported: ${result.protocolVersion}`);
|
|
1749
|
-
this._serverCapabilities = result.capabilities;
|
|
1750
|
-
this._serverVersion = result.serverInfo;
|
|
1751
|
-
if (transport.setProtocolVersion) transport.setProtocolVersion(result.protocolVersion);
|
|
1752
|
-
this._instructions = result.instructions;
|
|
1753
|
-
await this.notification({ method: "notifications/initialized" });
|
|
1754
|
-
if (this._pendingListChangedConfig) {
|
|
1755
|
-
this._setupListChangedHandlers(this._pendingListChangedConfig);
|
|
1756
|
-
this._pendingListChangedConfig = void 0;
|
|
1757
|
-
}
|
|
1758
|
-
} catch (error) {
|
|
1759
|
-
this.close();
|
|
1760
|
-
throw error;
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
/**
|
|
1764
|
-
* After initialization has completed, this will be populated with the server's reported capabilities.
|
|
1765
|
-
*/
|
|
1766
|
-
getServerCapabilities() {
|
|
1767
|
-
return this._serverCapabilities;
|
|
1768
|
-
}
|
|
1769
|
-
/**
|
|
1770
|
-
* After initialization has completed, this will be populated with information about the server's name and version.
|
|
1771
|
-
*/
|
|
1772
|
-
getServerVersion() {
|
|
1773
|
-
return this._serverVersion;
|
|
1774
|
-
}
|
|
1775
|
-
/**
|
|
1776
|
-
* After initialization has completed, this may be populated with information about the server's instructions.
|
|
1777
|
-
*/
|
|
1778
|
-
getInstructions() {
|
|
1779
|
-
return this._instructions;
|
|
1780
|
-
}
|
|
1781
|
-
assertCapabilityForMethod(method) {
|
|
1782
|
-
switch (method) {
|
|
1783
|
-
case "logging/setLevel":
|
|
1784
|
-
if (!this._serverCapabilities?.logging) throw new Error(`Server does not support logging (required for ${method})`);
|
|
1785
|
-
break;
|
|
1786
|
-
case "prompts/get":
|
|
1787
|
-
case "prompts/list":
|
|
1788
|
-
if (!this._serverCapabilities?.prompts) throw new Error(`Server does not support prompts (required for ${method})`);
|
|
1789
|
-
break;
|
|
1790
|
-
case "resources/list":
|
|
1791
|
-
case "resources/templates/list":
|
|
1792
|
-
case "resources/read":
|
|
1793
|
-
case "resources/subscribe":
|
|
1794
|
-
case "resources/unsubscribe":
|
|
1795
|
-
if (!this._serverCapabilities?.resources) throw new Error(`Server does not support resources (required for ${method})`);
|
|
1796
|
-
if (method === "resources/subscribe" && !this._serverCapabilities.resources.subscribe) throw new Error(`Server does not support resource subscriptions (required for ${method})`);
|
|
1797
|
-
break;
|
|
1798
|
-
case "tools/call":
|
|
1799
|
-
case "tools/list":
|
|
1800
|
-
if (!this._serverCapabilities?.tools) throw new Error(`Server does not support tools (required for ${method})`);
|
|
1801
|
-
break;
|
|
1802
|
-
case "completion/complete":
|
|
1803
|
-
if (!this._serverCapabilities?.completions) throw new Error(`Server does not support completions (required for ${method})`);
|
|
1804
|
-
break;
|
|
1805
|
-
case "initialize": break;
|
|
1806
|
-
case "ping": break;
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1809
|
-
assertNotificationCapability(method) {
|
|
1810
|
-
switch (method) {
|
|
1811
|
-
case "notifications/roots/list_changed":
|
|
1812
|
-
if (!this._capabilities.roots?.listChanged) throw new Error(`Client does not support roots list changed notifications (required for ${method})`);
|
|
1813
|
-
break;
|
|
1814
|
-
case "notifications/initialized": break;
|
|
1815
|
-
case "notifications/cancelled": break;
|
|
1816
|
-
case "notifications/progress": break;
|
|
1817
|
-
}
|
|
1818
|
-
}
|
|
1819
|
-
assertRequestHandlerCapability(method) {
|
|
1820
|
-
if (!this._capabilities) return;
|
|
1821
|
-
switch (method) {
|
|
1822
|
-
case "sampling/createMessage":
|
|
1823
|
-
if (!this._capabilities.sampling) throw new Error(`Client does not support sampling capability (required for ${method})`);
|
|
1824
|
-
break;
|
|
1825
|
-
case "elicitation/create":
|
|
1826
|
-
if (!this._capabilities.elicitation) throw new Error(`Client does not support elicitation capability (required for ${method})`);
|
|
1827
|
-
break;
|
|
1828
|
-
case "roots/list":
|
|
1829
|
-
if (!this._capabilities.roots) throw new Error(`Client does not support roots capability (required for ${method})`);
|
|
1830
|
-
break;
|
|
1831
|
-
case "tasks/get":
|
|
1832
|
-
case "tasks/list":
|
|
1833
|
-
case "tasks/result":
|
|
1834
|
-
case "tasks/cancel":
|
|
1835
|
-
if (!this._capabilities.tasks) throw new Error(`Client does not support tasks capability (required for ${method})`);
|
|
1836
|
-
break;
|
|
1837
|
-
case "ping": break;
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
assertTaskCapability(method) {
|
|
1841
|
-
assertToolsCallTaskCapability(this._serverCapabilities?.tasks?.requests, method, "Server");
|
|
1842
|
-
}
|
|
1843
|
-
assertTaskHandlerCapability(method) {
|
|
1844
|
-
if (!this._capabilities) return;
|
|
1845
|
-
assertClientRequestTaskCapability(this._capabilities.tasks?.requests, method, "Client");
|
|
1846
|
-
}
|
|
1847
|
-
async ping(options) {
|
|
1848
|
-
return this.request({ method: "ping" }, EmptyResultSchema, options);
|
|
1849
|
-
}
|
|
1850
|
-
async complete(params, options) {
|
|
1851
|
-
return this.request({
|
|
1852
|
-
method: "completion/complete",
|
|
1853
|
-
params
|
|
1854
|
-
}, CompleteResultSchema, options);
|
|
1855
|
-
}
|
|
1856
|
-
async setLoggingLevel(level, options) {
|
|
1857
|
-
return this.request({
|
|
1858
|
-
method: "logging/setLevel",
|
|
1859
|
-
params: { level }
|
|
1860
|
-
}, EmptyResultSchema, options);
|
|
1861
|
-
}
|
|
1862
|
-
async getPrompt(params, options) {
|
|
1863
|
-
return this.request({
|
|
1864
|
-
method: "prompts/get",
|
|
1865
|
-
params
|
|
1866
|
-
}, GetPromptResultSchema, options);
|
|
1867
|
-
}
|
|
1868
|
-
async listPrompts(params, options) {
|
|
1869
|
-
return this.request({
|
|
1870
|
-
method: "prompts/list",
|
|
1871
|
-
params
|
|
1872
|
-
}, ListPromptsResultSchema, options);
|
|
1873
|
-
}
|
|
1874
|
-
async listResources(params, options) {
|
|
1875
|
-
return this.request({
|
|
1876
|
-
method: "resources/list",
|
|
1877
|
-
params
|
|
1878
|
-
}, ListResourcesResultSchema, options);
|
|
1879
|
-
}
|
|
1880
|
-
async listResourceTemplates(params, options) {
|
|
1881
|
-
return this.request({
|
|
1882
|
-
method: "resources/templates/list",
|
|
1883
|
-
params
|
|
1884
|
-
}, ListResourceTemplatesResultSchema, options);
|
|
1885
|
-
}
|
|
1886
|
-
async readResource(params, options) {
|
|
1887
|
-
return this.request({
|
|
1888
|
-
method: "resources/read",
|
|
1889
|
-
params
|
|
1890
|
-
}, ReadResourceResultSchema, options);
|
|
1891
|
-
}
|
|
1892
|
-
async subscribeResource(params, options) {
|
|
1893
|
-
return this.request({
|
|
1894
|
-
method: "resources/subscribe",
|
|
1895
|
-
params
|
|
1896
|
-
}, EmptyResultSchema, options);
|
|
1897
|
-
}
|
|
1898
|
-
async unsubscribeResource(params, options) {
|
|
1899
|
-
return this.request({
|
|
1900
|
-
method: "resources/unsubscribe",
|
|
1901
|
-
params
|
|
1902
|
-
}, EmptyResultSchema, options);
|
|
1903
|
-
}
|
|
1904
|
-
/**
|
|
1905
|
-
* Calls a tool and waits for the result. Automatically validates structured output if the tool has an outputSchema.
|
|
1906
|
-
*
|
|
1907
|
-
* For task-based execution with streaming behavior, use client.experimental.tasks.callToolStream() instead.
|
|
1908
|
-
*/
|
|
1909
|
-
async callTool(params, resultSchema = CallToolResultSchema, options) {
|
|
1910
|
-
if (this.isToolTaskRequired(params.name)) throw new McpError(ErrorCode.InvalidRequest, `Tool "${params.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);
|
|
1911
|
-
const result = await this.request({
|
|
1912
|
-
method: "tools/call",
|
|
1913
|
-
params
|
|
1914
|
-
}, resultSchema, options);
|
|
1915
|
-
const validator = this.getToolOutputValidator(params.name);
|
|
1916
|
-
if (validator) {
|
|
1917
|
-
if (!result.structuredContent && !result.isError) throw new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`);
|
|
1918
|
-
if (result.structuredContent) try {
|
|
1919
|
-
const validationResult = validator(result.structuredContent);
|
|
1920
|
-
if (!validationResult.valid) throw new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`);
|
|
1921
|
-
} catch (error) {
|
|
1922
|
-
if (error instanceof McpError) throw error;
|
|
1923
|
-
throw new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error instanceof Error ? error.message : String(error)}`);
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
return result;
|
|
1927
|
-
}
|
|
1928
|
-
isToolTask(toolName) {
|
|
1929
|
-
if (!this._serverCapabilities?.tasks?.requests?.tools?.call) return false;
|
|
1930
|
-
return this._cachedKnownTaskTools.has(toolName);
|
|
1931
|
-
}
|
|
1932
|
-
/**
|
|
1933
|
-
* Check if a tool requires task-based execution.
|
|
1934
|
-
* Unlike isToolTask which includes 'optional' tools, this only checks for 'required'.
|
|
1935
|
-
*/
|
|
1936
|
-
isToolTaskRequired(toolName) {
|
|
1937
|
-
return this._cachedRequiredTaskTools.has(toolName);
|
|
1938
|
-
}
|
|
1939
|
-
/**
|
|
1940
|
-
* Cache validators for tool output schemas.
|
|
1941
|
-
* Called after listTools() to pre-compile validators for better performance.
|
|
1942
|
-
*/
|
|
1943
|
-
cacheToolMetadata(tools) {
|
|
1944
|
-
this._cachedToolOutputValidators.clear();
|
|
1945
|
-
this._cachedKnownTaskTools.clear();
|
|
1946
|
-
this._cachedRequiredTaskTools.clear();
|
|
1947
|
-
for (const tool of tools) {
|
|
1948
|
-
if (tool.outputSchema) {
|
|
1949
|
-
const toolValidator = this._jsonSchemaValidator.getValidator(tool.outputSchema);
|
|
1950
|
-
this._cachedToolOutputValidators.set(tool.name, toolValidator);
|
|
1951
|
-
}
|
|
1952
|
-
const taskSupport = tool.execution?.taskSupport;
|
|
1953
|
-
if (taskSupport === "required" || taskSupport === "optional") this._cachedKnownTaskTools.add(tool.name);
|
|
1954
|
-
if (taskSupport === "required") this._cachedRequiredTaskTools.add(tool.name);
|
|
1955
|
-
}
|
|
1956
|
-
}
|
|
1957
|
-
/**
|
|
1958
|
-
* Get cached validator for a tool
|
|
1959
|
-
*/
|
|
1960
|
-
getToolOutputValidator(toolName) {
|
|
1961
|
-
return this._cachedToolOutputValidators.get(toolName);
|
|
1962
|
-
}
|
|
1963
|
-
async listTools(params, options) {
|
|
1964
|
-
const result = await this.request({
|
|
1965
|
-
method: "tools/list",
|
|
1966
|
-
params
|
|
1967
|
-
}, ListToolsResultSchema, options);
|
|
1968
|
-
this.cacheToolMetadata(result.tools);
|
|
1969
|
-
return result;
|
|
1970
|
-
}
|
|
1971
|
-
/**
|
|
1972
|
-
* Set up a single list changed handler.
|
|
1973
|
-
* @internal
|
|
1974
|
-
*/
|
|
1975
|
-
_setupListChangedHandler(listType, notificationSchema, options, fetcher) {
|
|
1976
|
-
const parseResult = ListChangedOptionsBaseSchema.safeParse(options);
|
|
1977
|
-
if (!parseResult.success) throw new Error(`Invalid ${listType} listChanged options: ${parseResult.error.message}`);
|
|
1978
|
-
if (typeof options.onChanged !== "function") throw new Error(`Invalid ${listType} listChanged options: onChanged must be a function`);
|
|
1979
|
-
const { autoRefresh, debounceMs } = parseResult.data;
|
|
1980
|
-
const { onChanged } = options;
|
|
1981
|
-
const refresh = async () => {
|
|
1982
|
-
if (!autoRefresh) {
|
|
1983
|
-
onChanged(null, null);
|
|
1984
|
-
return;
|
|
1985
|
-
}
|
|
1986
|
-
try {
|
|
1987
|
-
onChanged(null, await fetcher());
|
|
1988
|
-
} catch (e) {
|
|
1989
|
-
onChanged(e instanceof Error ? e : new Error(String(e)), null);
|
|
1990
|
-
}
|
|
1991
|
-
};
|
|
1992
|
-
const handler = () => {
|
|
1993
|
-
if (debounceMs) {
|
|
1994
|
-
const existingTimer = this._listChangedDebounceTimers.get(listType);
|
|
1995
|
-
if (existingTimer) clearTimeout(existingTimer);
|
|
1996
|
-
const timer = setTimeout(refresh, debounceMs);
|
|
1997
|
-
this._listChangedDebounceTimers.set(listType, timer);
|
|
1998
|
-
} else refresh();
|
|
1999
|
-
};
|
|
2000
|
-
this.setNotificationHandler(notificationSchema, handler);
|
|
2001
|
-
}
|
|
2002
|
-
async sendRootsListChanged() {
|
|
2003
|
-
return this.notification({ method: "notifications/roots/list_changed" });
|
|
2004
|
-
}
|
|
2005
|
-
};
|
|
2006
|
-
//#endregion
|
|
2007
|
-
export { Client };
|