@@ -252,6 +252,209 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
252252 expect ( capabilities ?. extensions ) . toBeDefined ( ) ;
253253 expect ( capabilities ?. extensions ?. [ 'io.modelcontextprotocol/test-extension' ] ) . toEqual ( { streaming : true } ) ;
254254 } ) ;
255+
256+ test ( 'should expose current server capabilities via the underlying server' , ( ) => {
257+ const mcpServer = new McpServer (
258+ {
259+ name : 'test server' ,
260+ version : '1.0'
261+ } ,
262+ { capabilities : { tools : { listChanged : false } } }
263+ ) ;
264+
265+ expect ( mcpServer . server . getCapabilities ( ) ) . toEqual ( {
266+ tools : { listChanged : false }
267+ } ) ;
268+ } ) ;
269+
270+ /***
271+ * Test: listChanged capability should default to true when not specified
272+ */
273+ test ( 'should default tools.listChanged to true when not explicitly set' , async ( ) => {
274+ const mcpServer = new McpServer ( {
275+ name : 'test server' ,
276+ version : '1.0'
277+ } ) ;
278+ const client = new Client ( {
279+ name : 'test client' ,
280+ version : '1.0'
281+ } ) ;
282+
283+ mcpServer . registerTool ( 'test' , { } , async ( ) => ( {
284+ content : [ { type : 'text' , text : 'Test' } ]
285+ } ) ) ;
286+
287+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
288+ await Promise . all ( [ client . connect ( clientTransport ) , mcpServer . connect ( serverTransport ) ] ) ;
289+
290+ const capabilities = client . getServerCapabilities ( ) ;
291+ expect ( capabilities ?. tools ?. listChanged ) . toBe ( true ) ;
292+ } ) ;
293+
294+ /***
295+ * Test: listChanged capability should respect explicit false setting
296+ */
297+ test ( 'should respect tools.listChanged: false when explicitly set' , async ( ) => {
298+ const mcpServer = new McpServer ( { name : 'test server' , version : '1.0' } , { capabilities : { tools : { listChanged : false } } } ) ;
299+ const client = new Client ( {
300+ name : 'test client' ,
301+ version : '1.0'
302+ } ) ;
303+
304+ mcpServer . registerTool ( 'test' , { } , async ( ) => ( {
305+ content : [ { type : 'text' , text : 'Test' } ]
306+ } ) ) ;
307+
308+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
309+ await Promise . all ( [ client . connect ( clientTransport ) , mcpServer . connect ( serverTransport ) ] ) ;
310+
311+ const capabilities = client . getServerCapabilities ( ) ;
312+ expect ( capabilities ?. tools ?. listChanged ) . toBe ( false ) ;
313+ } ) ;
314+
315+ /***
316+ * Test: resources.listChanged should respect explicit false setting
317+ */
318+ test ( 'should respect resources.listChanged: false when explicitly set' , async ( ) => {
319+ const mcpServer = new McpServer (
320+ {
321+ name : 'test server' ,
322+ version : '1.0'
323+ } ,
324+ { capabilities : { resources : { listChanged : false } } }
325+ ) ;
326+ const client = new Client ( {
327+ name : 'test client' ,
328+ version : '1.0'
329+ } ) ;
330+
331+ mcpServer . registerResource ( 'test-resource' , 'test://resource' , { } , async ( ) => ( {
332+ contents : [ { uri : 'test://resource' , text : 'Test' } ]
333+ } ) ) ;
334+
335+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
336+ await Promise . all ( [ client . connect ( clientTransport ) , mcpServer . connect ( serverTransport ) ] ) ;
337+
338+ const capabilities = client . getServerCapabilities ( ) ;
339+ expect ( capabilities ?. resources ?. listChanged ) . toBe ( false ) ;
340+ } ) ;
341+
342+ /***
343+ * Test: prompts.listChanged should respect explicit false setting
344+ */
345+ test ( 'should respect prompts.listChanged: false when explicitly set' , async ( ) => {
346+ const mcpServer = new McpServer ( { name : 'test server' , version : '1.0' } , { capabilities : { prompts : { listChanged : false } } } ) ;
347+ const client = new Client ( {
348+ name : 'test client' ,
349+ version : '1.0'
350+ } ) ;
351+
352+ mcpServer . registerPrompt ( 'test-prompt' , { } , async ( ) => ( {
353+ messages : [ { role : 'assistant' , content : { type : 'text' , text : 'Test' } } ]
354+ } ) ) ;
355+
356+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
357+ await Promise . all ( [ client . connect ( clientTransport ) , mcpServer . connect ( serverTransport ) ] ) ;
358+
359+ const capabilities = client . getServerCapabilities ( ) ;
360+ expect ( capabilities ?. prompts ?. listChanged ) . toBe ( false ) ;
361+ } ) ;
362+
363+ /***
364+ * Test: explicit false should suppress tool list changed notifications
365+ */
366+ test ( 'should not send tools list changed notifications when tools.listChanged is false' , async ( ) => {
367+ const notifications : Notification [ ] = [ ] ;
368+ const mcpServer = new McpServer ( { name : 'test server' , version : '1.0' } , { capabilities : { tools : { listChanged : false } } } ) ;
369+ const client = new Client ( {
370+ name : 'test client' ,
371+ version : '1.0'
372+ } ) ;
373+ client . fallbackNotificationHandler = async notification => {
374+ notifications . push ( notification ) ;
375+ } ;
376+
377+ mcpServer . registerTool ( 'test' , { } , async ( ) => ( {
378+ content : [ { type : 'text' , text : 'Test' } ]
379+ } ) ) ;
380+
381+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
382+ await Promise . all ( [ client . connect ( clientTransport ) , mcpServer . connect ( serverTransport ) ] ) ;
383+
384+ mcpServer . registerTool ( 'test-2' , { } , async ( ) => ( {
385+ content : [ { type : 'text' , text : 'Test 2' } ]
386+ } ) ) ;
387+
388+ await new Promise ( resolve => setTimeout ( resolve , 50 ) ) ;
389+
390+ expect ( notifications . filter ( notification => notification . method === 'notifications/tools/list_changed' ) ) . toHaveLength ( 0 ) ;
391+ } ) ;
392+
393+ /***
394+ * Test: explicit false should suppress resource list changed notifications
395+ */
396+ test ( 'should not send resources list changed notifications when resources.listChanged is false' , async ( ) => {
397+ const notifications : Notification [ ] = [ ] ;
398+ const mcpServer = new McpServer (
399+ {
400+ name : 'test server' ,
401+ version : '1.0'
402+ } ,
403+ { capabilities : { resources : { listChanged : false } } }
404+ ) ;
405+ const client = new Client ( {
406+ name : 'test client' ,
407+ version : '1.0'
408+ } ) ;
409+ client . fallbackNotificationHandler = async notification => {
410+ notifications . push ( notification ) ;
411+ } ;
412+
413+ mcpServer . registerResource ( 'test-resource' , 'test://resource' , { } , async ( ) => ( {
414+ contents : [ { uri : 'test://resource' , text : 'Test' } ]
415+ } ) ) ;
416+
417+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
418+ await Promise . all ( [ client . connect ( clientTransport ) , mcpServer . connect ( serverTransport ) ] ) ;
419+
420+ mcpServer . registerResource ( 'test-resource-2' , 'test://resource-2' , { } , async ( ) => ( {
421+ contents : [ { uri : 'test://resource-2' , text : 'Test 2' } ]
422+ } ) ) ;
423+
424+ await new Promise ( resolve => setTimeout ( resolve , 50 ) ) ;
425+
426+ expect ( notifications . filter ( notification => notification . method === 'notifications/resources/list_changed' ) ) . toHaveLength ( 0 ) ;
427+ } ) ;
428+
429+ /***
430+ * Test: explicit false should suppress prompt list changed notifications
431+ */
432+ test ( 'should not send prompts list changed notifications when prompts.listChanged is false' , async ( ) => {
433+ const notifications : Notification [ ] = [ ] ;
434+ const mcpServer = new McpServer ( { name : 'test server' , version : '1.0' } , { capabilities : { prompts : { listChanged : false } } } ) ;
435+ const client = new Client ( {
436+ name : 'test client' ,
437+ version : '1.0'
438+ } ) ;
439+ client . fallbackNotificationHandler = async notification => {
440+ notifications . push ( notification ) ;
441+ } ;
442+
443+ mcpServer . registerPrompt ( 'test-prompt' , { } , async ( ) => ( {
444+ messages : [ { role : 'assistant' , content : { type : 'text' , text : 'Test' } } ]
445+ } ) ) ;
446+
447+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
448+ await Promise . all ( [ client . connect ( clientTransport ) , mcpServer . connect ( serverTransport ) ] ) ;
449+
450+ mcpServer . registerPrompt ( 'test-prompt-2' , { } , async ( ) => ( {
451+ messages : [ { role : 'assistant' , content : { type : 'text' , text : 'Test 2' } } ]
452+ } ) ) ;
453+
454+ await new Promise ( resolve => setTimeout ( resolve , 50 ) ) ;
455+
456+ expect ( notifications . filter ( notification => notification . method === 'notifications/prompts/list_changed' ) ) . toHaveLength ( 0 ) ;
457+ } ) ;
255458 } ) ;
256459
257460 describe ( 'ResourceTemplate' , ( ) => {
0 commit comments