@@ -290,6 +290,95 @@ await Can_Handle_Requests(
290290 } ) ;
291291 }
292292
293+ #pragma warning disable MCPEXP001
294+ [ Fact ]
295+ public async Task Initialize_IncludesExtensionsInResponse ( )
296+ {
297+ await Can_Handle_Requests (
298+ serverCapabilities : new ServerCapabilities
299+ {
300+ Extensions = new Dictionary < string , object > { [ "io.myext" ] = new JsonObject { [ "required" ] = true } } ,
301+ } ,
302+ method : RequestMethods . Initialize ,
303+ configureOptions : null ,
304+ assertResult : ( _ , response ) =>
305+ {
306+ var result = JsonSerializer . Deserialize < InitializeResult > ( response , McpJsonUtilities . DefaultOptions ) ;
307+ Assert . NotNull ( result ) ;
308+ Assert . NotNull ( result . Capabilities . Extensions ) ;
309+ Assert . True ( result . Capabilities . Extensions . ContainsKey ( "io.myext" ) ) ;
310+ } ) ;
311+ }
312+
313+ [ Fact ]
314+ public async Task Initialize_IncludesExperimentalInResponse ( )
315+ {
316+ await Can_Handle_Requests (
317+ serverCapabilities : new ServerCapabilities
318+ {
319+ Experimental = new Dictionary < string , object > { [ "customFeature" ] = new JsonObject { [ "enabled" ] = true } } ,
320+ } ,
321+ method : RequestMethods . Initialize ,
322+ configureOptions : null ,
323+ assertResult : ( _ , response ) =>
324+ {
325+ var result = JsonSerializer . Deserialize < InitializeResult > ( response , McpJsonUtilities . DefaultOptions ) ;
326+ Assert . NotNull ( result ) ;
327+ Assert . NotNull ( result . Capabilities . Experimental ) ;
328+ Assert . True ( result . Capabilities . Experimental . ContainsKey ( "customFeature" ) ) ;
329+ } ) ;
330+ }
331+
332+ [ Fact ]
333+ public async Task Initialize_CopiesAllCapabilityProperties ( )
334+ {
335+ // Set every public property on ServerCapabilities to a non-null value.
336+ // If a new property is added to ServerCapabilities in the future but the
337+ // server fails to copy it, this test will fail as a reminder.
338+ var inputCapabilities = new ServerCapabilities
339+ {
340+ Experimental = new Dictionary < string , object > { [ "test" ] = new JsonObject ( ) } ,
341+ Logging = new LoggingCapability ( ) ,
342+ Prompts = new PromptsCapability ( ) ,
343+ Resources = new ResourcesCapability ( ) ,
344+ Tools = new ToolsCapability ( ) ,
345+ Completions = new CompletionsCapability ( ) ,
346+ Tasks = new McpTasksCapability ( ) ,
347+ Extensions = new Dictionary < string , object > { [ "io.test" ] = new JsonObject ( ) } ,
348+ } ;
349+
350+ await Can_Handle_Requests (
351+ serverCapabilities : inputCapabilities ,
352+ method : RequestMethods . Initialize ,
353+ configureOptions : options =>
354+ {
355+ // Tasks capability requires a TaskStore
356+ options . TaskStore = new InMemoryMcpTaskStore ( ) ;
357+ } ,
358+ assertResult : ( _ , response ) =>
359+ {
360+ var result = JsonSerializer . Deserialize < InitializeResult > ( response , McpJsonUtilities . DefaultOptions ) ;
361+ Assert . NotNull ( result ) ;
362+
363+ // Use reflection to verify every public property on ServerCapabilities is non-null.
364+ // This catches cases where new capability properties are added but not copied
365+ // from options in McpServerImpl.
366+ foreach ( var property in typeof ( ServerCapabilities ) . GetProperties ( BindingFlags . Public | BindingFlags . Instance ) )
367+ {
368+ if ( ! property . CanRead )
369+ {
370+ continue ;
371+ }
372+
373+ Assert . True (
374+ property . GetValue ( result . Capabilities ) is not null ,
375+ $ "ServerCapabilities.{ property . Name } was set on options but is null in the initialize response. " +
376+ $ "Ensure the property is copied in McpServerImpl's Configure* methods.") ;
377+ }
378+ } ) ;
379+ }
380+ #pragma warning restore MCPEXP001
381+
293382 [ Fact ]
294383 public async Task Can_Handle_Completion_Requests ( )
295384 {
0 commit comments