tiny-stdio-mcp-server 0.1.16 → 0.1.18
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/index.d.ts +1 -1
- package/dist/server.d.ts +6 -0
- package/dist/server.js +128 -103
- package/dist/types.d.ts +1 -0
- package/dist/types.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -125,7 +125,7 @@ Dynamically add/remove tools at runtime and notify connected clients.
|
|
|
125
125
|
|
|
126
126
|
## Configuration Options
|
|
127
127
|
|
|
128
|
-
- `createServer({ name, version })`: server identity
|
|
128
|
+
- `createServer({ name, version, toolCallTimeoutMs? })`: server identity plus an optional positive-integer tool timeout in milliseconds. Timed-out calls return JSON-RPC error `-32603`; handlers continue running in the background.
|
|
129
129
|
- `.tool(name, description, schema, handler, outputSchema?)`: tool metadata, input schema, handler, and optional structured output schema.
|
|
130
130
|
- `.connect({ readable, writable })`: custom stream transport for tests or embedded hosts.
|
|
131
131
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createServer } from "./server.js";
|
|
2
|
-
export type { MessageHandler, MessageSession, Server } from "./server.js";
|
|
2
|
+
export type { CustomMethodHandler, MessageHandler, MessageSession, MessageSessionContext, Server } from "./server.js";
|
|
3
3
|
export { defineSchema } from "./schema.js";
|
|
4
4
|
export type { TypedSchema } from "./schema.js";
|
|
5
5
|
export { Image, Audio, File, toContentBlocks, fileTypeFromBuffer, DEFAULT_FROM_URL_MAX_BYTES, } from "./content/index.js";
|
package/dist/server.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface Server {
|
|
|
6
6
|
prompt(definition: Prompt, handler: PromptHandler): Server;
|
|
7
7
|
resource(definition: Resource, handler: ResourceHandler): Server;
|
|
8
8
|
resourceTemplate(definition: ResourceTemplate, handler: ResourceHandler): Server;
|
|
9
|
+
method(name: string, handler: CustomMethodHandler): Server;
|
|
9
10
|
onNotification(listener: (notification: JSONRPCNotification) => void): () => void;
|
|
10
11
|
removeTool(name: string): boolean;
|
|
11
12
|
removePrompt(name: string): boolean;
|
|
@@ -21,6 +22,11 @@ export interface Server {
|
|
|
21
22
|
connect(transport: Transport): Promise<void>;
|
|
22
23
|
connectSDK(transport: SDKTransport): Promise<void>;
|
|
23
24
|
}
|
|
25
|
+
export interface MessageSessionContext {
|
|
26
|
+
readonly signal: AbortSignal;
|
|
27
|
+
notify(method: string, params?: Record<string, unknown>): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export type CustomMethodHandler = (params: Record<string, unknown> | undefined, session: MessageSessionContext) => unknown | Promise<unknown>;
|
|
24
30
|
export type MessageHandler = (method: string, params?: Record<string, unknown>) => Promise<HandleResult>;
|
|
25
31
|
export interface MessageSession {
|
|
26
32
|
handleMessage: MessageHandler;
|
package/dist/server.js
CHANGED
|
@@ -3,15 +3,15 @@ import AjvModule from "ajv";
|
|
|
3
3
|
import uriTemplateParser from "uri-template";
|
|
4
4
|
import UriTemplate from "uri-template-lite";
|
|
5
5
|
import { JSON_RPC_ERROR_CODES, ToolError } from "./types.js";
|
|
6
|
-
import { parseMessage, formatSuccessResponse, formatErrorResponse
|
|
6
|
+
import { parseMessage, formatSuccessResponse, formatErrorResponse } from "./jsonrpc.js";
|
|
7
7
|
import { toContentBlocks } from "./content/convert.js";
|
|
8
8
|
const PROTOCOL_VERSION = "2025-11-25";
|
|
9
|
-
const SUPPORTED_PROTOCOL_VERSIONS = new Set([
|
|
10
|
-
"2025-03-26",
|
|
11
|
-
"2025-06-18",
|
|
12
|
-
PROTOCOL_VERSION,
|
|
13
|
-
]);
|
|
9
|
+
const SUPPORTED_PROTOCOL_VERSIONS = new Set(["2025-03-26", "2025-06-18", PROTOCOL_VERSION]);
|
|
14
10
|
export function createServer(options) {
|
|
11
|
+
if (options.toolCallTimeoutMs !== undefined &&
|
|
12
|
+
(!Number.isInteger(options.toolCallTimeoutMs) || options.toolCallTimeoutMs <= 0)) {
|
|
13
|
+
throw new Error("toolCallTimeoutMs must be a positive integer.");
|
|
14
|
+
}
|
|
15
15
|
const Ajv = "default" in AjvModule ? AjvModule.default : AjvModule;
|
|
16
16
|
const jsonSchemaValidator = new Ajv({ strict: false });
|
|
17
17
|
const supportNotifications = options.supportNotifications !== false;
|
|
@@ -20,6 +20,7 @@ export function createServer(options) {
|
|
|
20
20
|
const prompts = new Map();
|
|
21
21
|
const resources = new Map();
|
|
22
22
|
const resourceTemplates = new Map();
|
|
23
|
+
const methods = new Map();
|
|
23
24
|
const notificationListeners = new Set();
|
|
24
25
|
const connectionNotificationListeners = new Map();
|
|
25
26
|
const defaultLifecycle = {
|
|
@@ -27,6 +28,7 @@ export function createServer(options) {
|
|
|
27
28
|
initializeAccepted: false,
|
|
28
29
|
notificationReady: false,
|
|
29
30
|
resourceSubscriptions: new Set(),
|
|
31
|
+
abortController: new AbortController()
|
|
30
32
|
};
|
|
31
33
|
const messageLifecycles = new Set([defaultLifecycle]);
|
|
32
34
|
const handleMessageWithLifecycle = async (method, lifecycle, params) => {
|
|
@@ -43,30 +45,27 @@ export function createServer(options) {
|
|
|
43
45
|
lifecycle.initializeAccepted = true;
|
|
44
46
|
lifecycle.initialized = true;
|
|
45
47
|
lifecycle.notificationReady = false;
|
|
46
|
-
const requestedProtocol = typeof params?.protocolVersion === "string"
|
|
47
|
-
? params.protocolVersion
|
|
48
|
-
: undefined;
|
|
48
|
+
const requestedProtocol = typeof params?.protocolVersion === "string" ? params.protocolVersion : undefined;
|
|
49
49
|
const result = {
|
|
50
|
-
protocolVersion: requestedProtocol !== undefined &&
|
|
51
|
-
SUPPORTED_PROTOCOL_VERSIONS.has(requestedProtocol)
|
|
50
|
+
protocolVersion: requestedProtocol !== undefined && SUPPORTED_PROTOCOL_VERSIONS.has(requestedProtocol)
|
|
52
51
|
? requestedProtocol
|
|
53
52
|
: PROTOCOL_VERSION,
|
|
54
53
|
capabilities: {
|
|
55
54
|
tools: {
|
|
56
|
-
...(supportNotifications ? { listChanged: true } : {})
|
|
55
|
+
...(supportNotifications ? { listChanged: true } : {})
|
|
57
56
|
},
|
|
58
57
|
prompts: {
|
|
59
|
-
...(supportNotifications ? { listChanged: true } : {})
|
|
58
|
+
...(supportNotifications ? { listChanged: true } : {})
|
|
60
59
|
},
|
|
61
60
|
resources: {
|
|
62
61
|
...(supportNotifications ? { listChanged: true } : {}),
|
|
63
|
-
...(supportResourceSubscriptions ? { subscribe: true } : {})
|
|
64
|
-
}
|
|
62
|
+
...(supportResourceSubscriptions ? { subscribe: true } : {})
|
|
63
|
+
}
|
|
65
64
|
},
|
|
66
65
|
serverInfo: {
|
|
67
66
|
name: options.name,
|
|
68
|
-
version: options.version
|
|
69
|
-
}
|
|
67
|
+
version: options.version
|
|
68
|
+
}
|
|
70
69
|
};
|
|
71
70
|
return { result };
|
|
72
71
|
}
|
|
@@ -75,8 +74,8 @@ export function createServer(options) {
|
|
|
75
74
|
return {
|
|
76
75
|
error: {
|
|
77
76
|
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
78
|
-
message: "Server not initialized"
|
|
79
|
-
}
|
|
77
|
+
message: "Server not initialized"
|
|
78
|
+
}
|
|
80
79
|
};
|
|
81
80
|
}
|
|
82
81
|
lifecycle.notificationReady = true;
|
|
@@ -87,8 +86,8 @@ export function createServer(options) {
|
|
|
87
86
|
return {
|
|
88
87
|
error: {
|
|
89
88
|
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
90
|
-
message: "Server not initialized"
|
|
91
|
-
}
|
|
89
|
+
message: "Server not initialized"
|
|
90
|
+
}
|
|
92
91
|
};
|
|
93
92
|
}
|
|
94
93
|
if (method === "tools/list") {
|
|
@@ -97,10 +96,9 @@ export function createServer(options) {
|
|
|
97
96
|
const descriptor = { ...tool };
|
|
98
97
|
delete descriptor.handler;
|
|
99
98
|
delete descriptor.inputValidator;
|
|
100
|
-
delete descriptor
|
|
101
|
-
.outputValidator;
|
|
99
|
+
delete descriptor.outputValidator;
|
|
102
100
|
toolList.push({
|
|
103
|
-
...descriptor
|
|
101
|
+
...descriptor
|
|
104
102
|
});
|
|
105
103
|
}
|
|
106
104
|
return { result: { tools: toolList } };
|
|
@@ -111,8 +109,8 @@ export function createServer(options) {
|
|
|
111
109
|
return {
|
|
112
110
|
error: {
|
|
113
111
|
code: JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
114
|
-
message: "Tool name required"
|
|
115
|
-
}
|
|
112
|
+
message: "Tool name required"
|
|
113
|
+
}
|
|
116
114
|
};
|
|
117
115
|
}
|
|
118
116
|
const tool = tools.get(toolName);
|
|
@@ -120,24 +118,42 @@ export function createServer(options) {
|
|
|
120
118
|
return {
|
|
121
119
|
error: {
|
|
122
120
|
code: JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
123
|
-
message: `Tool not found: ${toolName}
|
|
124
|
-
}
|
|
121
|
+
message: `Tool not found: ${toolName}`
|
|
122
|
+
}
|
|
125
123
|
};
|
|
126
124
|
}
|
|
127
125
|
const toolArgs = (params?.arguments ?? {});
|
|
128
|
-
if (options.validateToolArguments !== false &&
|
|
129
|
-
!tool.inputValidator(toolArgs)) {
|
|
126
|
+
if (options.validateToolArguments !== false && !tool.inputValidator(toolArgs)) {
|
|
130
127
|
const errors = tool.inputValidator.errors ?? [];
|
|
131
128
|
return {
|
|
132
129
|
error: {
|
|
133
130
|
code: JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
134
131
|
message: `Invalid tool arguments: ${jsonSchemaValidator.errorsText(errors)}`,
|
|
135
|
-
data: errors
|
|
136
|
-
}
|
|
132
|
+
data: errors
|
|
133
|
+
}
|
|
137
134
|
};
|
|
138
135
|
}
|
|
139
136
|
try {
|
|
140
|
-
|
|
137
|
+
let handlerResult;
|
|
138
|
+
if (options.toolCallTimeoutMs === undefined) {
|
|
139
|
+
handlerResult = await tool.handler(toolArgs);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
let timeout;
|
|
143
|
+
const handlerPromise = Promise.resolve().then(() => tool.handler(toolArgs));
|
|
144
|
+
handlerResult = await Promise.race([
|
|
145
|
+
handlerPromise,
|
|
146
|
+
new Promise((_resolve, reject) => {
|
|
147
|
+
timeout = setTimeout(() => {
|
|
148
|
+
reject(new ToolError(JSON_RPC_ERROR_CODES.INTERNAL_ERROR, `Tool call timed out: ${toolName}`));
|
|
149
|
+
}, options.toolCallTimeoutMs);
|
|
150
|
+
})
|
|
151
|
+
]).finally(() => {
|
|
152
|
+
if (timeout !== undefined) {
|
|
153
|
+
clearTimeout(timeout);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
141
157
|
const result = normalizeToolResult(handlerResult, tool.outputSchema);
|
|
142
158
|
if (result.isError !== true &&
|
|
143
159
|
tool.outputValidator !== undefined &&
|
|
@@ -153,14 +169,14 @@ export function createServer(options) {
|
|
|
153
169
|
error: {
|
|
154
170
|
code: err.code,
|
|
155
171
|
message: err.message,
|
|
156
|
-
...(err.data === undefined ? {} : { data: err.data })
|
|
157
|
-
}
|
|
172
|
+
...(err.data === undefined ? {} : { data: err.data })
|
|
173
|
+
}
|
|
158
174
|
};
|
|
159
175
|
}
|
|
160
176
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
161
177
|
const result = {
|
|
162
178
|
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
163
|
-
isError: true
|
|
179
|
+
isError: true
|
|
164
180
|
};
|
|
165
181
|
return { result };
|
|
166
182
|
}
|
|
@@ -168,8 +184,8 @@ export function createServer(options) {
|
|
|
168
184
|
if (method === "prompts/list") {
|
|
169
185
|
return {
|
|
170
186
|
result: {
|
|
171
|
-
prompts: [...prompts.values()].map(({ handler: _handler, ...prompt }) => prompt)
|
|
172
|
-
}
|
|
187
|
+
prompts: [...prompts.values()].map(({ handler: _handler, ...prompt }) => prompt)
|
|
188
|
+
}
|
|
173
189
|
};
|
|
174
190
|
}
|
|
175
191
|
if (method === "prompts/get") {
|
|
@@ -199,15 +215,15 @@ export function createServer(options) {
|
|
|
199
215
|
if (method === "resources/list") {
|
|
200
216
|
return {
|
|
201
217
|
result: {
|
|
202
|
-
resources: [...resources.values()].map(({ handler: _handler, ...resource }) => resource)
|
|
203
|
-
}
|
|
218
|
+
resources: [...resources.values()].map(({ handler: _handler, ...resource }) => resource)
|
|
219
|
+
}
|
|
204
220
|
};
|
|
205
221
|
}
|
|
206
222
|
if (method === "resources/templates/list") {
|
|
207
223
|
return {
|
|
208
224
|
result: {
|
|
209
|
-
resourceTemplates: [...resourceTemplates.values()].map(({ handler: _handler, ...resourceTemplate }) => resourceTemplate)
|
|
210
|
-
}
|
|
225
|
+
resourceTemplates: [...resourceTemplates.values()].map(({ handler: _handler, ...resourceTemplate }) => resourceTemplate)
|
|
226
|
+
}
|
|
211
227
|
};
|
|
212
228
|
}
|
|
213
229
|
if (method === "resources/read") {
|
|
@@ -230,14 +246,13 @@ export function createServer(options) {
|
|
|
230
246
|
return internalError(toErrorMessage(error));
|
|
231
247
|
}
|
|
232
248
|
}
|
|
233
|
-
if (method === "resources/subscribe" ||
|
|
234
|
-
method === "resources/unsubscribe") {
|
|
249
|
+
if (method === "resources/subscribe" || method === "resources/unsubscribe") {
|
|
235
250
|
if (!supportResourceSubscriptions) {
|
|
236
251
|
return {
|
|
237
252
|
error: {
|
|
238
253
|
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
239
|
-
message: "Method not found"
|
|
240
|
-
}
|
|
254
|
+
message: "Method not found"
|
|
255
|
+
}
|
|
241
256
|
};
|
|
242
257
|
}
|
|
243
258
|
const uri = typeof params?.uri === "string" ? params.uri : undefined;
|
|
@@ -256,11 +271,33 @@ export function createServer(options) {
|
|
|
256
271
|
}
|
|
257
272
|
return { result: {} };
|
|
258
273
|
}
|
|
274
|
+
const customMethod = methods.get(method);
|
|
275
|
+
if (customMethod !== undefined) {
|
|
276
|
+
try {
|
|
277
|
+
const result = await customMethod(params, {
|
|
278
|
+
signal: lifecycle.abortController.signal,
|
|
279
|
+
async notify(notificationMethod, notificationParams) {
|
|
280
|
+
if (!lifecycle.notificationReady || lifecycle.listener === undefined) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
await lifecycle.listener({
|
|
284
|
+
jsonrpc: "2.0",
|
|
285
|
+
method: notificationMethod,
|
|
286
|
+
...(notificationParams === undefined ? {} : { params: notificationParams })
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
return { result };
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
return internalError(toErrorMessage(error));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
259
296
|
return {
|
|
260
297
|
error: {
|
|
261
298
|
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
262
|
-
message: "Method not found"
|
|
263
|
-
}
|
|
299
|
+
message: "Method not found"
|
|
300
|
+
}
|
|
264
301
|
};
|
|
265
302
|
};
|
|
266
303
|
const createMessageSession = (listener) => {
|
|
@@ -269,6 +306,8 @@ export function createServer(options) {
|
|
|
269
306
|
initializeAccepted: false,
|
|
270
307
|
notificationReady: false,
|
|
271
308
|
resourceSubscriptions: new Set(),
|
|
309
|
+
abortController: new AbortController(),
|
|
310
|
+
listener
|
|
272
311
|
};
|
|
273
312
|
messageLifecycles.add(lifecycle);
|
|
274
313
|
if (listener !== undefined) {
|
|
@@ -277,11 +316,12 @@ export function createServer(options) {
|
|
|
277
316
|
return {
|
|
278
317
|
handleMessage: (method, params) => handleMessageWithLifecycle(method, lifecycle, params),
|
|
279
318
|
close: () => {
|
|
319
|
+
lifecycle.abortController.abort();
|
|
280
320
|
if (listener !== undefined) {
|
|
281
321
|
connectionNotificationListeners.delete(listener);
|
|
282
322
|
}
|
|
283
323
|
messageLifecycles.delete(lifecycle);
|
|
284
|
-
}
|
|
324
|
+
}
|
|
285
325
|
};
|
|
286
326
|
};
|
|
287
327
|
const handleMessage = (method, params) => handleMessageWithLifecycle(method, defaultLifecycle, params);
|
|
@@ -299,7 +339,7 @@ export function createServer(options) {
|
|
|
299
339
|
const requestWithId = request;
|
|
300
340
|
write(formatErrorResponse(requestWithId.id, {
|
|
301
341
|
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
302
|
-
message: "Invalid Request"
|
|
342
|
+
message: "Invalid Request"
|
|
303
343
|
}) + "\n");
|
|
304
344
|
return;
|
|
305
345
|
}
|
|
@@ -312,7 +352,7 @@ export function createServer(options) {
|
|
|
312
352
|
const requestWithId = request;
|
|
313
353
|
write(formatErrorResponse(requestWithId.id, {
|
|
314
354
|
code: JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
315
|
-
message: "Internal error"
|
|
355
|
+
message: "Internal error"
|
|
316
356
|
}) + "\n");
|
|
317
357
|
}
|
|
318
358
|
return;
|
|
@@ -333,7 +373,7 @@ export function createServer(options) {
|
|
|
333
373
|
const notification = {
|
|
334
374
|
jsonrpc: "2.0",
|
|
335
375
|
method,
|
|
336
|
-
...(params === undefined ? {} : { params })
|
|
376
|
+
...(params === undefined ? {} : { params })
|
|
337
377
|
};
|
|
338
378
|
for (const listener of notificationListeners) {
|
|
339
379
|
listener(notification);
|
|
@@ -357,12 +397,10 @@ export function createServer(options) {
|
|
|
357
397
|
name,
|
|
358
398
|
description,
|
|
359
399
|
inputSchema: inputSchema,
|
|
360
|
-
...(outputSchema === undefined
|
|
361
|
-
? {}
|
|
362
|
-
: { outputSchema: outputSchema }),
|
|
400
|
+
...(outputSchema === undefined ? {} : { outputSchema: outputSchema }),
|
|
363
401
|
handler: handler,
|
|
364
402
|
inputValidator,
|
|
365
|
-
...(outputValidator === undefined ? {} : { outputValidator })
|
|
403
|
+
...(outputValidator === undefined ? {} : { outputValidator })
|
|
366
404
|
});
|
|
367
405
|
return server;
|
|
368
406
|
},
|
|
@@ -378,7 +416,7 @@ export function createServer(options) {
|
|
|
378
416
|
...definition,
|
|
379
417
|
handler: handler,
|
|
380
418
|
inputValidator,
|
|
381
|
-
...(outputValidator === undefined ? {} : { outputValidator })
|
|
419
|
+
...(outputValidator === undefined ? {} : { outputValidator })
|
|
382
420
|
});
|
|
383
421
|
return server;
|
|
384
422
|
},
|
|
@@ -400,6 +438,11 @@ export function createServer(options) {
|
|
|
400
438
|
resourceTemplates.set(definition.uriTemplate, { ...definition, handler });
|
|
401
439
|
return server;
|
|
402
440
|
},
|
|
441
|
+
method(name, handler) {
|
|
442
|
+
assertNonEmptyName(name, "Method name required");
|
|
443
|
+
methods.set(name, handler);
|
|
444
|
+
return server;
|
|
445
|
+
},
|
|
403
446
|
onNotification(listener) {
|
|
404
447
|
notificationListeners.add(listener);
|
|
405
448
|
return () => {
|
|
@@ -447,7 +490,7 @@ export function createServer(options) {
|
|
|
447
490
|
async listen() {
|
|
448
491
|
return server.connect({
|
|
449
492
|
readable: process.stdin,
|
|
450
|
-
writable: process.stdout
|
|
493
|
+
writable: process.stdout
|
|
451
494
|
});
|
|
452
495
|
},
|
|
453
496
|
async connect(transport) {
|
|
@@ -458,7 +501,7 @@ export function createServer(options) {
|
|
|
458
501
|
const session = server.createMessageSession(listener);
|
|
459
502
|
const rl = readline.createInterface({
|
|
460
503
|
input: transport.readable,
|
|
461
|
-
crlfDelay: Infinity
|
|
504
|
+
crlfDelay: Infinity
|
|
462
505
|
});
|
|
463
506
|
const pendingMessages = new Set();
|
|
464
507
|
rl.on("line", (line) => {
|
|
@@ -503,8 +546,8 @@ export function createServer(options) {
|
|
|
503
546
|
id: message.id,
|
|
504
547
|
error: {
|
|
505
548
|
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
506
|
-
message: "Invalid Request"
|
|
507
|
-
}
|
|
549
|
+
message: "Invalid Request"
|
|
550
|
+
}
|
|
508
551
|
});
|
|
509
552
|
return;
|
|
510
553
|
}
|
|
@@ -519,8 +562,8 @@ export function createServer(options) {
|
|
|
519
562
|
id: request.id,
|
|
520
563
|
error: {
|
|
521
564
|
code: JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
522
|
-
message: "Internal error"
|
|
523
|
-
}
|
|
565
|
+
message: "Internal error"
|
|
566
|
+
}
|
|
524
567
|
});
|
|
525
568
|
return;
|
|
526
569
|
}
|
|
@@ -529,7 +572,7 @@ export function createServer(options) {
|
|
|
529
572
|
const response = {
|
|
530
573
|
jsonrpc: "2.0",
|
|
531
574
|
id: request.id,
|
|
532
|
-
error
|
|
575
|
+
error
|
|
533
576
|
};
|
|
534
577
|
await transport.send(response);
|
|
535
578
|
}
|
|
@@ -537,7 +580,7 @@ export function createServer(options) {
|
|
|
537
580
|
const response = {
|
|
538
581
|
jsonrpc: "2.0",
|
|
539
582
|
id: request.id,
|
|
540
|
-
result
|
|
583
|
+
result
|
|
541
584
|
};
|
|
542
585
|
await transport.send(response);
|
|
543
586
|
}
|
|
@@ -551,7 +594,7 @@ export function createServer(options) {
|
|
|
551
594
|
reject(error);
|
|
552
595
|
});
|
|
553
596
|
});
|
|
554
|
-
}
|
|
597
|
+
}
|
|
555
598
|
};
|
|
556
599
|
return server;
|
|
557
600
|
}
|
|
@@ -559,24 +602,24 @@ function invalidParams(message) {
|
|
|
559
602
|
return {
|
|
560
603
|
error: {
|
|
561
604
|
code: JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
562
|
-
message
|
|
563
|
-
}
|
|
605
|
+
message
|
|
606
|
+
}
|
|
564
607
|
};
|
|
565
608
|
}
|
|
566
609
|
function internalError(message) {
|
|
567
610
|
return {
|
|
568
611
|
error: {
|
|
569
612
|
code: JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
570
|
-
message
|
|
571
|
-
}
|
|
613
|
+
message
|
|
614
|
+
}
|
|
572
615
|
};
|
|
573
616
|
}
|
|
574
617
|
function resourceNotFound(uri) {
|
|
575
618
|
return {
|
|
576
619
|
error: {
|
|
577
620
|
code: JSON_RPC_ERROR_CODES.RESOURCE_NOT_FOUND,
|
|
578
|
-
message: `Resource not found: ${uri}
|
|
579
|
-
}
|
|
621
|
+
message: `Resource not found: ${uri}`
|
|
622
|
+
}
|
|
580
623
|
};
|
|
581
624
|
}
|
|
582
625
|
function toErrorMessage(error) {
|
|
@@ -599,7 +642,7 @@ function assertNonEmptyName(name, message) {
|
|
|
599
642
|
function assertReadableUriTemplate(uriTemplate) {
|
|
600
643
|
const parsed = uriTemplateParser.parse(uriTemplate);
|
|
601
644
|
const expanded = parsed.expand(new Proxy({}, {
|
|
602
|
-
get: (_target, property) => typeof property === "string" ? "value" : undefined
|
|
645
|
+
get: (_target, property) => (typeof property === "string" ? "value" : undefined)
|
|
603
646
|
}));
|
|
604
647
|
if (typeof expanded !== "string" || !isValidUri(expanded)) {
|
|
605
648
|
throw new Error(`Invalid resource URI template: ${uriTemplate}`);
|
|
@@ -668,12 +711,8 @@ function normalizeToolResult(handlerResult, outputSchema) {
|
|
|
668
711
|
if (isCallToolResult(handlerResult) && handlerResult.isError === true) {
|
|
669
712
|
return handlerResult;
|
|
670
713
|
}
|
|
671
|
-
const callToolResult = isCallToolResult(handlerResult)
|
|
672
|
-
|
|
673
|
-
: undefined;
|
|
674
|
-
const structuredContent = callToolResult
|
|
675
|
-
? callToolResult.structuredContent
|
|
676
|
-
: handlerResult;
|
|
714
|
+
const callToolResult = isCallToolResult(handlerResult) ? handlerResult : undefined;
|
|
715
|
+
const structuredContent = callToolResult ? callToolResult.structuredContent : handlerResult;
|
|
677
716
|
if (!isJsonObject(structuredContent)) {
|
|
678
717
|
throw new ToolError(JSON_RPC_ERROR_CODES.INTERNAL_ERROR, "Structured tool result must be an object");
|
|
679
718
|
}
|
|
@@ -681,10 +720,8 @@ function normalizeToolResult(handlerResult, outputSchema) {
|
|
|
681
720
|
content: callToolResult !== undefined && callToolResult.content.length > 0
|
|
682
721
|
? callToolResult.content
|
|
683
722
|
: [{ type: "text", text: JSON.stringify(structuredContent) }],
|
|
684
|
-
...(callToolResult?.isError !== undefined
|
|
685
|
-
|
|
686
|
-
: {}),
|
|
687
|
-
structuredContent,
|
|
723
|
+
...(callToolResult?.isError !== undefined ? { isError: callToolResult.isError } : {}),
|
|
724
|
+
structuredContent
|
|
688
725
|
};
|
|
689
726
|
}
|
|
690
727
|
function assertObjectRootSchema(schema, path) {
|
|
@@ -696,9 +733,7 @@ function isJsonObject(value) {
|
|
|
696
733
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
697
734
|
}
|
|
698
735
|
function isGetPromptResult(value) {
|
|
699
|
-
if (typeof value !== "object" ||
|
|
700
|
-
value === null ||
|
|
701
|
-
!hasOwnProperty(value, "messages")) {
|
|
736
|
+
if (typeof value !== "object" || value === null || !hasOwnProperty(value, "messages")) {
|
|
702
737
|
return false;
|
|
703
738
|
}
|
|
704
739
|
return ((!hasOwnProperty(value, "description") ||
|
|
@@ -713,12 +748,10 @@ function isGetPromptResult(value) {
|
|
|
713
748
|
isPromptContentItem(message.content)));
|
|
714
749
|
}
|
|
715
750
|
function isReadResourceResult(value) {
|
|
716
|
-
if (typeof value !== "object" ||
|
|
717
|
-
value === null ||
|
|
718
|
-
!hasOwnProperty(value, "contents")) {
|
|
751
|
+
if (typeof value !== "object" || value === null || !hasOwnProperty(value, "contents")) {
|
|
719
752
|
return false;
|
|
720
753
|
}
|
|
721
|
-
return
|
|
754
|
+
return Array.isArray(value.contents) && value.contents.every(isResourceContents);
|
|
722
755
|
}
|
|
723
756
|
function hasContentArray(value) {
|
|
724
757
|
return (typeof value === "object" &&
|
|
@@ -727,9 +760,7 @@ function hasContentArray(value) {
|
|
|
727
760
|
Array.isArray(value.content));
|
|
728
761
|
}
|
|
729
762
|
function isContentItem(value) {
|
|
730
|
-
if (typeof value !== "object" ||
|
|
731
|
-
value === null ||
|
|
732
|
-
!hasOwnProperty(value, "type")) {
|
|
763
|
+
if (typeof value !== "object" || value === null || !hasOwnProperty(value, "type")) {
|
|
733
764
|
return false;
|
|
734
765
|
}
|
|
735
766
|
const block = value;
|
|
@@ -761,9 +792,7 @@ function isContentItem(value) {
|
|
|
761
792
|
(!hasOwnProperty(block, "mimeType") ||
|
|
762
793
|
block.mimeType === undefined ||
|
|
763
794
|
typeof block.mimeType === "string") &&
|
|
764
|
-
(!hasOwnProperty(block, "size") ||
|
|
765
|
-
block.size === undefined ||
|
|
766
|
-
typeof block.size === "number"));
|
|
795
|
+
(!hasOwnProperty(block, "size") || block.size === undefined || typeof block.size === "number"));
|
|
767
796
|
}
|
|
768
797
|
if (block.type !== "resource" ||
|
|
769
798
|
!hasOwnProperty(block, "resource") ||
|
|
@@ -787,13 +816,10 @@ function isResourceContents(value) {
|
|
|
787
816
|
return false;
|
|
788
817
|
}
|
|
789
818
|
return ((hasOwnProperty(value, "text") && typeof value.text === "string") ||
|
|
790
|
-
(hasOwnProperty(value, "blob") &&
|
|
791
|
-
typeof value.blob === "string" &&
|
|
792
|
-
isBase64(value.blob)));
|
|
819
|
+
(hasOwnProperty(value, "blob") && typeof value.blob === "string" && isBase64(value.blob)));
|
|
793
820
|
}
|
|
794
821
|
function hasValidContentAnnotations(value) {
|
|
795
|
-
if (!hasOwnProperty(value, "annotations") ||
|
|
796
|
-
value.annotations === undefined) {
|
|
822
|
+
if (!hasOwnProperty(value, "annotations") || value.annotations === undefined) {
|
|
797
823
|
return true;
|
|
798
824
|
}
|
|
799
825
|
if (!isJsonObject(value.annotations)) {
|
|
@@ -817,8 +843,7 @@ function isBase64(value) {
|
|
|
817
843
|
const paddingStart = value.indexOf("=");
|
|
818
844
|
const encoded = paddingStart === -1 ? value : value.slice(0, paddingStart);
|
|
819
845
|
const padding = paddingStart === -1 ? "" : value.slice(paddingStart);
|
|
820
|
-
if (padding.length > 2 ||
|
|
821
|
-
[...padding].some((character) => character !== "=")) {
|
|
846
|
+
if (padding.length > 2 || [...padding].some((character) => character !== "=")) {
|
|
822
847
|
return false;
|
|
823
848
|
}
|
|
824
849
|
if ([...encoded].some((character) => !alphabet.includes(character))) {
|
package/dist/types.d.ts
CHANGED
|
@@ -208,6 +208,7 @@ export interface JSONSchemaProperty extends Record<string, unknown> {
|
|
|
208
208
|
export interface ServerOptions {
|
|
209
209
|
name: string;
|
|
210
210
|
version: string;
|
|
211
|
+
toolCallTimeoutMs?: number;
|
|
211
212
|
validateToolArguments?: boolean;
|
|
212
213
|
supportNotifications?: boolean;
|
|
213
214
|
supportResourceSubscriptions?: boolean;
|
package/dist/types.js
CHANGED