Don't treat McpServerHandlers as an independent options type (#1313)

This commit is contained in:
Stephen Halter 2026-02-19 14:45:51 -08:00 • committed by GitHub
commit 411cef6ab0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 89 additions and 100 deletions

View file

@ -583,7 +583,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.ListResourceTemplatesHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.ListResourceTemplatesHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Resources ??= new();
});
return builder;
}
@ -616,7 +621,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.ListToolsHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.ListToolsHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Tools ??= new();
});
return builder;
}
@ -636,7 +646,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.CallToolHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.CallToolHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Tools ??= new();
});
return builder;
}
@ -669,7 +684,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.ListPromptsHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.ListPromptsHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Prompts ??= new();
});
return builder;
}
@ -684,7 +704,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.GetPromptHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.GetPromptHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Prompts ??= new();
});
return builder;
}
@ -705,7 +730,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.ListResourcesHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.ListResourcesHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Resources ??= new();
});
return builder;
}
@ -724,7 +754,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.ReadResourceHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.ReadResourceHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Resources ??= new();
});
return builder;
}
@ -743,7 +778,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.CompleteHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.CompleteHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Completions ??= new();
});
return builder;
}
@ -773,7 +813,13 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.SubscribeToResourcesHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.SubscribeToResourcesHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Resources ??= new();
options.Capabilities.Resources.Subscribe = true;
});
return builder;
}
@ -803,7 +849,13 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.UnsubscribeFromResourcesHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.UnsubscribeFromResourcesHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Resources ??= new();
options.Capabilities.Resources.Subscribe = true;
});
return builder;
}
@ -830,7 +882,12 @@ public static partial class McpServerBuilderExtensions
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.SetLoggingLevelHandler = handler);
builder.Services.Configure<McpServerOptions>(options =>
{
options.Handlers.SetLoggingLevelHandler = handler;
options.Capabilities ??= new();
options.Capabilities.Logging ??= new();
});
return builder;
}
#endregion

View file

@ -1,5 +1,4 @@
using Microsoft.Extensions.Options;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
namespace ModelContextProtocol;
@ -7,19 +6,17 @@ namespace ModelContextProtocol;
/// <summary>
/// Configures the McpServerOptions using addition services from DI.
/// </summary>
/// <param name="serverHandlers">The server handlers configuration options.</param>
/// <param name="serverTools">The individually registered tools.</param>
/// <param name="serverPrompts">The individually registered prompts.</param>
/// <param name="serverResources">The individually registered resources.</param>
internal sealed class McpServerOptionsSetup(
IOptions<McpServerHandlers> serverHandlers,
IEnumerable<McpServerTool> serverTools,
IEnumerable<McpServerPrompt> serverPrompts,
IEnumerable<McpServerResource> serverResources) : IConfigureOptions<McpServerOptions>
{
/// <summary>
/// Configures the given McpServerOptions instance by setting server information
/// and applying custom server handlers and tools.
/// and collecting registered server primitives.
/// </summary>
/// <param name="options">The options instance to be configured.</param>
public void Configure(McpServerOptions options)
@ -70,70 +67,5 @@ internal sealed class McpServerOptionsSetup(
{
options.ResourceCollection = resourceCollection;
}
// Apply custom server handlers.
OverwriteWithSetHandlers(serverHandlers.Value, options);
}
/// <summary>
/// Overwrite any handlers in McpServerOptions with non-null handlers from this instance.
/// </summary>
private static void OverwriteWithSetHandlers(McpServerHandlers handlers, McpServerOptions options)
{
McpServerHandlers optionsHandlers = options.Handlers;
PromptsCapability? promptsCapability = options.Capabilities?.Prompts;
if (handlers.ListPromptsHandler is not null || handlers.GetPromptHandler is not null)
{
promptsCapability ??= new();
optionsHandlers.ListPromptsHandler = handlers.ListPromptsHandler ?? optionsHandlers.ListPromptsHandler;
optionsHandlers.GetPromptHandler = handlers.GetPromptHandler ?? optionsHandlers.GetPromptHandler;
}
ResourcesCapability? resourcesCapability = options.Capabilities?.Resources;
if (handlers.ListResourceTemplatesHandler is not null || handlers.ListResourcesHandler is not null || handlers.ReadResourceHandler is not null)
{
resourcesCapability ??= new();
optionsHandlers.ListResourceTemplatesHandler = handlers.ListResourceTemplatesHandler ?? optionsHandlers.ListResourceTemplatesHandler;
optionsHandlers.ListResourcesHandler = handlers.ListResourcesHandler ?? optionsHandlers.ListResourcesHandler;
optionsHandlers.ReadResourceHandler = handlers.ReadResourceHandler ?? optionsHandlers.ReadResourceHandler;
}
if (handlers.SubscribeToResourcesHandler is not null || handlers.UnsubscribeFromResourcesHandler is not null)
{
resourcesCapability ??= new();
optionsHandlers.SubscribeToResourcesHandler = handlers.SubscribeToResourcesHandler ?? optionsHandlers.SubscribeToResourcesHandler;
optionsHandlers.UnsubscribeFromResourcesHandler = handlers.UnsubscribeFromResourcesHandler ?? optionsHandlers.UnsubscribeFromResourcesHandler;
resourcesCapability.Subscribe = true;
}
ToolsCapability? toolsCapability = options.Capabilities?.Tools;
if (handlers.ListToolsHandler is not null || handlers.CallToolHandler is not null)
{
toolsCapability ??= new();
optionsHandlers.ListToolsHandler = handlers.ListToolsHandler ?? optionsHandlers.ListToolsHandler;
optionsHandlers.CallToolHandler = handlers.CallToolHandler ?? optionsHandlers.CallToolHandler;
}
LoggingCapability? loggingCapability = options.Capabilities?.Logging;
if (handlers.SetLoggingLevelHandler is not null)
{
loggingCapability ??= new();
optionsHandlers.SetLoggingLevelHandler = handlers.SetLoggingLevelHandler;
}
CompletionsCapability? completionsCapability = options.Capabilities?.Completions;
if (handlers.CompleteHandler is not null)
{
completionsCapability ??= new();
optionsHandlers.CompleteHandler = handlers.CompleteHandler;
}
options.Capabilities ??= new();
options.Capabilities.Prompts = promptsCapability;
options.Capabilities.Resources = resourcesCapability;
options.Capabilities.Tools = toolsCapability;
options.Capabilities.Logging = loggingCapability;
options.Capabilities.Completions = completionsCapability;
}
}