@modelcontextprotocol/sdk
Advanced tools
Comparing version 0.5.0 to 0.6.0
@@ -57,3 +57,3 @@ import { Protocol, ProtocolOptions, RequestOptions } from "../shared/protocol.js"; | ||
protected assertRequestHandlerCapability(method: string): void; | ||
ping(): Promise<{ | ||
ping(options?: RequestOptions): Promise<{ | ||
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined; | ||
@@ -78,3 +78,3 @@ }>; | ||
}>, import("zod").ZodTypeAny, "passthrough">>; | ||
setLoggingLevel(level: LoggingLevel): Promise<{ | ||
setLoggingLevel(level: LoggingLevel, options?: RequestOptions): Promise<{ | ||
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined; | ||
@@ -591,6 +591,6 @@ }>; | ||
}>, import("zod").ZodTypeAny, "passthrough">>; | ||
subscribeResource(params: SubscribeRequest["params"]): Promise<{ | ||
subscribeResource(params: SubscribeRequest["params"], options?: RequestOptions): Promise<{ | ||
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined; | ||
}>; | ||
unsubscribeResource(params: UnsubscribeRequest["params"]): Promise<{ | ||
unsubscribeResource(params: UnsubscribeRequest["params"], options?: RequestOptions): Promise<{ | ||
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined; | ||
@@ -597,0 +597,0 @@ }>; |
@@ -166,4 +166,4 @@ import { Protocol, } from "../shared/protocol.js"; | ||
} | ||
async ping() { | ||
return this.request({ method: "ping" }, EmptyResultSchema); | ||
async ping(options) { | ||
return this.request({ method: "ping" }, EmptyResultSchema, options); | ||
} | ||
@@ -173,4 +173,4 @@ async complete(params, options) { | ||
} | ||
async setLoggingLevel(level) { | ||
return this.request({ method: "logging/setLevel", params: { level } }, EmptyResultSchema); | ||
async setLoggingLevel(level, options) { | ||
return this.request({ method: "logging/setLevel", params: { level } }, EmptyResultSchema, options); | ||
} | ||
@@ -192,7 +192,7 @@ async getPrompt(params, options) { | ||
} | ||
async subscribeResource(params) { | ||
return this.request({ method: "resources/subscribe", params }, EmptyResultSchema); | ||
async subscribeResource(params, options) { | ||
return this.request({ method: "resources/subscribe", params }, EmptyResultSchema, options); | ||
} | ||
async unsubscribeResource(params) { | ||
return this.request({ method: "resources/unsubscribe", params }, EmptyResultSchema); | ||
async unsubscribeResource(params, options) { | ||
return this.request({ method: "resources/unsubscribe", params }, EmptyResultSchema, options); | ||
} | ||
@@ -199,0 +199,0 @@ async callTool(params, resultSchema = CallToolResultSchema, options) { |
@@ -6,3 +6,3 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ | ||
import { z } from "zod"; | ||
import { RequestSchema, NotificationSchema, ResultSchema, LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, InitializeRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, CreateMessageRequestSchema, ListRootsRequestSchema, } from "../types.js"; | ||
import { RequestSchema, NotificationSchema, ResultSchema, LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, InitializeRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, CreateMessageRequestSchema, ListRootsRequestSchema, ErrorCode, } from "../types.js"; | ||
import { Server } from "../server/index.js"; | ||
@@ -358,2 +358,38 @@ import { InMemoryTransport } from "../inMemory.js"; | ||
}); | ||
test("should handle request timeout", async () => { | ||
const server = new Server({ | ||
name: "test server", | ||
version: "1.0", | ||
}, { | ||
capabilities: { | ||
resources: {}, | ||
}, | ||
}); | ||
// Set up server with a delayed response | ||
server.setRequestHandler(ListResourcesRequestSchema, async (_request, extra) => { | ||
const timer = new Promise((resolve) => { | ||
const timeout = setTimeout(resolve, 100); | ||
extra.signal.addEventListener("abort", () => clearTimeout(timeout)); | ||
}); | ||
await timer; | ||
return { | ||
resources: [], | ||
}; | ||
}); | ||
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); | ||
const client = new Client({ | ||
name: "test client", | ||
version: "1.0", | ||
}, { | ||
capabilities: {}, | ||
}); | ||
await Promise.all([ | ||
client.connect(clientTransport), | ||
server.connect(serverTransport), | ||
]); | ||
// Request with 0 msec timeout should fail immediately | ||
await expect(client.listResources(undefined, { timeout: 0 })).rejects.toMatchObject({ | ||
code: ErrorCode.RequestTimeout, | ||
}); | ||
}); | ||
//# sourceMappingURL=index.test.js.map |
@@ -6,3 +6,3 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ | ||
import { z } from "zod"; | ||
import { RequestSchema, NotificationSchema, ResultSchema, LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, CreateMessageRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, SetLevelRequestSchema, } from "../types.js"; | ||
import { RequestSchema, NotificationSchema, ResultSchema, LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, CreateMessageRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, SetLevelRequestSchema, ErrorCode, } from "../types.js"; | ||
import { InMemoryTransport } from "../inMemory.js"; | ||
@@ -361,2 +361,50 @@ import { Client } from "../client/index.js"; | ||
}); | ||
test("should handle request timeout", async () => { | ||
const server = new Server({ | ||
name: "test server", | ||
version: "1.0", | ||
}, { | ||
capabilities: { | ||
sampling: {}, | ||
}, | ||
}); | ||
// Set up client that delays responses | ||
const client = new Client({ | ||
name: "test client", | ||
version: "1.0", | ||
}, { | ||
capabilities: { | ||
sampling: {}, | ||
}, | ||
}); | ||
client.setRequestHandler(CreateMessageRequestSchema, async (_request, extra) => { | ||
await new Promise((resolve, reject) => { | ||
const timeout = setTimeout(resolve, 100); | ||
extra.signal.addEventListener("abort", () => { | ||
clearTimeout(timeout); | ||
reject(extra.signal.reason); | ||
}); | ||
}); | ||
return { | ||
model: "test", | ||
role: "assistant", | ||
content: { | ||
type: "text", | ||
text: "Test response", | ||
}, | ||
}; | ||
}); | ||
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); | ||
await Promise.all([ | ||
client.connect(clientTransport), | ||
server.connect(serverTransport), | ||
]); | ||
// Request with 0 msec timeout should fail immediately | ||
await expect(server.createMessage({ | ||
messages: [], | ||
maxTokens: 10, | ||
}, { timeout: 0 })).rejects.toMatchObject({ | ||
code: ErrorCode.RequestTimeout, | ||
}); | ||
}); | ||
//# sourceMappingURL=index.test.js.map |
@@ -22,2 +22,6 @@ import { ZodLiteral, ZodObject, ZodType, z } from "zod"; | ||
/** | ||
* The default request timeout, in miliseconds. | ||
*/ | ||
export declare const DEFAULT_REQUEST_TIMEOUT_MSEC = 60000; | ||
/** | ||
* Options that can be given per request. | ||
@@ -32,6 +36,10 @@ */ | ||
* Can be used to cancel an in-flight request. This will cause an AbortError to be raised from request(). | ||
*/ | ||
signal?: AbortSignal; | ||
/** | ||
* A timeout (in milliseconds) for this request. If exceeded, an McpError with code `RequestTimeout` will be raised from request(). | ||
* | ||
* Use abortAfterTimeout() to easily implement timeouts using this signal. | ||
* If not specified, `DEFAULT_REQUEST_TIMEOUT_MSEC` will be used as the timeout. | ||
*/ | ||
signal?: AbortSignal; | ||
timeout?: number; | ||
}; | ||
@@ -38,0 +46,0 @@ /** |
import { CancelledNotificationSchema, ErrorCode, McpError, PingRequestSchema, ProgressNotificationSchema, } from "../types.js"; | ||
/** | ||
* The default request timeout, in miliseconds. | ||
*/ | ||
export const DEFAULT_REQUEST_TIMEOUT_MSEC = 60000; | ||
/** | ||
* Implements MCP protocol framing on top of a pluggable transport, including | ||
@@ -173,3 +177,3 @@ * features like request/response linking, notifications, and progress. | ||
return new Promise((resolve, reject) => { | ||
var _a, _b, _c; | ||
var _a, _b, _c, _d; | ||
if (!this._transport) { | ||
@@ -196,4 +200,8 @@ reject(new Error("Not connected")); | ||
} | ||
let timeoutId = undefined; | ||
this._responseHandlers.set(messageId, (response) => { | ||
var _a; | ||
if (timeoutId !== undefined) { | ||
clearTimeout(timeoutId); | ||
} | ||
if ((_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.aborted) { | ||
@@ -213,8 +221,7 @@ return; | ||
}); | ||
(_c = options === null || options === void 0 ? void 0 : options.signal) === null || _c === void 0 ? void 0 : _c.addEventListener("abort", () => { | ||
var _a, _b; | ||
const reason = (_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.reason; | ||
const cancel = (reason) => { | ||
var _a; | ||
this._responseHandlers.delete(messageId); | ||
this._progressHandlers.delete(messageId); | ||
(_b = this._transport) === null || _b === void 0 ? void 0 : _b.send({ | ||
(_a = this._transport) === null || _a === void 0 ? void 0 : _a.send({ | ||
jsonrpc: "2.0", | ||
@@ -226,6 +233,22 @@ method: "cancelled", | ||
}, | ||
}); | ||
}).catch((error) => this._onerror(new Error(`Failed to send cancellation: ${error}`))); | ||
reject(reason); | ||
}; | ||
(_c = options === null || options === void 0 ? void 0 : options.signal) === null || _c === void 0 ? void 0 : _c.addEventListener("abort", () => { | ||
var _a; | ||
if (timeoutId !== undefined) { | ||
clearTimeout(timeoutId); | ||
} | ||
cancel((_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.reason); | ||
}); | ||
this._transport.send(jsonrpcRequest).catch(reject); | ||
const timeout = (_d = options === null || options === void 0 ? void 0 : options.timeout) !== null && _d !== void 0 ? _d : DEFAULT_REQUEST_TIMEOUT_MSEC; | ||
timeoutId = setTimeout(() => cancel(new McpError(ErrorCode.RequestTimeout, "Request timed out", { | ||
timeout, | ||
})), timeout); | ||
this._transport.send(jsonrpcRequest).catch((error) => { | ||
if (timeoutId !== undefined) { | ||
clearTimeout(timeoutId); | ||
} | ||
reject(error); | ||
}); | ||
}); | ||
@@ -232,0 +255,0 @@ } |
@@ -93,2 +93,3 @@ import { z } from "zod"; | ||
ErrorCode[ErrorCode["ConnectionClosed"] = -1] = "ConnectionClosed"; | ||
ErrorCode[ErrorCode["RequestTimeout"] = -2] = "RequestTimeout"; | ||
// Standard JSON-RPC error codes | ||
@@ -95,0 +96,0 @@ ErrorCode[ErrorCode["ParseError"] = -32700] = "ParseError"; |
{ | ||
"name": "@modelcontextprotocol/sdk", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Model Context Protocol implementation for TypeScript", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -1,2 +0,2 @@ | ||
# MCP TypeScript SDK | ||
# MCP TypeScript SDK ![NPM Version](https://img.shields.io/npm/v/%40modelcontextprotocol%2Fsdk) | ||
@@ -3,0 +3,0 @@ TypeScript implementation of the Model Context Protocol (MCP), providing both client and server capabilities for integrating with LLM surfaces. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1659551
31788
79