Skip to content

Commit 677511b

Browse files
chughtapanclaude
andauthored
Allow servers / clients to advertise extensions in the capability object (modelcontextprotocol#1630)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9aed95a commit 677511b

File tree

3 files changed

+66
-4
lines changed

3 files changed

+66
-4
lines changed

packages/core/src/types/spec.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ export interface ClientCapabilities {
586586
* @example Extensions — UI extension with MIME type support
587587
* {@includeCode ./examples/ClientCapabilities/extensions-ui-mime-types.json}
588588
*/
589-
extensions?: { [key: string]: object };
589+
extensions?: { [key: string]: JSONObject };
590590
}
591591

592592
/**
@@ -703,7 +703,7 @@ export interface ServerCapabilities {
703703
* @example Extensions — UI extension support
704704
* {@includeCode ./examples/ServerCapabilities/extensions-ui.json}
705705
*/
706-
extensions?: { [key: string]: object };
706+
extensions?: { [key: string]: JSONObject };
707707
}
708708

709709
/**

packages/core/src/types/types.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,11 @@ export const ClientCapabilitiesSchema = z.object({
557557
/**
558558
* Present if the client supports task creation.
559559
*/
560-
tasks: ClientTasksCapabilitySchema.optional()
560+
tasks: ClientTasksCapabilitySchema.optional(),
561+
/**
562+
* Extensions that the client supports. Keys are extension identifiers (vendor-prefix/extension-name).
563+
*/
564+
extensions: z.record(z.string(), JSONObjectSchema).optional()
561565
});
562566

563567
export const InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
@@ -635,7 +639,11 @@ export const ServerCapabilitiesSchema = z.object({
635639
/**
636640
* Present if the server supports task creation.
637641
*/
638-
tasks: ServerTasksCapabilitySchema.optional()
642+
tasks: ServerTasksCapabilitySchema.optional(),
643+
/**
644+
* Extensions that the server supports. Keys are extension identifiers (vendor-prefix/extension-name).
645+
*/
646+
extensions: z.record(z.string(), JSONObjectSchema).optional()
639647
});
640648

641649
/**

test/integration/test/server/mcp.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,60 @@ describe('Zod v4', () => {
338338
message: 'Completed step 3 of 3'
339339
});
340340
});
341+
342+
/***
343+
* Test: Extensions capability registration
344+
*/
345+
test('should register and advertise server extensions capability', async () => {
346+
const mcpServer = new McpServer({
347+
name: 'test server',
348+
version: '1.0'
349+
});
350+
const client = new Client({
351+
name: 'test client',
352+
version: '1.0'
353+
});
354+
355+
mcpServer.server.registerCapabilities({
356+
extensions: {
357+
'io.modelcontextprotocol/test-extension': { listChanged: true }
358+
}
359+
});
360+
361+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
362+
await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]);
363+
364+
const capabilities = client.getServerCapabilities();
365+
expect(capabilities?.extensions).toBeDefined();
366+
expect(capabilities?.extensions?.['io.modelcontextprotocol/test-extension']).toEqual({ listChanged: true });
367+
});
368+
369+
test('should advertise client extensions capability to server', async () => {
370+
const mcpServer = new McpServer({
371+
name: 'test server',
372+
version: '1.0'
373+
});
374+
const client = new Client(
375+
{
376+
name: 'test client',
377+
version: '1.0'
378+
},
379+
{
380+
capabilities: {
381+
extensions: {
382+
'io.modelcontextprotocol/test-extension': { streaming: true }
383+
}
384+
}
385+
}
386+
);
387+
388+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
389+
await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]);
390+
391+
const capabilities = mcpServer.server.getClientCapabilities();
392+
expect(capabilities?.extensions).toBeDefined();
393+
expect(capabilities?.extensions?.['io.modelcontextprotocol/test-extension']).toEqual({ streaming: true });
394+
});
341395
});
342396

343397
describe('ResourceTemplate', () => {

0 commit comments

Comments
 (0)