diff --git a/packages/core/src/types/spec.types.ts b/packages/core/src/types/spec.types.ts index f36434bef..ba849c546 100644 --- a/packages/core/src/types/spec.types.ts +++ b/packages/core/src/types/spec.types.ts @@ -586,7 +586,7 @@ export interface ClientCapabilities { * @example Extensions — UI extension with MIME type support * {@includeCode ./examples/ClientCapabilities/extensions-ui-mime-types.json} */ - extensions?: { [key: string]: object }; + extensions?: { [key: string]: JSONObject }; } /** @@ -703,7 +703,7 @@ export interface ServerCapabilities { * @example Extensions — UI extension support * {@includeCode ./examples/ServerCapabilities/extensions-ui.json} */ - extensions?: { [key: string]: object }; + extensions?: { [key: string]: JSONObject }; } /** diff --git a/packages/core/src/types/types.ts b/packages/core/src/types/types.ts index 98216a4e0..967092d3f 100644 --- a/packages/core/src/types/types.ts +++ b/packages/core/src/types/types.ts @@ -556,7 +556,11 @@ export const ClientCapabilitiesSchema = z.object({ /** * Present if the client supports task creation. */ - tasks: ClientTasksCapabilitySchema.optional() + tasks: ClientTasksCapabilitySchema.optional(), + /** + * Extensions that the client supports. Keys are extension identifiers (vendor-prefix/extension-name). + */ + extensions: z.record(z.string(), JSONObjectSchema).optional() }); export const InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({ @@ -634,7 +638,11 @@ export const ServerCapabilitiesSchema = z.object({ /** * Present if the server supports task creation. */ - tasks: ServerTasksCapabilitySchema.optional() + tasks: ServerTasksCapabilitySchema.optional(), + /** + * Extensions that the server supports. Keys are extension identifiers (vendor-prefix/extension-name). + */ + extensions: z.record(z.string(), JSONObjectSchema).optional() }); /** diff --git a/test/integration/test/server/mcp.test.ts b/test/integration/test/server/mcp.test.ts index 4ea04beae..b58149716 100644 --- a/test/integration/test/server/mcp.test.ts +++ b/test/integration/test/server/mcp.test.ts @@ -338,6 +338,60 @@ describe('Zod v4', () => { message: 'Completed step 3 of 3' }); }); + + /*** + * Test: Extensions capability registration + */ + test('should register and advertise server extensions capability', async () => { + const mcpServer = new McpServer({ + name: 'test server', + version: '1.0' + }); + const client = new Client({ + name: 'test client', + version: '1.0' + }); + + mcpServer.server.registerCapabilities({ + extensions: { + 'io.modelcontextprotocol/test-extension': { listChanged: true } + } + }); + + const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); + await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]); + + const capabilities = client.getServerCapabilities(); + expect(capabilities?.extensions).toBeDefined(); + expect(capabilities?.extensions?.['io.modelcontextprotocol/test-extension']).toEqual({ listChanged: true }); + }); + + test('should advertise client extensions capability to server', async () => { + const mcpServer = new McpServer({ + name: 'test server', + version: '1.0' + }); + const client = new Client( + { + name: 'test client', + version: '1.0' + }, + { + capabilities: { + extensions: { + 'io.modelcontextprotocol/test-extension': { streaming: true } + } + } + } + ); + + const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); + await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]); + + const capabilities = mcpServer.server.getClientCapabilities(); + expect(capabilities?.extensions).toBeDefined(); + expect(capabilities?.extensions?.['io.modelcontextprotocol/test-extension']).toEqual({ streaming: true }); + }); }); describe('ResourceTemplate', () => {