diff --git a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Extensions/McpServerBuilderExtensions.cs b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Extensions/McpServerBuilderExtensions.cs
index d7c88bc6ffa6..23769319767a 100644
--- a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Extensions/McpServerBuilderExtensions.cs
+++ b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Extensions/McpServerBuilderExtensions.cs
@@ -60,23 +60,36 @@ public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, Kernel
}
///
- /// Adds a resource template to the server.
+ /// Adds a prompt definition and handlers for listing and reading prompts.
///
/// The MCP server builder.
- /// The resource template definition.
+ /// The prompt definition.
/// The builder instance.
- public static IMcpServerBuilder WithPrompt(this IMcpServerBuilder builder, PromptDefinition templateDefinition)
+ public static IMcpServerBuilder WithPrompt(this IMcpServerBuilder builder, PromptDefinition promptDefinition)
{
- PromptRegistry.RegisterPrompt(templateDefinition);
+ // Register the prompt definition in the DI container
+ builder.Services.AddSingleton(promptDefinition);
+
+ builder.WithPromptHandlers();
+
+ return builder;
+ }
- builder.WithListPromptsHandler(PromptRegistry.HandlerListPromptRequestsAsync);
- builder.WithGetPromptHandler(PromptRegistry.HandlerGetPromptRequestsAsync);
+ ///
+ /// Adds handlers for listing and reading prompts.
+ ///
+ /// The MCP server builder.
+ /// The builder instance.
+ public static IMcpServerBuilder WithPromptHandlers(this IMcpServerBuilder builder)
+ {
+ builder.WithListPromptsHandler(HandleListPromptRequestsAsync);
+ builder.WithGetPromptHandler(HandleGetPromptRequestsAsync);
return builder;
}
///
- /// Adds a resource template to the server.
+ /// Adds a resource template and handlers for listing and reading resource templates.
///
/// The MCP server builder.
/// The kernel instance.
@@ -95,23 +108,36 @@ public static IMcpServerBuilder WithResourceTemplate(
}
///
- /// Adds a resource template to the server.
+ /// Adds a resource template and handlers for listing and reading resource templates.
///
/// The MCP server builder.
/// The resource template definition.
/// The builder instance.
public static IMcpServerBuilder WithResourceTemplate(this IMcpServerBuilder builder, ResourceTemplateDefinition templateDefinition)
{
- ResourceRegistry.RegisterResourceTemplate(templateDefinition);
+ // Register the resource template definition in the DI container
+ builder.Services.AddSingleton(templateDefinition);
+
+ builder.WithResourceTemplateHandlers();
+
+ return builder;
+ }
- builder.WithListResourceTemplatesHandler(ResourceRegistry.HandleListResourceTemplatesRequestAsync);
- builder.WithReadResourceHandler(ResourceRegistry.HandleReadResourceRequestAsync);
+ ///
+ /// Adds handlers for listing and reading resource templates.
+ ///
+ /// The MCP server builder.
+ /// The builder instance.
+ public static IMcpServerBuilder WithResourceTemplateHandlers(this IMcpServerBuilder builder)
+ {
+ builder.WithListResourceTemplatesHandler(HandleListResourceTemplatesRequestAsync);
+ builder.WithReadResourceHandler(HandleReadResourceRequestAsync);
return builder;
}
///
- /// Adds a resource to the server.
+ /// Adds a resource and handlers for listing and reading resources.
///
/// The MCP server builder.
/// The kernel instance.
@@ -130,18 +156,117 @@ public static IMcpServerBuilder WithResource(
}
///
- /// Adds a resource to the server.
+ /// Adds a resource and handlers for listing and reading resources.
///
/// The MCP server builder.
/// The resource definition.
/// The builder instance.
public static IMcpServerBuilder WithResource(this IMcpServerBuilder builder, ResourceDefinition resourceDefinition)
{
- ResourceRegistry.RegisterResource(resourceDefinition);
+ // Register the resource definition in the DI container
+ builder.Services.AddSingleton(resourceDefinition);
+
+ builder.WithResourceHandlers();
+
+ return builder;
+ }
- builder.WithListResourcesHandler(ResourceRegistry.HandleListResourcesRequestAsync);
- builder.WithReadResourceHandler(ResourceRegistry.HandleReadResourceRequestAsync);
+ ///
+ /// Adds handlers for listing and reading resources.
+ ///
+ /// The MCP server builder.
+ /// The builder instance.
+ public static IMcpServerBuilder WithResourceHandlers(this IMcpServerBuilder builder)
+ {
+ builder.WithListResourcesHandler(HandleListResourcesRequestAsync);
+ builder.WithReadResourceHandler(HandleReadResourceRequestAsync);
return builder;
}
+
+ private static Task HandleListPromptRequestsAsync(RequestContext context, CancellationToken cancellationToken)
+ {
+ // Get and return all prompt definitions registered in the DI container
+ IEnumerable promptDefinitions = context.Server.Services!.GetServices();
+
+ return Task.FromResult(new ListPromptsResult
+ {
+ Prompts = [.. promptDefinitions.Select(d => d.Prompt)]
+ });
+ }
+
+ private static async Task HandleGetPromptRequestsAsync(RequestContext context, CancellationToken cancellationToken)
+ {
+ // Make sure the prompt name is provided
+ if (context.Params?.Name is not string { } promptName || string.IsNullOrEmpty(promptName))
+ {
+ throw new ArgumentException("Prompt name is required.");
+ }
+
+ // Get all prompt definitions registered in the DI container
+ IEnumerable promptDefinitions = context.Server.Services!.GetServices();
+
+ // Look up the prompt definition
+ PromptDefinition? definition = promptDefinitions.FirstOrDefault(d => d.Prompt.Name == promptName);
+ if (definition is null)
+ {
+ throw new ArgumentException($"No handler found for the prompt '{promptName}'.");
+ }
+
+ // Invoke the handler
+ return await definition.Handler(context, cancellationToken);
+ }
+
+ private static Task HandleReadResourceRequestAsync(RequestContext context, CancellationToken cancellationToken)
+ {
+ // Make sure the uri of the resource or resource template is provided
+ if (context.Params?.Uri is not string { } resourceUri || string.IsNullOrEmpty(resourceUri))
+ {
+ throw new ArgumentException("Resource uri is required.");
+ }
+
+ // Look up in registered resource first
+ IEnumerable resourceDefinitions = context.Server.Services!.GetServices();
+
+ ResourceDefinition? resourceDefinition = resourceDefinitions.FirstOrDefault(d => d.Resource.Uri == resourceUri);
+ if (resourceDefinition is not null)
+ {
+ return resourceDefinition.InvokeHandlerAsync(context, cancellationToken);
+ }
+
+ // Look up in registered resource templates
+ IEnumerable resourceTemplateDefinitions = context.Server.Services!.GetServices();
+
+ foreach (var resourceTemplateDefinition in resourceTemplateDefinitions)
+ {
+ if (resourceTemplateDefinition.IsMatch(resourceUri))
+ {
+ return resourceTemplateDefinition.InvokeHandlerAsync(context, cancellationToken);
+ }
+ }
+
+ throw new ArgumentException($"No handler found for the resource uri '{resourceUri}'.");
+ }
+
+ private static Task HandleListResourceTemplatesRequestAsync(RequestContext context, CancellationToken cancellationToken)
+ {
+ // Get and return all resource template definitions registered in the DI container
+ IEnumerable definitions = context.Server.Services!.GetServices();
+
+ return Task.FromResult(new ListResourceTemplatesResult
+ {
+ ResourceTemplates = [.. definitions.Select(d => d.ResourceTemplate)]
+ });
+ }
+
+ private static Task HandleListResourcesRequestAsync(RequestContext context, CancellationToken cancellationToken)
+ {
+ // Get and return all resource template definitions registered in the DI container
+ IEnumerable definitions = context.Server.Services!.GetServices();
+
+ return Task.FromResult(new ListResourcesResult
+ {
+ Resources = [.. definitions.Select(d => d.Resource)]
+ });
+ }
}
diff --git a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Prompts/PromptRegistry.cs b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Prompts/PromptRegistry.cs
deleted file mode 100644
index 062983dab3ba..000000000000
--- a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Prompts/PromptRegistry.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using ModelContextProtocol.Protocol.Types;
-using ModelContextProtocol.Server;
-
-namespace MCPServer.Prompts;
-
-///
-/// Represents the prompt registry that contains the prompt definitions and provides the handlers for the prompt `List` and `Get` requests.
-///
-internal static class PromptRegistry
-{
- private static readonly Dictionary s_definitions = new();
-
- ///
- /// Registers a prompt definition.
- ///
- /// The prompt definition to register.
- public static void RegisterPrompt(PromptDefinition definition)
- {
- if (s_definitions.ContainsKey(definition.Prompt.Name))
- {
- throw new ArgumentException($"A prompt with the name '{definition.Prompt.Name}' is already registered.");
- }
-
- s_definitions[definition.Prompt.Name] = definition;
- }
-
- ///
- /// Handles the `Get` prompt requests.
- ///
- /// The request context.
- /// The cancellation token.
- /// The result of the `Get` prompt request.
- public static async Task HandlerGetPromptRequestsAsync(RequestContext context, CancellationToken cancellationToken)
- {
- // Make sure the prompt name is provided
- if (context.Params?.Name is not string { } promptName || string.IsNullOrEmpty(promptName))
- {
- throw new ArgumentException("Prompt name is required.");
- }
-
- // Look up the prompt handler
- if (!s_definitions.TryGetValue(promptName, out PromptDefinition? definition))
- {
- throw new ArgumentException($"No handler found for the prompt '{promptName}'.");
- }
-
- // Invoke the handler
- return await definition.Handler(context, cancellationToken);
- }
-
- ///
- /// Handles the `List` prompt requests.
- ///
- /// Context of the request.
- /// The cancellation token.
- /// The result of the `List` prompt request.
- public static Task HandlerListPromptRequestsAsync(RequestContext context, CancellationToken cancellationToken)
- {
- return Task.FromResult(new ListPromptsResult
- {
- Prompts = [.. s_definitions.Values.Select(d => d.Prompt)]
- });
- }
-}
diff --git a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Resources/ResourceRegistry.cs b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Resources/ResourceRegistry.cs
deleted file mode 100644
index ea2a89eef594..000000000000
--- a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Resources/ResourceRegistry.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using ModelContextProtocol.Protocol.Types;
-using ModelContextProtocol.Server;
-
-namespace MCPServer.Resources;
-
-///
-/// Represents the resource registry that contains the resource and resource template definitions and provides the handlers for the `List` and `Get` requests.
-///
-internal static class ResourceRegistry
-{
- private static readonly Dictionary s_resourceDefinitions = [];
-
- private static readonly IList s_resourceTemplateDefinitions = [];
-
- ///
- /// Registers a resource.
- ///
- /// The resource to register.
- public static void RegisterResource(ResourceDefinition definition)
- {
- if (s_resourceDefinitions.ContainsKey(definition.Resource.Uri))
- {
- throw new ArgumentException($"A resource with the uri '{definition.Resource.Uri}' is already registered.");
- }
-
- s_resourceDefinitions[definition.Resource.Uri] = definition;
- }
-
- ///
- /// Registers a resource template.
- ///
- /// The resource template to register.
- public static void RegisterResourceTemplate(ResourceTemplateDefinition definition)
- {
- if (s_resourceTemplateDefinitions.Any(d => d.ResourceTemplate.UriTemplate == definition.ResourceTemplate.UriTemplate))
- {
- throw new ArgumentException($"A resource template with the uri template '{definition.ResourceTemplate.UriTemplate}' is already registered.");
- }
-
- s_resourceTemplateDefinitions.Add(definition);
- }
-
- ///
- /// Handles the `ListResourceTemplates` request.
- ///
- /// The MCP server context.
- /// The cancellation token.
- /// The result of the request.
- public static Task HandleListResourceTemplatesRequestAsync(RequestContext context, CancellationToken cancellationToken)
- {
- return Task.FromResult(new ListResourceTemplatesResult
- {
- ResourceTemplates = [.. s_resourceTemplateDefinitions.Select(d => d.ResourceTemplate)]
- });
- }
-
- ///
- /// Handles the `ListResources` request.
- ///
- /// The MCP server context.
- /// The cancellation token.
- /// The result of the request.
- public static Task HandleListResourcesRequestAsync(RequestContext context, CancellationToken cancellationToken)
- {
- return Task.FromResult(new ListResourcesResult
- {
- Resources = [.. s_resourceDefinitions.Values.Select(d => d.Resource)]
- });
- }
-
- ///
- /// Handles the `ReadResource` request.
- ///
- /// The MCP server context.
- /// The cancellation token.
- /// The result of the request.
- public static Task HandleReadResourceRequestAsync(RequestContext context, CancellationToken cancellationToken)
- {
- // Make sure the uri of the resource or resource template is provided
- if (context.Params?.Uri is not string { } resourceUri || string.IsNullOrEmpty(resourceUri))
- {
- throw new ArgumentException("Resource uri is required.");
- }
-
- // Look up in registered resource first
- if (s_resourceDefinitions.TryGetValue(resourceUri, out ResourceDefinition? resourceDefinition))
- {
- return resourceDefinition.InvokeHandlerAsync(context, cancellationToken);
- }
-
- // Look up in registered resource templates
- foreach (var resourceTemplateDefinition in s_resourceTemplateDefinitions)
- {
- if (resourceTemplateDefinition.IsMatch(resourceUri))
- {
- return resourceTemplateDefinition.InvokeHandlerAsync(context, cancellationToken);
- }
- }
-
- throw new ArgumentException($"No handler found for the resource uri '{resourceUri}'.");
- }
-}
diff --git a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Resources/ResourceTemplateDefinition.cs b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Resources/ResourceTemplateDefinition.cs
index f3f7736f5f9f..d7455c3a7010 100644
--- a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Resources/ResourceTemplateDefinition.cs
+++ b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Resources/ResourceTemplateDefinition.cs
@@ -57,10 +57,6 @@ public async Task InvokeHandlerAsync(RequestContext()
- ?? throw new InvalidOperationException("Kernel is not available.");
-
this.Kernel
??= context.Server.Services?.GetRequiredService()
?? throw new InvalidOperationException("Kernel is not available.");