From 0bf7e66e98209dd5fd97dff09e8a3435e31f54aa Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Thu, 7 Nov 2024 12:57:19 +0000 Subject: [PATCH 1/3] Require `protocolVersion` to be a string now --- src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types.ts b/src/types.ts index b22e8fb2..1d8b1877 100644 --- a/src/types.ts +++ b/src/types.ts @@ -196,7 +196,7 @@ export const InitializeRequestSchema = RequestSchema.extend({ /** * The latest version of the Model Context Protocol that the client supports. The client MAY decide to support older versions as well. */ - protocolVersion: z.string().or(z.number().int()), + protocolVersion: z.string(), capabilities: ClientCapabilitiesSchema, clientInfo: ImplementationSchema, }), @@ -268,7 +268,7 @@ export const InitializeResultSchema = ResultSchema.extend({ /** * The version of the Model Context Protocol that the server wants to use. This may not match the version that the client requested. If the client cannot support this version, it MUST disconnect. */ - protocolVersion: z.string().or(z.number().int()), + protocolVersion: z.string(), capabilities: ServerCapabilitiesSchema, serverInfo: ImplementationSchema, }); From b618157c939b4f87a52833749e21939a6d3f0872 Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Thu, 7 Nov 2024 13:00:52 +0000 Subject: [PATCH 2/3] Continue allowing 2024-10-07 in version negotiation --- src/client/index.ts | 45 +++++++++++++++++++++++---------------------- src/server/index.ts | 33 +++++++++++++++------------------ src/types.ts | 3 ++- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/client/index.ts b/src/client/index.ts index 5649866a..e256b4ed 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,36 +1,37 @@ import { ProgressCallback, Protocol } from "../shared/protocol.js"; import { Transport } from "../shared/transport.js"; import { + CallToolRequest, + CallToolResultSchema, ClientNotification, ClientRequest, ClientResult, + CompleteRequest, + CompleteResultSchema, + EmptyResultSchema, + GetPromptRequest, + GetPromptResultSchema, Implementation, InitializeResultSchema, + LATEST_PROTOCOL_VERSION, + ListPromptsRequest, + ListPromptsResultSchema, + ListResourcesRequest, + ListResourcesResultSchema, + ListResourceTemplatesRequest, + ListResourceTemplatesResultSchema, + ListToolsRequest, + ListToolsResultSchema, + LoggingLevel, Notification, - PROTOCOL_VERSION, + ReadResourceRequest, + ReadResourceResultSchema, Request, Result, ServerCapabilities, - CompleteRequest, - GetPromptRequest, - ListPromptsRequest, - ListResourcesRequest, - ReadResourceRequest, SubscribeRequest, - UnsubscribeRequest, - CallToolRequest, - ListToolsRequest, - CompleteResultSchema, - GetPromptResultSchema, - ListPromptsResultSchema, - ListResourcesResultSchema, - ReadResourceResultSchema, - CallToolResultSchema, - ListToolsResultSchema, - EmptyResultSchema, - LoggingLevel, - ListResourceTemplatesRequest, - ListResourceTemplatesResultSchema, + SUPPORTED_PROTOCOL_VERSIONS, + UnsubscribeRequest } from "../types.js"; /** @@ -84,7 +85,7 @@ export class Client< { method: "initialize", params: { - protocolVersion: PROTOCOL_VERSION, + protocolVersion: LATEST_PROTOCOL_VERSION, capabilities: {}, clientInfo: this._clientInfo, }, @@ -96,7 +97,7 @@ export class Client< throw new Error(`Server sent invalid initialize result: ${result}`); } - if (result.protocolVersion !== PROTOCOL_VERSION) { + if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) { throw new Error( `Server's protocol version is not supported: ${result.protocolVersion}`, ); diff --git a/src/server/index.ts b/src/server/index.ts index dc546625..8cf2a919 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,30 +1,31 @@ import { ProgressCallback, Protocol } from "../shared/protocol.js"; import { ClientCapabilities, + CreateMessageRequest, + CreateMessageResultSchema, + EmptyResultSchema, Implementation, InitializedNotificationSchema, InitializeRequest, InitializeRequestSchema, InitializeResult, + LATEST_PROTOCOL_VERSION, + ListPromptsRequestSchema, + ListResourcesRequestSchema, + ListRootsRequest, + ListRootsResultSchema, + ListToolsRequestSchema, + LoggingMessageNotification, Notification, - PROTOCOL_VERSION, Request, + ResourceUpdatedNotification, Result, + ServerCapabilities, ServerNotification, ServerRequest, ServerResult, - ServerCapabilities, - ListResourcesRequestSchema, - ListToolsRequestSchema, - ListPromptsRequestSchema, SetLevelRequestSchema, - CreateMessageRequest, - CreateMessageResultSchema, - EmptyResultSchema, - LoggingMessageNotification, - ResourceUpdatedNotification, - ListRootsRequest, - ListRootsResultSchema, + SUPPORTED_PROTOCOL_VERSIONS } from "../types.js"; /** @@ -86,17 +87,13 @@ export class Server< private async _oninitialize( request: InitializeRequest, ): Promise { - if (request.params.protocolVersion !== PROTOCOL_VERSION) { - throw new Error( - `Client's protocol version is not supported: ${request.params.protocolVersion}`, - ); - } + const requestedVersion = request.params.protocolVersion; this._clientCapabilities = request.params.capabilities; this._clientVersion = request.params.clientInfo; return { - protocolVersion: PROTOCOL_VERSION, + protocolVersion: SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion) ? requestedVersion : LATEST_PROTOCOL_VERSION, capabilities: this.getCapabilities(), serverInfo: this._serverInfo, }; diff --git a/src/types.ts b/src/types.ts index 1d8b1877..caf05785 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,7 @@ import { z } from "zod"; -export const PROTOCOL_VERSION = "2024-11-05"; +export const LATEST_PROTOCOL_VERSION = "2024-11-05"; +export const SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, "2024-10-07"]; /* JSON-RPC types */ export const JSONRPC_VERSION = "2.0"; From 1f3dbef66c62aec3edc8aefef0545e4286cfb3d7 Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Thu, 7 Nov 2024 13:09:20 +0000 Subject: [PATCH 3/3] Support old tools/call result structure, if explicitly opted in --- src/client/index.ts | 4 +++- src/shared/protocol.ts | 4 ++-- src/types.ts | 9 +++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/client/index.ts b/src/client/index.ts index e256b4ed..c3662b29 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -6,6 +6,7 @@ import { ClientNotification, ClientRequest, ClientResult, + CompatibilityCallToolResultSchema, CompleteRequest, CompleteResultSchema, EmptyResultSchema, @@ -218,11 +219,12 @@ export class Client< async callTool( params: CallToolRequest["params"], + resultSchema: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema = CallToolResultSchema, onprogress?: ProgressCallback, ) { return this.request( { method: "tools/call", params }, - CallToolResultSchema, + resultSchema, onprogress, ); } diff --git a/src/shared/protocol.ts b/src/shared/protocol.ts index fdb117ca..22d2503f 100644 --- a/src/shared/protocol.ts +++ b/src/shared/protocol.ts @@ -1,4 +1,4 @@ -import { AnyZodObject, ZodLiteral, ZodObject, z } from "zod"; +import { ZodLiteral, ZodObject, ZodType, z } from "zod"; import { ErrorCode, JSONRPCError, @@ -250,7 +250,7 @@ export class Protocol< * * Do not use this method to emit notifications! Use notification() instead. */ - request( + request>( request: SendRequestT, resultSchema: T, onprogress?: ProgressCallback, diff --git a/src/types.ts b/src/types.ts index caf05785..f932699e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -722,6 +722,13 @@ export const CallToolResultSchema = ResultSchema.extend({ isError: z.boolean(), }); +/** + * CallToolResultSchema extended with backwards compatibility to protocol version 2024-10-07. + */ +export const CompatibilityCallToolResultSchema = CallToolResultSchema.or(ResultSchema.extend({ + toolResult: z.unknown(), +})); + /** * Used by the client to invoke a tool provided by the server. */ @@ -1054,6 +1061,7 @@ export const ServerResultSchema = z.union([ ListResourceTemplatesResultSchema, ReadResourceResultSchema, CallToolResultSchema, + CompatibilityCallToolResultSchema, ListToolsResultSchema, ]); @@ -1148,6 +1156,7 @@ export type Tool = z.infer; export type ListToolsRequest = z.infer; export type ListToolsResult = z.infer; export type CallToolResult = z.infer; +export type CompatibilityCallToolResult = z.infer; export type CallToolRequest = z.infer; export type ToolListChangedNotification = z.infer< typeof ToolListChangedNotificationSchema