From 4b94617928c892a7bfc05a52473c9261a104d392 Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Thu, 18 Sep 2025 00:02:39 +0300 Subject: [PATCH 1/7] Icons type as per SEP-973, spec types test improvements, ImplementationSchema use IconsSchema --- src/spec.types.test.ts | 993 +++++++++++++++-------------------------- src/types.ts | 24 +- 2 files changed, 382 insertions(+), 635 deletions(-) diff --git a/src/spec.types.test.ts b/src/spec.types.test.ts index 5aa497f4a..e8db9907f 100644 --- a/src/spec.types.test.ts +++ b/src/spec.types.test.ts @@ -53,622 +53,363 @@ type MakeUnknownsNotOptional = })) : T); -function checkCancelledNotification( - sdk: WithJSONRPC, - spec: SpecTypes.CancelledNotification -) { - sdk = spec; - spec = sdk; -} -function checkBaseMetadata( - sdk: RemovePassthrough, - spec: SpecTypes.BaseMetadata -) { - sdk = spec; - spec = sdk; -} -function checkImplementation( - sdk: RemovePassthrough, - spec: SpecTypes.Implementation -) { - sdk = spec; - spec = sdk; -} -function checkProgressNotification( - sdk: WithJSONRPC, - spec: SpecTypes.ProgressNotification -) { - sdk = spec; - spec = sdk; -} - -function checkSubscribeRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.SubscribeRequest -) { - sdk = spec; - spec = sdk; -} -function checkUnsubscribeRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.UnsubscribeRequest -) { - sdk = spec; - spec = sdk; -} -function checkPaginatedRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.PaginatedRequest -) { - sdk = spec; - spec = sdk; -} -function checkPaginatedResult( - sdk: SDKTypes.PaginatedResult, - spec: SpecTypes.PaginatedResult -) { - sdk = spec; - spec = sdk; -} -function checkListRootsRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.ListRootsRequest -) { - sdk = spec; - spec = sdk; -} -function checkListRootsResult( - sdk: RemovePassthrough, - spec: SpecTypes.ListRootsResult -) { - sdk = spec; - spec = sdk; -} -function checkRoot( - sdk: RemovePassthrough, - spec: SpecTypes.Root -) { - sdk = spec; - spec = sdk; -} -function checkElicitRequest( - sdk: WithJSONRPCRequest>, - spec: SpecTypes.ElicitRequest -) { - sdk = spec; - spec = sdk; -} -function checkElicitResult( - sdk: RemovePassthrough, - spec: SpecTypes.ElicitResult -) { - sdk = spec; - spec = sdk; -} -function checkCompleteRequest( - sdk: WithJSONRPCRequest>, - spec: SpecTypes.CompleteRequest -) { - sdk = spec; - spec = sdk; -} -function checkCompleteResult( - sdk: SDKTypes.CompleteResult, - spec: SpecTypes.CompleteResult -) { - sdk = spec; - spec = sdk; -} -function checkProgressToken( - sdk: SDKTypes.ProgressToken, - spec: SpecTypes.ProgressToken -) { - sdk = spec; - spec = sdk; -} -function checkCursor( - sdk: SDKTypes.Cursor, - spec: SpecTypes.Cursor -) { - sdk = spec; - spec = sdk; -} -function checkRequest( - sdk: SDKTypes.Request, - spec: SpecTypes.Request -) { - sdk = spec; - spec = sdk; -} -function checkResult( - sdk: SDKTypes.Result, - spec: SpecTypes.Result -) { - sdk = spec; - spec = sdk; -} -function checkRequestId( - sdk: SDKTypes.RequestId, - spec: SpecTypes.RequestId -) { - sdk = spec; - spec = sdk; -} -function checkJSONRPCRequest( - sdk: SDKTypes.JSONRPCRequest, - spec: SpecTypes.JSONRPCRequest -) { - sdk = spec; - spec = sdk; -} -function checkJSONRPCNotification( - sdk: SDKTypes.JSONRPCNotification, - spec: SpecTypes.JSONRPCNotification -) { - sdk = spec; - spec = sdk; -} -function checkJSONRPCResponse( - sdk: SDKTypes.JSONRPCResponse, - spec: SpecTypes.JSONRPCResponse -) { - sdk = spec; - spec = sdk; -} -function checkEmptyResult( - sdk: SDKTypes.EmptyResult, - spec: SpecTypes.EmptyResult -) { - sdk = spec; - spec = sdk; -} -function checkNotification( - sdk: SDKTypes.Notification, - spec: SpecTypes.Notification -) { - sdk = spec; - spec = sdk; -} -function checkClientResult( - sdk: SDKTypes.ClientResult, - spec: SpecTypes.ClientResult -) { - sdk = spec; - spec = sdk; -} -function checkClientNotification( - sdk: WithJSONRPC, - spec: SpecTypes.ClientNotification -) { - sdk = spec; - spec = sdk; -} -function checkServerResult( - sdk: SDKTypes.ServerResult, - spec: SpecTypes.ServerResult -) { - sdk = spec; - spec = sdk; -} -function checkResourceTemplateReference( - sdk: RemovePassthrough, - spec: SpecTypes.ResourceTemplateReference -) { - sdk = spec; - spec = sdk; -} -function checkPromptReference( - sdk: RemovePassthrough, - spec: SpecTypes.PromptReference -) { - sdk = spec; - spec = sdk; -} -function checkToolAnnotations( - sdk: RemovePassthrough, - spec: SpecTypes.ToolAnnotations -) { - sdk = spec; - spec = sdk; -} -function checkTool( - sdk: RemovePassthrough, - spec: SpecTypes.Tool -) { - sdk = spec; - spec = sdk; -} -function checkListToolsRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.ListToolsRequest -) { - sdk = spec; - spec = sdk; -} -function checkListToolsResult( - sdk: RemovePassthrough, - spec: SpecTypes.ListToolsResult -) { - sdk = spec; - spec = sdk; -} -function checkCallToolResult( - sdk: RemovePassthrough, - spec: SpecTypes.CallToolResult -) { - sdk = spec; - spec = sdk; -} -function checkCallToolRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.CallToolRequest -) { - sdk = spec; - spec = sdk; -} -function checkToolListChangedNotification( - sdk: WithJSONRPC, - spec: SpecTypes.ToolListChangedNotification -) { - sdk = spec; - spec = sdk; -} -function checkResourceListChangedNotification( - sdk: WithJSONRPC, - spec: SpecTypes.ResourceListChangedNotification -) { - sdk = spec; - spec = sdk; -} -function checkPromptListChangedNotification( - sdk: WithJSONRPC, - spec: SpecTypes.PromptListChangedNotification -) { - sdk = spec; - spec = sdk; -} -function checkRootsListChangedNotification( - sdk: WithJSONRPC, - spec: SpecTypes.RootsListChangedNotification -) { - sdk = spec; - spec = sdk; -} -function checkResourceUpdatedNotification( - sdk: WithJSONRPC, - spec: SpecTypes.ResourceUpdatedNotification -) { - sdk = spec; - spec = sdk; -} -function checkSamplingMessage( - sdk: RemovePassthrough, - spec: SpecTypes.SamplingMessage -) { - sdk = spec; - spec = sdk; -} -function checkCreateMessageResult( - sdk: RemovePassthrough, - spec: SpecTypes.CreateMessageResult -) { - sdk = spec; - spec = sdk; -} -function checkSetLevelRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.SetLevelRequest -) { - sdk = spec; - spec = sdk; -} -function checkPingRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.PingRequest -) { - sdk = spec; - spec = sdk; -} -function checkInitializedNotification( - sdk: WithJSONRPC, - spec: SpecTypes.InitializedNotification -) { - sdk = spec; - spec = sdk; -} -function checkListResourcesRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.ListResourcesRequest -) { - sdk = spec; - spec = sdk; -} -function checkListResourcesResult( - sdk: RemovePassthrough, - spec: SpecTypes.ListResourcesResult -) { - sdk = spec; - spec = sdk; -} -function checkListResourceTemplatesRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.ListResourceTemplatesRequest -) { - sdk = spec; - spec = sdk; -} -function checkListResourceTemplatesResult( - sdk: RemovePassthrough, - spec: SpecTypes.ListResourceTemplatesResult -) { - sdk = spec; - spec = sdk; -} -function checkReadResourceRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.ReadResourceRequest -) { - sdk = spec; - spec = sdk; -} -function checkReadResourceResult( - sdk: RemovePassthrough, - spec: SpecTypes.ReadResourceResult -) { - sdk = spec; - spec = sdk; -} -function checkResourceContents( - sdk: RemovePassthrough, - spec: SpecTypes.ResourceContents -) { - sdk = spec; - spec = sdk; -} -function checkTextResourceContents( - sdk: RemovePassthrough, - spec: SpecTypes.TextResourceContents -) { - sdk = spec; - spec = sdk; -} -function checkBlobResourceContents( - sdk: RemovePassthrough, - spec: SpecTypes.BlobResourceContents -) { - sdk = spec; - spec = sdk; -} -function checkResource( - sdk: RemovePassthrough, - spec: SpecTypes.Resource -) { - sdk = spec; - spec = sdk; -} -function checkResourceTemplate( - sdk: RemovePassthrough, - spec: SpecTypes.ResourceTemplate -) { - sdk = spec; - spec = sdk; -} -function checkPromptArgument( - sdk: RemovePassthrough, - spec: SpecTypes.PromptArgument -) { - sdk = spec; - spec = sdk; -} -function checkPrompt( - sdk: RemovePassthrough, - spec: SpecTypes.Prompt -) { - sdk = spec; - spec = sdk; -} -function checkListPromptsRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.ListPromptsRequest -) { - sdk = spec; - spec = sdk; -} -function checkListPromptsResult( - sdk: RemovePassthrough, - spec: SpecTypes.ListPromptsResult -) { - sdk = spec; - spec = sdk; -} -function checkGetPromptRequest( - sdk: WithJSONRPCRequest, - spec: SpecTypes.GetPromptRequest -) { - sdk = spec; - spec = sdk; -} -function checkTextContent( - sdk: RemovePassthrough, - spec: SpecTypes.TextContent -) { - sdk = spec; - spec = sdk; -} -function checkImageContent( - sdk: RemovePassthrough, - spec: SpecTypes.ImageContent -) { - sdk = spec; - spec = sdk; -} -function checkAudioContent( - sdk: RemovePassthrough, - spec: SpecTypes.AudioContent -) { - sdk = spec; - spec = sdk; -} -function checkEmbeddedResource( - sdk: RemovePassthrough, - spec: SpecTypes.EmbeddedResource -) { - sdk = spec; - spec = sdk; -} -function checkResourceLink( - sdk: RemovePassthrough, - spec: SpecTypes.ResourceLink -) { - sdk = spec; - spec = sdk; -} -function checkContentBlock( - sdk: RemovePassthrough, - spec: SpecTypes.ContentBlock -) { - sdk = spec; - spec = sdk; -} -function checkPromptMessage( - sdk: RemovePassthrough, - spec: SpecTypes.PromptMessage -) { - sdk = spec; - spec = sdk; -} -function checkGetPromptResult( - sdk: RemovePassthrough, - spec: SpecTypes.GetPromptResult -) { - sdk = spec; - spec = sdk; -} -function checkBooleanSchema( - sdk: RemovePassthrough, - spec: SpecTypes.BooleanSchema -) { - sdk = spec; - spec = sdk; -} -function checkStringSchema( - sdk: RemovePassthrough, - spec: SpecTypes.StringSchema -) { - sdk = spec; - spec = sdk; -} -function checkNumberSchema( - sdk: RemovePassthrough, - spec: SpecTypes.NumberSchema -) { - sdk = spec; - spec = sdk; -} -function checkEnumSchema( - sdk: RemovePassthrough, - spec: SpecTypes.EnumSchema -) { - sdk = spec; - spec = sdk; -} -function checkPrimitiveSchemaDefinition( - sdk: RemovePassthrough, - spec: SpecTypes.PrimitiveSchemaDefinition -) { - sdk = spec; - spec = sdk; -} -function checkJSONRPCError( - sdk: SDKTypes.JSONRPCError, - spec: SpecTypes.JSONRPCError -) { - sdk = spec; - spec = sdk; -} -function checkJSONRPCMessage( - sdk: SDKTypes.JSONRPCMessage, - spec: SpecTypes.JSONRPCMessage -) { - sdk = spec; - spec = sdk; -} -function checkCreateMessageRequest( - sdk: WithJSONRPCRequest>, - spec: SpecTypes.CreateMessageRequest -) { - sdk = spec; - spec = sdk; -} -function checkInitializeRequest( - sdk: WithJSONRPCRequest>, - spec: SpecTypes.InitializeRequest -) { - sdk = spec; - spec = sdk; -} -function checkInitializeResult( - sdk: RemovePassthrough, - spec: SpecTypes.InitializeResult -) { - sdk = spec; - spec = sdk; -} -function checkClientCapabilities( - sdk: RemovePassthrough, - spec: SpecTypes.ClientCapabilities -) { - sdk = spec; - spec = sdk; -} -function checkServerCapabilities( - sdk: RemovePassthrough, - spec: SpecTypes.ServerCapabilities -) { - sdk = spec; - spec = sdk; -} -function checkClientRequest( - sdk: WithJSONRPCRequest>, - spec: SpecTypes.ClientRequest -) { - sdk = spec; - spec = sdk; -} -function checkServerRequest( - sdk: WithJSONRPCRequest>, - spec: SpecTypes.ServerRequest -) { - sdk = spec; - spec = sdk; -} -function checkLoggingMessageNotification( - sdk: MakeUnknownsNotOptional>, - spec: SpecTypes.LoggingMessageNotification -) { - sdk = spec; - spec = sdk; -} -function checkServerNotification( - sdk: MakeUnknownsNotOptional>, - spec: SpecTypes.ServerNotification -) { - sdk = spec; - spec = sdk; -} -function checkLoggingLevel( - sdk: SDKTypes.LoggingLevel, - spec: SpecTypes.LoggingLevel -) { - sdk = spec; - spec = sdk; -} -function checkIcon( - sdk: RemovePassthrough, - spec: SpecTypes.Icon -) { - sdk = spec; - spec = sdk; +const sdkTypeChecks = { + CancelledNotification: (sdk: WithJSONRPC, spec: SpecTypes.CancelledNotification) => { + sdk = spec; + spec = sdk; + }, + BaseMetadata: (sdk: RemovePassthrough, spec: SpecTypes.BaseMetadata) => { + sdk = spec; + spec = sdk; + }, + Implementation: (sdk: RemovePassthrough, spec: SpecTypes.Implementation) => { + sdk = spec; + spec = sdk; + }, + ProgressNotification: (sdk: WithJSONRPC, spec: SpecTypes.ProgressNotification) => { + sdk = spec; + spec = sdk; + }, + SubscribeRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.SubscribeRequest) => { + sdk = spec; + spec = sdk; + }, + UnsubscribeRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.UnsubscribeRequest) => { + sdk = spec; + spec = sdk; + }, + PaginatedRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.PaginatedRequest) => { + sdk = spec; + spec = sdk; + }, + PaginatedResult: (sdk: SDKTypes.PaginatedResult, spec: SpecTypes.PaginatedResult) => { + sdk = spec; + spec = sdk; + }, + ListRootsRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListRootsRequest) => { + sdk = spec; + spec = sdk; + }, + ListRootsResult: (sdk: RemovePassthrough, spec: SpecTypes.ListRootsResult) => { + sdk = spec; + spec = sdk; + }, + Root: (sdk: RemovePassthrough, spec: SpecTypes.Root) => { + sdk = spec; + spec = sdk; + }, + ElicitRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.ElicitRequest) => { + sdk = spec; + spec = sdk; + }, + ElicitResult: (sdk: RemovePassthrough, spec: SpecTypes.ElicitResult) => { + sdk = spec; + spec = sdk; + }, + CompleteRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.CompleteRequest) => { + sdk = spec; + spec = sdk; + }, + CompleteResult: (sdk: SDKTypes.CompleteResult, spec: SpecTypes.CompleteResult) => { + sdk = spec; + spec = sdk; + }, + ProgressToken: (sdk: SDKTypes.ProgressToken, spec: SpecTypes.ProgressToken) => { + sdk = spec; + spec = sdk; + }, + Cursor: (sdk: SDKTypes.Cursor, spec: SpecTypes.Cursor) => { + sdk = spec; + spec = sdk; + }, + Request: (sdk: SDKTypes.Request, spec: SpecTypes.Request) => { + sdk = spec; + spec = sdk; + }, + Result: (sdk: SDKTypes.Result, spec: SpecTypes.Result) => { + sdk = spec; + spec = sdk; + }, + RequestId: (sdk: SDKTypes.RequestId, spec: SpecTypes.RequestId) => { + sdk = spec; + spec = sdk; + }, + JSONRPCRequest: (sdk: SDKTypes.JSONRPCRequest, spec: SpecTypes.JSONRPCRequest) => { + sdk = spec; + spec = sdk; + }, + JSONRPCNotification: (sdk: SDKTypes.JSONRPCNotification, spec: SpecTypes.JSONRPCNotification) => { + sdk = spec; + spec = sdk; + }, + JSONRPCResponse: (sdk: SDKTypes.JSONRPCResponse, spec: SpecTypes.JSONRPCResponse) => { + sdk = spec; + spec = sdk; + }, + EmptyResult: (sdk: SDKTypes.EmptyResult, spec: SpecTypes.EmptyResult) => { + sdk = spec; + spec = sdk; + }, + Notification: (sdk: SDKTypes.Notification, spec: SpecTypes.Notification) => { + sdk = spec; + spec = sdk; + }, + ClientResult: (sdk: SDKTypes.ClientResult, spec: SpecTypes.ClientResult) => { + sdk = spec; + spec = sdk; + }, + ClientNotification: (sdk: WithJSONRPC, spec: SpecTypes.ClientNotification) => { + sdk = spec; + spec = sdk; + }, + ServerResult: (sdk: SDKTypes.ServerResult, spec: SpecTypes.ServerResult) => { + sdk = spec; + spec = sdk; + }, + ResourceTemplateReference: (sdk: RemovePassthrough, spec: SpecTypes.ResourceTemplateReference) => { + sdk = spec; + spec = sdk; + }, + PromptReference: (sdk: RemovePassthrough, spec: SpecTypes.PromptReference) => { + sdk = spec; + spec = sdk; + }, + ToolAnnotations: (sdk: RemovePassthrough, spec: SpecTypes.ToolAnnotations) => { + sdk = spec; + spec = sdk; + }, + Tool: (sdk: RemovePassthrough, spec: SpecTypes.Tool) => { + sdk = spec; + spec = sdk; + }, + ListToolsRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListToolsRequest) => { + sdk = spec; + spec = sdk; + }, + ListToolsResult: (sdk: RemovePassthrough, spec: SpecTypes.ListToolsResult) => { + sdk = spec; + spec = sdk; + }, + CallToolResult: (sdk: RemovePassthrough, spec: SpecTypes.CallToolResult) => { + sdk = spec; + spec = sdk; + }, + CallToolRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.CallToolRequest) => { + sdk = spec; + spec = sdk; + }, + ToolListChangedNotification: (sdk: WithJSONRPC, spec: SpecTypes.ToolListChangedNotification) => { + sdk = spec; + spec = sdk; + }, + ResourceListChangedNotification: (sdk: WithJSONRPC, spec: SpecTypes.ResourceListChangedNotification) => { + sdk = spec; + spec = sdk; + }, + PromptListChangedNotification: (sdk: WithJSONRPC, spec: SpecTypes.PromptListChangedNotification) => { + sdk = spec; + spec = sdk; + }, + RootsListChangedNotification: (sdk: WithJSONRPC, spec: SpecTypes.RootsListChangedNotification) => { + sdk = spec; + spec = sdk; + }, + ResourceUpdatedNotification: (sdk: WithJSONRPC, spec: SpecTypes.ResourceUpdatedNotification) => { + sdk = spec; + spec = sdk; + }, + SamplingMessage: (sdk: RemovePassthrough, spec: SpecTypes.SamplingMessage) => { + sdk = spec; + spec = sdk; + }, + CreateMessageResult: (sdk: RemovePassthrough, spec: SpecTypes.CreateMessageResult) => { + sdk = spec; + spec = sdk; + }, + SetLevelRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.SetLevelRequest) => { + sdk = spec; + spec = sdk; + }, + PingRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.PingRequest) => { + sdk = spec; + spec = sdk; + }, + InitializedNotification: (sdk: WithJSONRPC, spec: SpecTypes.InitializedNotification) => { + sdk = spec; + spec = sdk; + }, + ListResourcesRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListResourcesRequest) => { + sdk = spec; + spec = sdk; + }, + ListResourcesResult: (sdk: RemovePassthrough, spec: SpecTypes.ListResourcesResult) => { + sdk = spec; + spec = sdk; + }, + ListResourceTemplatesRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListResourceTemplatesRequest) => { + sdk = spec; + spec = sdk; + }, + ListResourceTemplatesResult: (sdk: RemovePassthrough, spec: SpecTypes.ListResourceTemplatesResult) => { + sdk = spec; + spec = sdk; + }, + ReadResourceRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ReadResourceRequest) => { + sdk = spec; + spec = sdk; + }, + ReadResourceResult: (sdk: RemovePassthrough, spec: SpecTypes.ReadResourceResult) => { + sdk = spec; + spec = sdk; + }, + ResourceContents: (sdk: RemovePassthrough, spec: SpecTypes.ResourceContents) => { + sdk = spec; + spec = sdk; + }, + TextResourceContents: (sdk: RemovePassthrough, spec: SpecTypes.TextResourceContents) => { + sdk = spec; + spec = sdk; + }, + BlobResourceContents: (sdk: RemovePassthrough, spec: SpecTypes.BlobResourceContents) => { + sdk = spec; + spec = sdk; + }, + Resource: (sdk: RemovePassthrough, spec: SpecTypes.Resource) => { + sdk = spec; + spec = sdk; + }, + ResourceTemplate: (sdk: RemovePassthrough, spec: SpecTypes.ResourceTemplate) => { + sdk = spec; + spec = sdk; + }, + PromptArgument: (sdk: RemovePassthrough, spec: SpecTypes.PromptArgument) => { + sdk = spec; + spec = sdk; + }, + Prompt: (sdk: RemovePassthrough, spec: SpecTypes.Prompt) => { + sdk = spec; + spec = sdk; + }, + ListPromptsRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListPromptsRequest) => { + sdk = spec; + spec = sdk; + }, + ListPromptsResult: (sdk: RemovePassthrough, spec: SpecTypes.ListPromptsResult) => { + sdk = spec; + spec = sdk; + }, + GetPromptRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.GetPromptRequest) => { + sdk = spec; + spec = sdk; + }, + TextContent: (sdk: RemovePassthrough, spec: SpecTypes.TextContent) => { + sdk = spec; + spec = sdk; + }, + ImageContent: (sdk: RemovePassthrough, spec: SpecTypes.ImageContent) => { + sdk = spec; + spec = sdk; + }, + AudioContent: (sdk: RemovePassthrough, spec: SpecTypes.AudioContent) => { + sdk = spec; + spec = sdk; + }, + EmbeddedResource: (sdk: RemovePassthrough, spec: SpecTypes.EmbeddedResource) => { + sdk = spec; + spec = sdk; + }, + ResourceLink: (sdk: RemovePassthrough, spec: SpecTypes.ResourceLink) => { + sdk = spec; + spec = sdk; + }, + ContentBlock: (sdk: RemovePassthrough, spec: SpecTypes.ContentBlock) => { + sdk = spec; + spec = sdk; + }, + PromptMessage: (sdk: RemovePassthrough, spec: SpecTypes.PromptMessage) => { + sdk = spec; + spec = sdk; + }, + GetPromptResult: (sdk: RemovePassthrough, spec: SpecTypes.GetPromptResult) => { + sdk = spec; + spec = sdk; + }, + BooleanSchema: (sdk: RemovePassthrough, spec: SpecTypes.BooleanSchema) => { + sdk = spec; + spec = sdk; + }, + StringSchema: (sdk: RemovePassthrough, spec: SpecTypes.StringSchema) => { + sdk = spec; + spec = sdk; + }, + NumberSchema: (sdk: RemovePassthrough, spec: SpecTypes.NumberSchema) => { + sdk = spec; + spec = sdk; + }, + EnumSchema: (sdk: RemovePassthrough, spec: SpecTypes.EnumSchema) => { + sdk = spec; + spec = sdk; + }, + PrimitiveSchemaDefinition: (sdk: RemovePassthrough, spec: SpecTypes.PrimitiveSchemaDefinition) => { + sdk = spec; + spec = sdk; + }, + JSONRPCError: (sdk: SDKTypes.JSONRPCError, spec: SpecTypes.JSONRPCError) => { + sdk = spec; + spec = sdk; + }, + JSONRPCMessage: (sdk: SDKTypes.JSONRPCMessage, spec: SpecTypes.JSONRPCMessage) => { + sdk = spec; + spec = sdk; + }, + CreateMessageRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.CreateMessageRequest) => { + sdk = spec; + spec = sdk; + }, + InitializeRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.InitializeRequest) => { + sdk = spec; + spec = sdk; + }, + InitializeResult: (sdk: RemovePassthrough, spec: SpecTypes.InitializeResult) => { + sdk = spec; + spec = sdk; + }, + ClientCapabilities: (sdk: RemovePassthrough, spec: SpecTypes.ClientCapabilities) => { + sdk = spec; + spec = sdk; + }, + ServerCapabilities: (sdk: RemovePassthrough, spec: SpecTypes.ServerCapabilities) => { + sdk = spec; + spec = sdk; + }, + ClientRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.ClientRequest) => { + sdk = spec; + spec = sdk; + }, + ServerRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.ServerRequest) => { + sdk = spec; + spec = sdk; + }, + LoggingMessageNotification: (sdk: MakeUnknownsNotOptional>, spec: SpecTypes.LoggingMessageNotification) => { + sdk = spec; + spec = sdk; + }, + ServerNotification: (sdk: MakeUnknownsNotOptional>, spec: SpecTypes.ServerNotification) => { + sdk = spec; + spec = sdk; + }, + LoggingLevel: (sdk: SDKTypes.LoggingLevel, spec: SpecTypes.LoggingLevel) => { + sdk = spec; + spec = sdk; + }, + Icon: (sdk: RemovePassthrough, spec: SpecTypes.Icon) => { + sdk = spec; + spec = sdk; + }, + Icons: (sdk: RemovePassthrough, spec: SpecTypes.Icons) => { + sdk = spec; + spec = sdk; + } } // This file is .gitignore'd, and fetched by `npm run fetch:spec-types` (called by `npm run test`) @@ -685,7 +426,6 @@ const MISSING_SDK_TYPES = [ 'Annotations', 'ModelHint', 'ModelPreferences', - 'Icons', ] function extractExportedTypes(source: string): string[] { @@ -695,7 +435,7 @@ function extractExportedTypes(source: string): string[] { describe('Spec Types', () => { const specTypes = extractExportedTypes(fs.readFileSync(SPEC_TYPES_FILE, 'utf-8')); const sdkTypes = extractExportedTypes(fs.readFileSync(SDK_TYPES_FILE, 'utf-8')); - const testSource = fs.readFileSync(__filename, 'utf-8'); + const typesToCheck = specTypes.filter(type => !MISSING_SDK_TYPES.includes(type)); it('should define some expected types', () => { expect(specTypes).toContain('JSONRPCNotification'); @@ -709,12 +449,15 @@ describe('Spec Types', () => { } }); - for (const type of specTypes) { - if (MISSING_SDK_TYPES.includes(type)) { - continue; // Skip missing SDK types - } - it(`${type} should have a compatibility test`, () => { - expect(testSource).toContain(`function check${type}(`); + describe('Compatibility tests', () => { + it.each(typesToCheck)('%s should have a compatibility test', (type) => { + expect(sdkTypeChecks[type as keyof typeof sdkTypeChecks]).toBeDefined(); + }); + }); + + describe('Missing SDK Types', () => { + it.each(MISSING_SDK_TYPES)('%s should not be present in MISSING_SDK_TYPES if it has a compatibility test', (type) => { + expect(sdkTypeChecks[type as keyof typeof sdkTypeChecks]).toBeUndefined(); }); - } + }); }); diff --git a/src/types.ts b/src/types.ts index 262e3b623..26ab0e24d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -220,6 +220,18 @@ export const IconSchema = z }) .passthrough(); +/** + * An optional list of icons for this implementation. + * This can be used by clients to display the implementation in a user interface. + * Each icon should have a `kind` property that specifies whether it is a data representation or a URL source, a `src` property that points to the icon file or data representation, and may also include a `mimeType` and `sizes` property. + * The `mimeType` property should be a valid MIME type for the icon file, such as "image/png" or "image/svg+xml". + * The `sizes` property should be a string that specifies one or more sizes at which the icon file can be used, such as "48x48" or "any" for scalable formats like SVG. + * The `sizes` property is optional, and if not provided, the client should assume that the icon can be used at any size. + */ +export const IconsSchema = z.object({ + icons: z.array(IconSchema).optional(), +}).passthrough(); + /** * Base metadata interface for common properties across resources, tools, prompts, and implementations. */ @@ -249,16 +261,7 @@ export const ImplementationSchema = BaseMetadataSchema.extend({ * An optional URL of the website for this implementation. */ websiteUrl: z.optional(z.string()), - /** - * An optional list of icons for this implementation. - * This can be used by clients to display the implementation in a user interface. - * Each icon should have a `kind` property that specifies whether it is a data representation or a URL source, a `src` property that points to the icon file or data representation, and may also include a `mimeType` and `sizes` property. - * The `mimeType` property should be a valid MIME type for the icon file, such as "image/png" or "image/svg+xml". - * The `sizes` property should be a string that specifies one or more sizes at which the icon file can be used, such as "48x48" or "any" for scalable formats like SVG. - * The `sizes` property is optional, and if not provided, the client should assume that the icon can be used at any size. - */ - icons: z.optional(z.array(IconSchema)), -}); +}).merge(IconsSchema); /** * Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities. @@ -1583,6 +1586,7 @@ export type CancelledNotification = Infer; /* Base Metadata */ export type Icon = Infer; +export type Icons = Infer; export type BaseMetadata = Infer; /* Initialization */ From c041fa6e16a0c1e68ef351062b05c6608c865f72 Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Thu, 18 Sep 2025 16:45:33 +0300 Subject: [PATCH 2/7] prettier format, IconsSchema strip instead of passthrough --- src/spec.types.test.ts | 515 +++++++++++++++++++++++++++++++---------- src/types.ts | 2 +- 2 files changed, 389 insertions(+), 128 deletions(-) diff --git a/src/spec.types.test.ts b/src/spec.types.test.ts index e8db9907f..816dba4cd 100644 --- a/src/spec.types.test.ts +++ b/src/spec.types.test.ts @@ -17,9 +17,11 @@ type RemovePassthrough = T extends object ? T extends Array ? Array> : T extends Function - ? T - : {[K in keyof T as string extends K ? never : K]: RemovePassthrough} - : T; + ? T + : { + [K in keyof T as string extends K ? never : K]: RemovePassthrough; + } + : T; // Adds the `jsonrpc` property to a type, to match the on-wire format of notifications. type WithJSONRPC = T & { jsonrpc: "2.0" }; @@ -27,70 +29,122 @@ type WithJSONRPC = T & { jsonrpc: "2.0" }; // Adds the `jsonrpc` and `id` properties to a type, to match the on-wire format of requests. type WithJSONRPCRequest = T & { jsonrpc: "2.0"; id: SDKTypes.RequestId }; -type IsUnknown = [unknown] extends [T] ? [T] extends [unknown] ? true : false : false; +type IsUnknown = [unknown] extends [T] + ? [T] extends [unknown] + ? true + : false + : false; // Turns {x?: unknown} into {x: unknown} but keeps {_meta?: unknown} unchanged (and leaves other optional properties unchanged, e.g. {x?: string}). // This works around an apparent quirk of ZodObject.unknown() (makes fields optional) -type MakeUnknownsNotOptional = - IsUnknown extends true - ? unknown - : (T extends object - ? (T extends Array - ? Array> - : (T extends Function - ? T - : Pick & { - // Start with empty object to avoid duplicates - // Make unknown properties required (except _meta) - [K in keyof T as '_meta' extends K ? never : IsUnknown extends true ? K : never]-?: unknown; - } & - Pick = IsUnknown extends true + ? unknown + : T extends object + ? T extends Array + ? Array> + : T extends Function + ? T + : Pick & { + // Start with empty object to avoid duplicates + // Make unknown properties required (except _meta) + [K in keyof T as "_meta" extends K + ? never + : IsUnknown extends true + ? K + : never]-?: unknown; + } & Pick< + T, + { // Pick all _meta and non-unknown properties with original modifiers - [K in keyof T]: '_meta' extends K ? K : IsUnknown extends true ? never : K - }[keyof T]> & { - // Recurse on the picked properties - [K in keyof Pick extends true ? never : K}[keyof T]>]: MakeUnknownsNotOptional - })) - : T); + [K in keyof T]: "_meta" extends K + ? K + : IsUnknown extends true + ? never + : K; + }[keyof T] + > & { + // Recurse on the picked properties + [K in keyof Pick< + T, + { + [K in keyof T]: "_meta" extends K + ? K + : IsUnknown extends true + ? never + : K; + }[keyof T] + >]: MakeUnknownsNotOptional; + } + : T; const sdkTypeChecks = { - CancelledNotification: (sdk: WithJSONRPC, spec: SpecTypes.CancelledNotification) => { + CancelledNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.CancelledNotification + ) => { sdk = spec; spec = sdk; }, - BaseMetadata: (sdk: RemovePassthrough, spec: SpecTypes.BaseMetadata) => { + BaseMetadata: ( + sdk: RemovePassthrough, + spec: SpecTypes.BaseMetadata + ) => { sdk = spec; spec = sdk; }, - Implementation: (sdk: RemovePassthrough, spec: SpecTypes.Implementation) => { + Implementation: ( + sdk: RemovePassthrough, + spec: SpecTypes.Implementation + ) => { sdk = spec; spec = sdk; }, - ProgressNotification: (sdk: WithJSONRPC, spec: SpecTypes.ProgressNotification) => { + ProgressNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.ProgressNotification + ) => { sdk = spec; spec = sdk; }, - SubscribeRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.SubscribeRequest) => { + SubscribeRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.SubscribeRequest + ) => { sdk = spec; spec = sdk; }, - UnsubscribeRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.UnsubscribeRequest) => { + UnsubscribeRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.UnsubscribeRequest + ) => { sdk = spec; spec = sdk; }, - PaginatedRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.PaginatedRequest) => { + PaginatedRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.PaginatedRequest + ) => { sdk = spec; spec = sdk; }, - PaginatedResult: (sdk: SDKTypes.PaginatedResult, spec: SpecTypes.PaginatedResult) => { + PaginatedResult: ( + sdk: SDKTypes.PaginatedResult, + spec: SpecTypes.PaginatedResult + ) => { sdk = spec; spec = sdk; }, - ListRootsRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListRootsRequest) => { + ListRootsRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.ListRootsRequest + ) => { sdk = spec; spec = sdk; }, - ListRootsResult: (sdk: RemovePassthrough, spec: SpecTypes.ListRootsResult) => { + ListRootsResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.ListRootsResult + ) => { sdk = spec; spec = sdk; }, @@ -98,23 +152,38 @@ const sdkTypeChecks = { sdk = spec; spec = sdk; }, - ElicitRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.ElicitRequest) => { + ElicitRequest: ( + sdk: WithJSONRPCRequest>, + spec: SpecTypes.ElicitRequest + ) => { sdk = spec; spec = sdk; }, - ElicitResult: (sdk: RemovePassthrough, spec: SpecTypes.ElicitResult) => { + ElicitResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.ElicitResult + ) => { sdk = spec; spec = sdk; }, - CompleteRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.CompleteRequest) => { + CompleteRequest: ( + sdk: WithJSONRPCRequest>, + spec: SpecTypes.CompleteRequest + ) => { sdk = spec; spec = sdk; }, - CompleteResult: (sdk: SDKTypes.CompleteResult, spec: SpecTypes.CompleteResult) => { + CompleteResult: ( + sdk: SDKTypes.CompleteResult, + spec: SpecTypes.CompleteResult + ) => { sdk = spec; spec = sdk; }, - ProgressToken: (sdk: SDKTypes.ProgressToken, spec: SpecTypes.ProgressToken) => { + ProgressToken: ( + sdk: SDKTypes.ProgressToken, + spec: SpecTypes.ProgressToken + ) => { sdk = spec; spec = sdk; }, @@ -134,15 +203,24 @@ const sdkTypeChecks = { sdk = spec; spec = sdk; }, - JSONRPCRequest: (sdk: SDKTypes.JSONRPCRequest, spec: SpecTypes.JSONRPCRequest) => { + JSONRPCRequest: ( + sdk: SDKTypes.JSONRPCRequest, + spec: SpecTypes.JSONRPCRequest + ) => { sdk = spec; spec = sdk; }, - JSONRPCNotification: (sdk: SDKTypes.JSONRPCNotification, spec: SpecTypes.JSONRPCNotification) => { + JSONRPCNotification: ( + sdk: SDKTypes.JSONRPCNotification, + spec: SpecTypes.JSONRPCNotification + ) => { sdk = spec; spec = sdk; }, - JSONRPCResponse: (sdk: SDKTypes.JSONRPCResponse, spec: SpecTypes.JSONRPCResponse) => { + JSONRPCResponse: ( + sdk: SDKTypes.JSONRPCResponse, + spec: SpecTypes.JSONRPCResponse + ) => { sdk = spec; spec = sdk; }, @@ -158,7 +236,10 @@ const sdkTypeChecks = { sdk = spec; spec = sdk; }, - ClientNotification: (sdk: WithJSONRPC, spec: SpecTypes.ClientNotification) => { + ClientNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.ClientNotification + ) => { sdk = spec; spec = sdk; }, @@ -166,15 +247,24 @@ const sdkTypeChecks = { sdk = spec; spec = sdk; }, - ResourceTemplateReference: (sdk: RemovePassthrough, spec: SpecTypes.ResourceTemplateReference) => { + ResourceTemplateReference: ( + sdk: RemovePassthrough, + spec: SpecTypes.ResourceTemplateReference + ) => { sdk = spec; spec = sdk; }, - PromptReference: (sdk: RemovePassthrough, spec: SpecTypes.PromptReference) => { + PromptReference: ( + sdk: RemovePassthrough, + spec: SpecTypes.PromptReference + ) => { sdk = spec; spec = sdk; }, - ToolAnnotations: (sdk: RemovePassthrough, spec: SpecTypes.ToolAnnotations) => { + ToolAnnotations: ( + sdk: RemovePassthrough, + spec: SpecTypes.ToolAnnotations + ) => { sdk = spec; spec = sdk; }, @@ -182,107 +272,185 @@ const sdkTypeChecks = { sdk = spec; spec = sdk; }, - ListToolsRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListToolsRequest) => { + ListToolsRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.ListToolsRequest + ) => { sdk = spec; spec = sdk; }, - ListToolsResult: (sdk: RemovePassthrough, spec: SpecTypes.ListToolsResult) => { + ListToolsResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.ListToolsResult + ) => { sdk = spec; spec = sdk; }, - CallToolResult: (sdk: RemovePassthrough, spec: SpecTypes.CallToolResult) => { + CallToolResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.CallToolResult + ) => { sdk = spec; spec = sdk; }, - CallToolRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.CallToolRequest) => { + CallToolRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.CallToolRequest + ) => { sdk = spec; spec = sdk; }, - ToolListChangedNotification: (sdk: WithJSONRPC, spec: SpecTypes.ToolListChangedNotification) => { + ToolListChangedNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.ToolListChangedNotification + ) => { sdk = spec; spec = sdk; }, - ResourceListChangedNotification: (sdk: WithJSONRPC, spec: SpecTypes.ResourceListChangedNotification) => { + ResourceListChangedNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.ResourceListChangedNotification + ) => { sdk = spec; spec = sdk; }, - PromptListChangedNotification: (sdk: WithJSONRPC, spec: SpecTypes.PromptListChangedNotification) => { + PromptListChangedNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.PromptListChangedNotification + ) => { sdk = spec; spec = sdk; }, - RootsListChangedNotification: (sdk: WithJSONRPC, spec: SpecTypes.RootsListChangedNotification) => { + RootsListChangedNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.RootsListChangedNotification + ) => { sdk = spec; spec = sdk; }, - ResourceUpdatedNotification: (sdk: WithJSONRPC, spec: SpecTypes.ResourceUpdatedNotification) => { + ResourceUpdatedNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.ResourceUpdatedNotification + ) => { sdk = spec; spec = sdk; }, - SamplingMessage: (sdk: RemovePassthrough, spec: SpecTypes.SamplingMessage) => { + SamplingMessage: ( + sdk: RemovePassthrough, + spec: SpecTypes.SamplingMessage + ) => { sdk = spec; spec = sdk; }, - CreateMessageResult: (sdk: RemovePassthrough, spec: SpecTypes.CreateMessageResult) => { + CreateMessageResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.CreateMessageResult + ) => { sdk = spec; spec = sdk; }, - SetLevelRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.SetLevelRequest) => { + SetLevelRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.SetLevelRequest + ) => { sdk = spec; spec = sdk; }, - PingRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.PingRequest) => { + PingRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.PingRequest + ) => { sdk = spec; spec = sdk; }, - InitializedNotification: (sdk: WithJSONRPC, spec: SpecTypes.InitializedNotification) => { + InitializedNotification: ( + sdk: WithJSONRPC, + spec: SpecTypes.InitializedNotification + ) => { sdk = spec; spec = sdk; }, - ListResourcesRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListResourcesRequest) => { + ListResourcesRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.ListResourcesRequest + ) => { sdk = spec; spec = sdk; }, - ListResourcesResult: (sdk: RemovePassthrough, spec: SpecTypes.ListResourcesResult) => { + ListResourcesResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.ListResourcesResult + ) => { sdk = spec; spec = sdk; }, - ListResourceTemplatesRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListResourceTemplatesRequest) => { + ListResourceTemplatesRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.ListResourceTemplatesRequest + ) => { sdk = spec; spec = sdk; }, - ListResourceTemplatesResult: (sdk: RemovePassthrough, spec: SpecTypes.ListResourceTemplatesResult) => { + ListResourceTemplatesResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.ListResourceTemplatesResult + ) => { sdk = spec; spec = sdk; }, - ReadResourceRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ReadResourceRequest) => { + ReadResourceRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.ReadResourceRequest + ) => { sdk = spec; spec = sdk; }, - ReadResourceResult: (sdk: RemovePassthrough, spec: SpecTypes.ReadResourceResult) => { + ReadResourceResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.ReadResourceResult + ) => { sdk = spec; spec = sdk; }, - ResourceContents: (sdk: RemovePassthrough, spec: SpecTypes.ResourceContents) => { + ResourceContents: ( + sdk: RemovePassthrough, + spec: SpecTypes.ResourceContents + ) => { sdk = spec; spec = sdk; }, - TextResourceContents: (sdk: RemovePassthrough, spec: SpecTypes.TextResourceContents) => { + TextResourceContents: ( + sdk: RemovePassthrough, + spec: SpecTypes.TextResourceContents + ) => { sdk = spec; spec = sdk; - }, - BlobResourceContents: (sdk: RemovePassthrough, spec: SpecTypes.BlobResourceContents) => { + }, + BlobResourceContents: ( + sdk: RemovePassthrough, + spec: SpecTypes.BlobResourceContents + ) => { sdk = spec; spec = sdk; }, - Resource: (sdk: RemovePassthrough, spec: SpecTypes.Resource) => { + Resource: ( + sdk: RemovePassthrough, + spec: SpecTypes.Resource + ) => { sdk = spec; spec = sdk; }, - ResourceTemplate: (sdk: RemovePassthrough, spec: SpecTypes.ResourceTemplate) => { + ResourceTemplate: ( + sdk: RemovePassthrough, + spec: SpecTypes.ResourceTemplate + ) => { sdk = spec; spec = sdk; }, - PromptArgument: (sdk: RemovePassthrough, spec: SpecTypes.PromptArgument) => { + PromptArgument: ( + sdk: RemovePassthrough, + spec: SpecTypes.PromptArgument + ) => { sdk = spec; spec = sdk; }, @@ -290,67 +458,115 @@ const sdkTypeChecks = { sdk = spec; spec = sdk; }, - ListPromptsRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.ListPromptsRequest) => { + ListPromptsRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.ListPromptsRequest + ) => { sdk = spec; spec = sdk; }, - ListPromptsResult: (sdk: RemovePassthrough, spec: SpecTypes.ListPromptsResult) => { + ListPromptsResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.ListPromptsResult + ) => { sdk = spec; spec = sdk; }, - GetPromptRequest: (sdk: WithJSONRPCRequest, spec: SpecTypes.GetPromptRequest) => { + GetPromptRequest: ( + sdk: WithJSONRPCRequest, + spec: SpecTypes.GetPromptRequest + ) => { sdk = spec; spec = sdk; }, - TextContent: (sdk: RemovePassthrough, spec: SpecTypes.TextContent) => { + TextContent: ( + sdk: RemovePassthrough, + spec: SpecTypes.TextContent + ) => { sdk = spec; spec = sdk; }, - ImageContent: (sdk: RemovePassthrough, spec: SpecTypes.ImageContent) => { + ImageContent: ( + sdk: RemovePassthrough, + spec: SpecTypes.ImageContent + ) => { sdk = spec; spec = sdk; }, - AudioContent: (sdk: RemovePassthrough, spec: SpecTypes.AudioContent) => { + AudioContent: ( + sdk: RemovePassthrough, + spec: SpecTypes.AudioContent + ) => { sdk = spec; spec = sdk; }, - EmbeddedResource: (sdk: RemovePassthrough, spec: SpecTypes.EmbeddedResource) => { + EmbeddedResource: ( + sdk: RemovePassthrough, + spec: SpecTypes.EmbeddedResource + ) => { sdk = spec; spec = sdk; - }, - ResourceLink: (sdk: RemovePassthrough, spec: SpecTypes.ResourceLink) => { + }, + ResourceLink: ( + sdk: RemovePassthrough, + spec: SpecTypes.ResourceLink + ) => { sdk = spec; spec = sdk; }, - ContentBlock: (sdk: RemovePassthrough, spec: SpecTypes.ContentBlock) => { + ContentBlock: ( + sdk: RemovePassthrough, + spec: SpecTypes.ContentBlock + ) => { sdk = spec; spec = sdk; }, - PromptMessage: (sdk: RemovePassthrough, spec: SpecTypes.PromptMessage) => { + PromptMessage: ( + sdk: RemovePassthrough, + spec: SpecTypes.PromptMessage + ) => { sdk = spec; spec = sdk; }, - GetPromptResult: (sdk: RemovePassthrough, spec: SpecTypes.GetPromptResult) => { + GetPromptResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.GetPromptResult + ) => { sdk = spec; spec = sdk; }, - BooleanSchema: (sdk: RemovePassthrough, spec: SpecTypes.BooleanSchema) => { + BooleanSchema: ( + sdk: RemovePassthrough, + spec: SpecTypes.BooleanSchema + ) => { sdk = spec; spec = sdk; }, - StringSchema: (sdk: RemovePassthrough, spec: SpecTypes.StringSchema) => { + StringSchema: ( + sdk: RemovePassthrough, + spec: SpecTypes.StringSchema + ) => { sdk = spec; spec = sdk; }, - NumberSchema: (sdk: RemovePassthrough, spec: SpecTypes.NumberSchema) => { + NumberSchema: ( + sdk: RemovePassthrough, + spec: SpecTypes.NumberSchema + ) => { sdk = spec; spec = sdk; }, - EnumSchema: (sdk: RemovePassthrough, spec: SpecTypes.EnumSchema) => { + EnumSchema: ( + sdk: RemovePassthrough, + spec: SpecTypes.EnumSchema + ) => { sdk = spec; spec = sdk; }, - PrimitiveSchemaDefinition: (sdk: RemovePassthrough, spec: SpecTypes.PrimitiveSchemaDefinition) => { + PrimitiveSchemaDefinition: ( + sdk: RemovePassthrough, + spec: SpecTypes.PrimitiveSchemaDefinition + ) => { sdk = spec; spec = sdk; }, @@ -358,43 +574,75 @@ const sdkTypeChecks = { sdk = spec; spec = sdk; }, - JSONRPCMessage: (sdk: SDKTypes.JSONRPCMessage, spec: SpecTypes.JSONRPCMessage) => { + JSONRPCMessage: ( + sdk: SDKTypes.JSONRPCMessage, + spec: SpecTypes.JSONRPCMessage + ) => { sdk = spec; spec = sdk; }, - CreateMessageRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.CreateMessageRequest) => { + CreateMessageRequest: ( + sdk: WithJSONRPCRequest>, + spec: SpecTypes.CreateMessageRequest + ) => { sdk = spec; spec = sdk; }, - InitializeRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.InitializeRequest) => { + InitializeRequest: ( + sdk: WithJSONRPCRequest>, + spec: SpecTypes.InitializeRequest + ) => { sdk = spec; spec = sdk; }, - InitializeResult: (sdk: RemovePassthrough, spec: SpecTypes.InitializeResult) => { + InitializeResult: ( + sdk: RemovePassthrough, + spec: SpecTypes.InitializeResult + ) => { sdk = spec; spec = sdk; }, - ClientCapabilities: (sdk: RemovePassthrough, spec: SpecTypes.ClientCapabilities) => { + ClientCapabilities: ( + sdk: RemovePassthrough, + spec: SpecTypes.ClientCapabilities + ) => { sdk = spec; spec = sdk; }, - ServerCapabilities: (sdk: RemovePassthrough, spec: SpecTypes.ServerCapabilities) => { + ServerCapabilities: ( + sdk: RemovePassthrough, + spec: SpecTypes.ServerCapabilities + ) => { sdk = spec; spec = sdk; }, - ClientRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.ClientRequest) => { + ClientRequest: ( + sdk: WithJSONRPCRequest>, + spec: SpecTypes.ClientRequest + ) => { sdk = spec; spec = sdk; }, - ServerRequest: (sdk: WithJSONRPCRequest>, spec: SpecTypes.ServerRequest) => { + ServerRequest: ( + sdk: WithJSONRPCRequest>, + spec: SpecTypes.ServerRequest + ) => { sdk = spec; spec = sdk; }, - LoggingMessageNotification: (sdk: MakeUnknownsNotOptional>, spec: SpecTypes.LoggingMessageNotification) => { + LoggingMessageNotification: ( + sdk: MakeUnknownsNotOptional< + WithJSONRPC + >, + spec: SpecTypes.LoggingMessageNotification + ) => { sdk = spec; spec = sdk; }, - ServerNotification: (sdk: MakeUnknownsNotOptional>, spec: SpecTypes.ServerNotification) => { + ServerNotification: ( + sdk: MakeUnknownsNotOptional>, + spec: SpecTypes.ServerNotification + ) => { sdk = spec; spec = sdk; }, @@ -409,55 +657,68 @@ const sdkTypeChecks = { Icons: (sdk: RemovePassthrough, spec: SpecTypes.Icons) => { sdk = spec; spec = sdk; - } -} + }, +}; // This file is .gitignore'd, and fetched by `npm run fetch:spec-types` (called by `npm run test`) -const SPEC_TYPES_FILE = 'spec.types.ts'; -const SDK_TYPES_FILE = 'src/types.ts'; +const SPEC_TYPES_FILE = "spec.types.ts"; +const SDK_TYPES_FILE = "src/types.ts"; const MISSING_SDK_TYPES = [ // These are inlined in the SDK: - 'Role', - 'Error', // The inner error object of a JSONRPCError + "Role", + "Error", // The inner error object of a JSONRPCError // These aren't supported by the SDK yet: // TODO: Add definitions to the SDK - 'Annotations', - 'ModelHint', - 'ModelPreferences', -] + "Annotations", + "ModelHint", + "ModelPreferences", +]; function extractExportedTypes(source: string): string[] { - return [...source.matchAll(/export\s+(?:interface|class|type)\s+(\w+)\b/g)].map(m => m[1]); + return [ + ...source.matchAll(/export\s+(?:interface|class|type)\s+(\w+)\b/g), + ].map((m) => m[1]); } -describe('Spec Types', () => { - const specTypes = extractExportedTypes(fs.readFileSync(SPEC_TYPES_FILE, 'utf-8')); - const sdkTypes = extractExportedTypes(fs.readFileSync(SDK_TYPES_FILE, 'utf-8')); - const typesToCheck = specTypes.filter(type => !MISSING_SDK_TYPES.includes(type)); +describe("Spec Types", () => { + const specTypes = extractExportedTypes( + fs.readFileSync(SPEC_TYPES_FILE, "utf-8") + ); + const sdkTypes = extractExportedTypes( + fs.readFileSync(SDK_TYPES_FILE, "utf-8") + ); + const typesToCheck = specTypes.filter( + (type) => !MISSING_SDK_TYPES.includes(type) + ); - it('should define some expected types', () => { - expect(specTypes).toContain('JSONRPCNotification'); - expect(specTypes).toContain('ElicitResult'); + it("should define some expected types", () => { + expect(specTypes).toContain("JSONRPCNotification"); + expect(specTypes).toContain("ElicitResult"); expect(specTypes).toHaveLength(94); }); - it('should have up to date list of missing sdk types', () => { + it("should have up to date list of missing sdk types", () => { for (const typeName of MISSING_SDK_TYPES) { expect(sdkTypes).not.toContain(typeName); } }); - describe('Compatibility tests', () => { - it.each(typesToCheck)('%s should have a compatibility test', (type) => { - expect(sdkTypeChecks[type as keyof typeof sdkTypeChecks]).toBeDefined(); - }); + describe("Compatibility tests", () => { + it.each(typesToCheck)("%s should have a compatibility test", (type) => { + expect(sdkTypeChecks[type as keyof typeof sdkTypeChecks]).toBeDefined(); + }); }); - describe('Missing SDK Types', () => { - it.each(MISSING_SDK_TYPES)('%s should not be present in MISSING_SDK_TYPES if it has a compatibility test', (type) => { - expect(sdkTypeChecks[type as keyof typeof sdkTypeChecks]).toBeUndefined(); - }); + describe("Missing SDK Types", () => { + it.each(MISSING_SDK_TYPES)( + "%s should not be present in MISSING_SDK_TYPES if it has a compatibility test", + (type) => { + expect( + sdkTypeChecks[type as keyof typeof sdkTypeChecks] + ).toBeUndefined(); + } + ); }); }); diff --git a/src/types.ts b/src/types.ts index 26ab0e24d..7c092a198 100644 --- a/src/types.ts +++ b/src/types.ts @@ -230,7 +230,7 @@ export const IconSchema = z */ export const IconsSchema = z.object({ icons: z.array(IconSchema).optional(), -}).passthrough(); +}).strip(); /** * Base metadata interface for common properties across resources, tools, prompts, and implementations. From fbf98f40023dfc03dc0bf77533a159176dedb4cf Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Fri, 19 Sep 2025 08:46:33 +0300 Subject: [PATCH 3/7] revert IconsSchema to passthrough - to be moved to strip in PR#792 --- src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 7c092a198..26ab0e24d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -230,7 +230,7 @@ export const IconSchema = z */ export const IconsSchema = z.object({ icons: z.array(IconSchema).optional(), -}).strip(); +}).passthrough(); /** * Base metadata interface for common properties across resources, tools, prompts, and implementations. From 4898f6730faac2efb8508eb5ecd89c24eb7c9d47 Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Mon, 29 Sep 2025 13:16:37 +0300 Subject: [PATCH 4/7] Icon schema sizes property - align with spec --- src/types.ts | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/types.ts b/src/types.ts index 26ab0e24d..e3b856923 100644 --- a/src/types.ts +++ b/src/types.ts @@ -216,7 +216,7 @@ export const IconSchema = z /** * Optional string specifying icon dimensions (e.g., "48x48 96x96"). */ - sizes: z.optional(z.string()), + sizes: z.optional(z.array(z.string())), }) .passthrough(); @@ -542,17 +542,12 @@ export const ResourceSchema = BaseMetadataSchema.extend({ */ mimeType: z.optional(z.string()), - /** - * An optional list of icons for this resource. - */ - icons: z.optional(z.array(IconSchema)), - /** * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) * for notes on _meta usage. */ _meta: z.optional(z.object({}).passthrough()), -}); +}).merge(IconsSchema); /** * A template description for resources available on the server. @@ -713,16 +708,12 @@ export const PromptSchema = BaseMetadataSchema.extend({ * A list of arguments to use for templating the prompt. */ arguments: z.optional(z.array(PromptArgumentSchema)), - /** - * An optional list of icons for this prompt. - */ - icons: z.optional(z.array(IconSchema)), /** * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) * for notes on _meta usage. */ _meta: z.optional(z.object({}).passthrough()), -}); +}).merge(IconsSchema); /** * Sent from the client to request a list of prompts and prompt templates the server has. @@ -975,17 +966,12 @@ export const ToolSchema = BaseMetadataSchema.extend({ */ annotations: z.optional(ToolAnnotationsSchema), - /** - * An optional list of icons for this tool. - */ - icons: z.optional(z.array(IconSchema)), - /** * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) * for notes on _meta usage. */ _meta: z.optional(z.object({}).passthrough()), -}); +}).merge(IconsSchema); /** * Sent from the client to request a list of tools the server has. From f9acee2cbdca509418876b4062cbfcbe376565e4 Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Mon, 29 Sep 2025 13:22:28 +0300 Subject: [PATCH 5/7] update comment on sizes prop, fix simpleStreamableHttp example --- src/examples/server/simpleStreamableHttp.ts | 2 +- src/types.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/examples/server/simpleStreamableHttp.ts b/src/examples/server/simpleStreamableHttp.ts index 6f1e20080..de420c1cc 100644 --- a/src/examples/server/simpleStreamableHttp.ts +++ b/src/examples/server/simpleStreamableHttp.ts @@ -22,7 +22,7 @@ const getServer = () => { const server = new McpServer({ name: 'simple-streamable-http-server', version: '1.0.0', - icons: [{src: './mcp.svg', sizes: '512x512', mimeType: 'image/svg+xml'}], + icons: [{src: './mcp.svg', sizes: ['512x512'], mimeType: 'image/svg+xml'}], websiteUrl: 'https://github.com/modelcontextprotocol/typescript-sdk', }, { capabilities: { logging: {} } }); diff --git a/src/types.ts b/src/types.ts index e3b856923..946deae01 100644 --- a/src/types.ts +++ b/src/types.ts @@ -214,7 +214,10 @@ export const IconSchema = z */ mimeType: z.optional(z.string()), /** - * Optional string specifying icon dimensions (e.g., "48x48 96x96"). + * Optional array of strings that specify sizes at which the icon can be used. + * Each string should be in WxH format (e.g., `"48x48"`, `"96x96"`) or `"any"` for scalable formats like SVG. + * + * If not provided, the client should assume that the icon can be used at any size. */ sizes: z.optional(z.array(z.string())), }) From cf82e7d925b334cfb7afdbf849b40eca2e2c67fc Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Tue, 30 Sep 2025 18:59:14 +0300 Subject: [PATCH 6/7] add IconsSchema to ResourceTemplates as per modelcontextprotocol/modelcontextprotocol#1565 --- src/types.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/types.ts b/src/types.ts index 946deae01..af82fe3f1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -224,12 +224,15 @@ export const IconSchema = z .passthrough(); /** - * An optional list of icons for this implementation. - * This can be used by clients to display the implementation in a user interface. - * Each icon should have a `kind` property that specifies whether it is a data representation or a URL source, a `src` property that points to the icon file or data representation, and may also include a `mimeType` and `sizes` property. - * The `mimeType` property should be a valid MIME type for the icon file, such as "image/png" or "image/svg+xml". - * The `sizes` property should be a string that specifies one or more sizes at which the icon file can be used, such as "48x48" or "any" for scalable formats like SVG. - * The `sizes` property is optional, and if not provided, the client should assume that the icon can be used at any size. + * Optional set of sized icons that the client can display in a user interface. + * + * Clients that support rendering icons MUST support at least the following MIME types: + * - `image/png` - PNG images (safe, universal compatibility) + * - `image/jpeg` (and `image/jpg`) - JPEG images (safe, universal compatibility) + * + * Clients that support rendering icons SHOULD also support: + * - `image/svg+xml` - SVG images (scalable but requires security precautions) + * - `image/webp` - WebP images (modern, efficient format) */ export const IconsSchema = z.object({ icons: z.array(IconSchema).optional(), @@ -578,7 +581,7 @@ export const ResourceTemplateSchema = BaseMetadataSchema.extend({ * for notes on _meta usage. */ _meta: z.optional(z.object({}).passthrough()), -}); +}).merge(IconsSchema); /** * Sent from the client to request a list of resources the server has. From ef62ae0f7882e03d353d9fd4cea2d7cea4e1f11a Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Tue, 30 Sep 2025 19:02:35 +0300 Subject: [PATCH 7/7] fix comments --- src/types.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/types.ts b/src/types.ts index af82fe3f1..ee2ceb5ed 100644 --- a/src/types.ts +++ b/src/types.ts @@ -224,17 +224,21 @@ export const IconSchema = z .passthrough(); /** - * Optional set of sized icons that the client can display in a user interface. + * Base schema to add `icons` property. * - * Clients that support rendering icons MUST support at least the following MIME types: - * - `image/png` - PNG images (safe, universal compatibility) - * - `image/jpeg` (and `image/jpg`) - JPEG images (safe, universal compatibility) - * - * Clients that support rendering icons SHOULD also support: - * - `image/svg+xml` - SVG images (scalable but requires security precautions) - * - `image/webp` - WebP images (modern, efficient format) */ export const IconsSchema = z.object({ + /** + * Optional set of sized icons that the client can display in a user interface. + * + * Clients that support rendering icons MUST support at least the following MIME types: + * - `image/png` - PNG images (safe, universal compatibility) + * - `image/jpeg` (and `image/jpg`) - JPEG images (safe, universal compatibility) + * + * Clients that support rendering icons SHOULD also support: + * - `image/svg+xml` - SVG images (scalable but requires security precautions) + * - `image/webp` - WebP images (modern, efficient format) + */ icons: z.array(IconSchema).optional(), }).passthrough();