Skip to content

Commit 8654c7f

Browse files
authored
Fix: Respect explicit listChanged: false capability setting (#1513)
1 parent 65bbcea commit 8654c7f

File tree

3 files changed

+97
-4
lines changed

3 files changed

+97
-4
lines changed

packages/server/src/server/mcp.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export class McpServer {
117117

118118
this.server.registerCapabilities({
119119
tools: {
120-
listChanged: true
120+
listChanged: this.server.getCapabilities().tools?.listChanged ?? true
121121
}
122122
});
123123

@@ -429,7 +429,7 @@ export class McpServer {
429429

430430
this.server.registerCapabilities({
431431
resources: {
432-
listChanged: true
432+
listChanged: this.server.getCapabilities().resources?.listChanged ?? true
433433
}
434434
});
435435

@@ -509,7 +509,7 @@ export class McpServer {
509509

510510
this.server.registerCapabilities({
511511
prompts: {
512-
listChanged: true
512+
listChanged: this.server.getCapabilities().prompts?.listChanged ?? true
513513
}
514514
});
515515

packages/server/src/server/server.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,10 @@ export class Server extends Protocol<ServerContext> {
452452
return this._clientVersion;
453453
}
454454

455-
private getCapabilities(): ServerCapabilities {
455+
/**
456+
* Returns the current server capabilities.
457+
*/
458+
public getCapabilities(): ServerCapabilities {
456459
return this._capabilities;
457460
}
458461

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

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,96 @@ describe('Zod v4', () => {
782782
]);
783783
});
784784

785+
/***
786+
* Test: listChanged capability should default to true when not specified
787+
*/
788+
test('should default tools.listChanged to true when not explicitly set', async () => {
789+
const mcpServer = new McpServer({
790+
name: 'test server',
791+
version: '1.0'
792+
});
793+
const client = new Client({
794+
name: 'test client',
795+
version: '1.0'
796+
});
797+
798+
mcpServer.registerTool('test', {}, async () => ({
799+
content: [{ type: 'text', text: 'Test' }]
800+
}));
801+
802+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
803+
await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]);
804+
805+
const capabilities = client.getServerCapabilities();
806+
expect(capabilities?.tools?.listChanged).toBe(true);
807+
});
808+
809+
/***
810+
* Test: listChanged capability should respect explicit false setting
811+
*/
812+
test('should respect tools.listChanged: false when explicitly set', async () => {
813+
const mcpServer = new McpServer({ name: 'test server', version: '1.0' }, { capabilities: { tools: { listChanged: false } } });
814+
const client = new Client({
815+
name: 'test client',
816+
version: '1.0'
817+
});
818+
819+
mcpServer.registerTool('test', {}, async () => ({
820+
content: [{ type: 'text', text: 'Test' }]
821+
}));
822+
823+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
824+
await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]);
825+
826+
const capabilities = client.getServerCapabilities();
827+
expect(capabilities?.tools?.listChanged).toBe(false);
828+
});
829+
830+
/***
831+
* Test: resources.listChanged should respect explicit false setting
832+
*/
833+
test('should respect resources.listChanged: false when explicitly set', async () => {
834+
const mcpServer = new McpServer(
835+
{ name: 'test server', version: '1.0' },
836+
{ capabilities: { resources: { listChanged: false } } }
837+
);
838+
const client = new Client({
839+
name: 'test client',
840+
version: '1.0'
841+
});
842+
843+
mcpServer.registerResource('test://resource', 'Test Resource', async () => ({
844+
contents: [{ uri: 'test://resource', text: 'Test' }]
845+
}));
846+
847+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
848+
await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]);
849+
850+
const capabilities = client.getServerCapabilities();
851+
expect(capabilities?.resources?.listChanged).toBe(false);
852+
});
853+
854+
/***
855+
* Test: prompts.listChanged should respect explicit false setting
856+
*/
857+
test('should respect prompts.listChanged: false when explicitly set', async () => {
858+
const mcpServer = new McpServer({ name: 'test server', version: '1.0' }, { capabilities: { prompts: { listChanged: false } } });
859+
const client = new Client({
860+
name: 'test client',
861+
version: '1.0'
862+
});
863+
864+
mcpServer.registerPrompt('test-prompt', async () => ({
865+
messages: [{ role: 'assistant', content: { type: 'text', text: 'Test' } }]
866+
}));
867+
868+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
869+
await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]);
870+
871+
const capabilities = client.getServerCapabilities();
872+
expect(capabilities?.prompts?.listChanged).toBe(false);
873+
});
874+
785875
/***
786876
* Test: Tool Registration with Parameters
787877
*/

0 commit comments

Comments
 (0)