Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 68 additions & 11 deletions src/ModelContextProtocol/McpServerBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,12 @@ public static IMcpServerBuilder WithListResourceTemplatesHandler(this IMcpServer
{
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;
}

Expand Down Expand Up @@ -616,7 +621,12 @@ public static IMcpServerBuilder WithListToolsHandler(this IMcpServerBuilder buil
{
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;
}

Expand All @@ -636,7 +646,12 @@ public static IMcpServerBuilder WithCallToolHandler(this IMcpServerBuilder build
{
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;
}

Expand Down Expand Up @@ -669,7 +684,12 @@ public static IMcpServerBuilder WithListPromptsHandler(this IMcpServerBuilder bu
{
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;
}

Expand All @@ -684,7 +704,12 @@ public static IMcpServerBuilder WithGetPromptHandler(this IMcpServerBuilder buil
{
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;
}

Expand All @@ -705,7 +730,12 @@ public static IMcpServerBuilder WithListResourcesHandler(this IMcpServerBuilder
{
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;
}

Expand All @@ -724,7 +754,12 @@ public static IMcpServerBuilder WithReadResourceHandler(this IMcpServerBuilder b
{
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;
}

Expand All @@ -743,7 +778,12 @@ public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder build
{
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;
}

Expand Down Expand Up @@ -773,7 +813,13 @@ public static IMcpServerBuilder WithSubscribeToResourcesHandler(this IMcpServerB
{
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;
}

Expand Down Expand Up @@ -803,7 +849,13 @@ public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpSer
{
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;
}

Expand All @@ -830,7 +882,12 @@ public static IMcpServerBuilder WithSetLoggingLevelHandler(this IMcpServerBuilde
{
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
Expand Down
70 changes: 1 addition & 69 deletions src/ModelContextProtocol/McpServerOptionsSetup.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
using Microsoft.Extensions.Options;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;

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)
Expand Down Expand Up @@ -70,70 +67,5 @@ public void Configure(McpServerOptions options)
{
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public void WithListToolsHandler_Sets_Handler()
_builder.Object.WithListToolsHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.ListToolsHandler);
Assert.Equal(handler, options.Handlers.ListToolsHandler);
}

[Fact]
Expand All @@ -39,9 +39,9 @@ public void WithCallToolHandler_Sets_Handler()
_builder.Object.WithCallToolHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.CallToolHandler);
Assert.Equal(handler, options.Handlers.CallToolHandler);
}

[Fact]
Expand All @@ -52,9 +52,9 @@ public void WithListPromptsHandler_Sets_Handler()
_builder.Object.WithListPromptsHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.ListPromptsHandler);
Assert.Equal(handler, options.Handlers.ListPromptsHandler);
}

[Fact]
Expand All @@ -65,9 +65,9 @@ public void WithGetPromptHandler_Sets_Handler()
_builder.Object.WithGetPromptHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.GetPromptHandler);
Assert.Equal(handler, options.Handlers.GetPromptHandler);
}

[Fact]
Expand All @@ -78,9 +78,9 @@ public void WithListResourceTemplatesHandler_Sets_Handler()
_builder.Object.WithListResourceTemplatesHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.ListResourceTemplatesHandler);
Assert.Equal(handler, options.Handlers.ListResourceTemplatesHandler);
}

[Fact]
Expand All @@ -91,9 +91,9 @@ public void WithListResourcesHandler_Sets_Handler()
_builder.Object.WithListResourcesHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.ListResourcesHandler);
Assert.Equal(handler, options.Handlers.ListResourcesHandler);
}

[Fact]
Expand All @@ -104,9 +104,9 @@ public void WithReadResourceHandler_Sets_Handler()
_builder.Object.WithReadResourceHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.ReadResourceHandler);
Assert.Equal(handler, options.Handlers.ReadResourceHandler);
}

[Fact]
Expand All @@ -117,9 +117,9 @@ public void WithCompleteHandler_Sets_Handler()
_builder.Object.WithCompleteHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.CompleteHandler);
Assert.Equal(handler, options.Handlers.CompleteHandler);
}

[Fact]
Expand All @@ -130,9 +130,9 @@ public void WithSubscribeToResourcesHandler_Sets_Handler()
_builder.Object.WithSubscribeToResourcesHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.SubscribeToResourcesHandler);
Assert.Equal(handler, options.Handlers.SubscribeToResourcesHandler);
}

[Fact]
Expand All @@ -143,8 +143,8 @@ public void WithUnsubscribeFromResourcesHandler_Sets_Handler()
_builder.Object.WithUnsubscribeFromResourcesHandler(handler);

var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
var options = serviceProvider.GetRequiredService<IOptions<McpServerOptions>>().Value;

Assert.Equal(handler, options.UnsubscribeFromResourcesHandler);
Assert.Equal(handler, options.Handlers.UnsubscribeFromResourcesHandler);
}
}
Loading