Model context protocol server prompts with microsoft semantic kernel
This post focuses on implementing server prompts, a key feature of the Model Context Protocol (MCP) designed for reusable template definitions. We will explore how to implement these server prompts using both the MCP C# SDK and Semantic Kernel for enhanced templating capabilities. Further details on MCP server prompts can be found in the MCP documentation. MCP Server Prompts via MCP C# SDK Attributes MCP C# SDK allows for defining prompts through attributes. This method offers a direct implementation without requiring Semantic Kernel for basic string manipulation as the following example shows. [McpServerPromptType] internal sealed class StringFormatPrompt { private readonly string _format; private readonly ILogger _logger; public StringFormatPrompt(ILogger logger) { _logger = logger; _format = "Tell a joke about {0}."; } [McpServerPrompt(Name = "Joke"), Description("Tell a joke about a topic.")] public IReadOnlyCollection Format([Description("The topic of the joke.")] string topic) { _logger.LogInformation("Generating prompt with topic: {Topic}", topic); var content = string.Format(CultureInfo.InvariantCulture, _format, topic); return [ new (ChatRole.User, content) ]; } } // Register for the prompt var serverBuilder = builder.Services.AddMcpServer() .WithHttpTransport() .WithPrompts(); Semantic Kernel Templates as MCP Server Prompts Semantic Kernel provides templating capabilities through JSON/YAML, Handlebars, and Liquid formats, along with plugin support. These templates can be exposed as MCP prompts using the MCP C# SDK. Prompt Templates in Semantic Kernel Semantic Kernel templates are configured with PromptTemplateConfig, created by IPromptTemplateFactory implementations, and can be easily rendered with input variables for dynamic prompt generation. var templateConfig = new PromptTemplateConfig("Tell a joke about {{$topic}}."); IPromptTemplateFactory templateFactory = new KernelPromptTemplateFactory(); var template = templateFactory.Create(templateConfig); var text = await template.RenderAsync(kernel, new KernelArguments { { "topic", "cats" } }); Expose prompts as McpServerPrompt McpServerPrompt is the abstract base class that represents an MCP prompt we can implement. internal sealed class TemplateServerPrompt : McpServerPrompt { public TemplateServerPrompt(PromptTemplateConfig promptTemplateConfig, IPromptTemplateFactory? promptTemplateFactory, ILoggerFactory? loggerFactory) { promptTemplateFactory ??= new KernelPromptTemplateFactory(loggerFactory ?? NullLoggerFactory.Instance); _template = promptTemplateFactory.Create(promptTemplateConfig); // MCP prompt ProtocolPrompt = new() { Name = promptTemplateConfig.Name ?? _template.GetType().Name, Description = promptTemplateConfig.Description, Arguments = promptTemplateConfig.InputVariables .Select(inputVariable => new PromptArgument { Name = inputVariable.Name, Description = inputVariable.Description, Required = inputVariable.IsRequired }) .ToList(), }; } public override async ValueTask GetAsync(RequestContext request, CancellationToken cancellationToken = default) { KernelArguments? arguments = default; var dictionary = request.Params?.Arguments; if (dictionary is not null) { arguments = new (); foreach (var (key, value) in dictionary) { arguments[key] = value; } } var kernel = request.Services?.GetService() ?? new Kernel(); var text = await _template.RenderAsync(kernel, arguments, cancellationToken); return new GetPromptResult { Messages = [ new PromptMessage { Content = new Content { Text = text } } ] }; } } // Register for the prompt with DI and MCP server // builder.Services.AddSingleton(...) var serverBuilder = builder.Services.AddMcpServer() .WithHttpTransport(); serverBuilder.Services.AddSingleton(provider => provider.GetRequiredService()); Exposing AIFunction as McpServerPrompt The McpServerPrompt class provides a Create method to expose a Microsoft.Extensions.AI.AIFunction as an MCP server prompt. internal sealed class TemplateAIFunction : AIFunction { //... protected override async ValueTask InvokeCoreAsync(AIFunctionArguments arguments, CancellationToken cancellationToken) { KernelArguments kernelArguments = []; foreach (var argument in arguments) { kernelArgume

This post focuses on implementing server prompts, a key feature of the Model Context Protocol (MCP) designed for reusable template definitions. We will explore how to implement these server prompts using both the MCP C# SDK and Semantic Kernel for enhanced templating capabilities. Further details on MCP server prompts can be found in the MCP documentation.
MCP Server Prompts via MCP C# SDK Attributes
MCP C# SDK allows for defining prompts through attributes. This method offers a direct implementation without requiring Semantic Kernel for basic string manipulation as the following example shows.
[McpServerPromptType]
internal sealed class StringFormatPrompt
{
private readonly string _format;
private readonly ILogger _logger;
public StringFormatPrompt(ILogger<StringFormatPrompt> logger)
{
_logger = logger;
_format = "Tell a joke about {0}.";
}
[McpServerPrompt(Name = "Joke"), Description("Tell a joke about a topic.")]
public IReadOnlyCollection<ChatMessage> Format([Description("The topic of the joke.")] string topic)
{
_logger.LogInformation("Generating prompt with topic: {Topic}", topic);
var content = string.Format(CultureInfo.InvariantCulture, _format, topic);
return [
new (ChatRole.User, content)
];
}
}
// Register for the prompt
var serverBuilder = builder.Services.AddMcpServer()
.WithHttpTransport()
.WithPrompts<StringFormatPrompt>();
Semantic Kernel Templates as MCP Server Prompts
Semantic Kernel provides templating capabilities through JSON/YAML, Handlebars, and Liquid formats, along with plugin support. These templates can be exposed as MCP prompts using the MCP C# SDK.
-
Prompt Templates in Semantic Kernel
Semantic Kernel templates are configured with PromptTemplateConfig, created by IPromptTemplateFactory implementations, and can be easily rendered with input variables for dynamic prompt generation.
var templateConfig = new PromptTemplateConfig("Tell a joke about {{$topic}}."); IPromptTemplateFactory templateFactory = new KernelPromptTemplateFactory(); var template = templateFactory.Create(templateConfig); var text = await template.RenderAsync(kernel, new KernelArguments { { "topic", "cats" } });
-
Expose prompts as McpServerPrompt
McpServerPrompt is the abstract base class that represents an MCP prompt we can implement.
internal sealed class TemplateServerPrompt : McpServerPrompt { public TemplateServerPrompt(PromptTemplateConfig promptTemplateConfig, IPromptTemplateFactory? promptTemplateFactory, ILoggerFactory? loggerFactory) { promptTemplateFactory ??= new KernelPromptTemplateFactory(loggerFactory ?? NullLoggerFactory.Instance); _template = promptTemplateFactory.Create(promptTemplateConfig); // MCP prompt ProtocolPrompt = new() { Name = promptTemplateConfig.Name ?? _template.GetType().Name, Description = promptTemplateConfig.Description, Arguments = promptTemplateConfig.InputVariables .Select(inputVariable => new PromptArgument { Name = inputVariable.Name, Description = inputVariable.Description, Required = inputVariable.IsRequired }) .ToList(), }; } public override async ValueTask<GetPromptResult> GetAsync(RequestContext<GetPromptRequestParams> request, CancellationToken cancellationToken = default) { KernelArguments? arguments = default; var dictionary = request.Params?.Arguments; if (dictionary is not null) { arguments = new (); foreach (var (key, value) in dictionary) { arguments[key] = value; } } var kernel = request.Services?.GetService<Kernel>() ?? new Kernel(); var text = await _template.RenderAsync(kernel, arguments, cancellationToken); return new GetPromptResult { Messages = [ new PromptMessage { Content = new Content { Text = text } } ] }; } } // Register for the prompt with DI and MCP server // builder.Services.AddSingleton
(...) var serverBuilder = builder.Services.AddMcpServer() .WithHttpTransport(); serverBuilder.Services.AddSingleton<McpServerPrompt>(provider => provider.GetRequiredService<TemplateServerPrompt>()); -
Exposing AIFunction as McpServerPrompt
The McpServerPrompt class provides a Create method to expose a Microsoft.Extensions.AI.AIFunction as an MCP server prompt.
internal sealed class TemplateAIFunction : AIFunction { //... protected override async ValueTask<object?> InvokeCoreAsync(AIFunctionArguments arguments, CancellationToken cancellationToken) { KernelArguments kernelArguments = []; foreach (var argument in arguments) { kernelArguments[argument.Key] = argument.Value; } var kernel = arguments.Services?.GetService<Kernel>() ?? new Kernel(); var text = await _template.RenderAsync(kernel, kernelArguments, cancellationToken); return text; } } // Register for the prompt with DI and MCP server // builder.Services.AddSingleton
(...) var serverBuilder = builder.Services.AddMcpServer() .WithHttpTransport(); serverBuilder.Services.AddSingleton<McpServerPrompt>(provider => McpServerPrompt.Create(provider.GetRequiredService<TemplateServerPrompt>()));
Please feel free to reach out on twitter @roamingcode