构建你的 MCP 能力层:.NET + SK 的系统方案

构建你的 MCP 能力层:.NET + SK 的系统方案 构建你的 MCP 能力层.NET SK 的系统方案引言在当今的 AI 应用开发中MCPModel Context Protocol正在成为连接大语言模型与外部工具、数据源的标准协议。它就像 USB 接口一样为 AI 系统提供了统一的“即插即用”能力扩展方式。而 Semantic KernelSK作为微软推出的轻量级 AI 编排框架天然支持 MCP 协议二者结合能让你快速构建一套灵活、可扩展的 MCP 能力层。本文将带你从实战角度出发使用 .NET 8 Semantic Kernel 构建一个完整的 MCP 能力层系统。我们会以“智能客服助手”为业务场景演示如何定义 MCP 能力、注册工具、并通过 SK 调用它们。—## 1. 什么是 MCP 能力层MCP 能力层是一个中间层负责管理、注册、路由和调用 AI 模型所需的工具与数据源。它的核心职责包括-工具注册将外部 API、数据库查询、文件操作等封装为 MCP 协议兼容的工具。-上下文管理维护对话历史、用户偏好、会话状态等信息。-动态路由根据用户意图自动选择合适的工具进行调用。-错误处理处理工具调用的超时、异常、重试等。在 .NET 生态中Semantic Kernel 提供了KernelFunction、Plugin、Memory等抽象天然支持 MCP 协议。我们可以利用这些组件快速搭建能力层。—## 2. 环境准备与项目搭建首先你需要安装 .NET 8 SDK。然后创建一个控制台应用bashdotnet new console -n McpCapabilityLayercd McpCapabilityLayerdotnet add package Microsoft.SemanticKerneldotnet add package Microsoft.SemanticKernel.Plugins.Memory接下来我们创建一个简单的配置类用于管理 AI 模型端点这里使用 OpenAI 兼容的模型如 Azure OpenAI 或本地 Ollamacsharp// Config.cspublic class Config{ public string ModelId { get; set; } gpt-4; public string Endpoint { get; set; } http://localhost:11434/v1; // Ollama 示例 public string ApiKey { get; set; } ollama; // 本地模型可用任意值}—## 3. 定义 MCP 能力创建 SK PluginMCP 能力在 SK 中表现为Plugin。每个 Plugin 包含多个KernelFunction这些函数就是暴露给 AI 模型的“工具”。下面我们创建一个CustomerSupportPlugin包含三个核心能力查询订单、创建工单、发送邮件。csharp// CustomerSupportPlugin.csusing Microsoft.SemanticKernel;using System.ComponentModel;public class CustomerSupportPlugin{ // 模拟订单数据 private static readonly Dictionarystring, string Orders new() { [ORD-001] 已发货预计3月10日送达, [ORD-002] 已签收签收人张三, [ORD-003] 待支付 }; /// summary /// 根据订单号查询订单状态 /// /summary [KernelFunction(get_order_status)] [Description(根据订单号查询订单的当前状态适用于用户询问订单进度)] [return: Description(订单状态描述字符串)] public string GetOrderStatus( [Description(订单号格式如ORD-001)] string orderId) { if (Orders.TryGetValue(orderId, out var status)) return $订单 {orderId} 的状态是{status}; return $未找到订单 {orderId}请检查订单号是否正确。; } /// summary /// 创建工单用于用户投诉或请求人工处理 /// /summary [KernelFunction(create_ticket)] [Description(当用户需要人工客服介入时创建一个工单记录问题)] [return: Description(工单编号)] public string CreateTicket( [Description(用户描述的问题内容)] string issueDescription, [Description(用户邮箱)] string userEmail) { // 模拟创建工单返回随机编号 var ticketId $TKT-{DateTime.Now:yyyyMMdd}-{Random.Shared.Next(1000, 9999)}; Console.WriteLine($[工单系统] 已创建工单 {ticketId}{issueDescription}通知邮箱{userEmail}); return $工单已创建编号为 {ticketId}我们将在24小时内回复您的邮箱 {userEmail}。; } /// summary /// 发送通知邮件模拟 /// /summary [KernelFunction(send_email)] [Description(发送邮件给用户用于重要通知如订单变更、退款确认等)] [return: Description(邮件发送结果)] public string SendEmail( [Description(收件人邮箱)] string toEmail, [Description(邮件主题)] string subject, [Description(邮件正文)] string body) { Console.WriteLine($[邮件系统] 发送邮件至 {toEmail}); Console.WriteLine($ 主题{subject}); Console.WriteLine($ 正文{body}); return $邮件已成功发送至 {toEmail}主题{subject}; }}关键点说明- 使用[KernelFunction]标记函数名称AI 模型通过此名称调用工具。- 使用[Description]提供语义描述帮助 AI 理解工具用途。- 参数也使用[Description]描述AI 会据此自动提取参数值。- 返回值同样用[Description]描述便于 AI 理解返回内容。—## 4. 构建 MCP 能力层核心编排逻辑现在我们创建一个MCPCapabilityLayer类负责初始化 SK、注册插件、处理用户消息并返回 AI 响应。这里我们使用 SK 的ChatCompletionService和FunctionChoiceBehavior来实现自动工具调用。csharp// MCPCapabilityLayer.csusing Microsoft.SemanticKernel;using Microsoft.SemanticKernel.ChatCompletion;using Microsoft.SemanticKernel.Connectors.OpenAI;public class MCPCapabilityLayer{ private readonly Kernel _kernel; private readonly IChatCompletionService _chatService; private readonly ChatHistory _chatHistory; public MCPCapabilityLayer(Config config) { // 1. 创建 Kernel 并配置 AI 服务 var builder Kernel.CreateBuilder() .AddOpenAIChatCompletion( modelId: config.ModelId, endpoint: new Uri(config.Endpoint), apiKey: config.ApiKey); // 2. 注册 MCP 能力Plugin builder.Plugins.AddFromObject(new CustomerSupportPlugin()); // 3. 可选注册内置插件如时间、记忆等 builder.Plugins.AddFromTypeMicrosoft.SemanticKernel.Plugins.Core.TimePlugin(); _kernel builder.Build(); _chatService _kernel.GetRequiredServiceIChatCompletionService(); _chatHistory new ChatHistory(); // 4. 设置系统提示词定义 AI 助手的行为边界 _chatHistory.AddSystemMessage( 你是一个专业的智能客服助手负责处理用户的咨询和请求。 你可以使用以下工具 - get_order_status查询订单状态 - create_ticket创建工单 - send_email发送邮件 - TimePlugin获取当前时间 注意 1. 如果用户要求查询订单请先确认订单号。 2. 创建工单时需要用户提供问题描述和邮箱。 3. 发送邮件需要收件人、主题和正文。 4. 如果用户输入不完整请礼貌地询问缺少的信息。 ); } /// summary /// 处理用户消息返回 AI 响应包含自动工具调用 /// /summary public async Taskstring ProcessUserMessage(string userMessage) { // 1. 添加用户消息到历史 _chatHistory.AddUserMessage(userMessage); // 2. 配置函数调用行为自动选择并执行工具 var executionSettings new OpenAIPromptExecutionSettings { FunctionChoiceBehavior FunctionChoiceBehavior.Auto(), // 自动模式 MaxTokens 1024, Temperature 0.3 }; // 3. 获取 AI 响应内部会自动调用工具并返回结果 var result await _chatService.GetChatMessageContentAsync( _chatHistory, executionSettings, _kernel); // 4. 将 AI 响应添加到历史 _chatHistory.AddMessage(result.Role, result.Content ?? ); return result.Content ?? 无响应; } /// summary /// 显示对话历史调试用 /// /summary public void ShowChatHistory() { Console.WriteLine(\n 对话历史 ); foreach (var msg in _chatHistory) { var role msg.Role AuthorRole.User ? 用户 : msg.Role AuthorRole.Assistant ? 助手 : 系统; Console.WriteLine($[{role}] {msg.Content}); } Console.WriteLine(\n); }}**核心机制解读**1.FunctionChoiceBehavior.Auto()这是 SK 的关键特性它告诉 AI 模型你可以自主决定是否需要调用工具。当用户问题需要调用工具时模型会发出函数调用请求SK 自动执行并返回结果然后模型基于结果生成最终回答。2.系统提示词我们明确定义了可用的工具列表和规则避免模型误用工具。3.对话历史维护通过ChatHistory对象维护上下文实现多轮对话。—## 5. 实战演示运行智能客服最后我们在Program.cs中编写入口代码模拟用户与 AI 助手的交互csharp// Program.csusing Microsoft.SemanticKernel;// 1. 初始化配置var config new Config{ ModelId llama3.2, // 使用 Ollama 本地模型 Endpoint http://localhost:11434/v1, ApiKey ollama};// 2. 创建 MCP 能力层实例var capabilityLayer new MCPCapabilityLayer(config);// 3. 模拟多轮对话Console.WriteLine( MCP 能力层 - 智能客服演示 \n);// 第一轮用户查询订单var userMsg1 我想查一下订单 ORD-001 的状态;Console.WriteLine($[用户] {userMsg1});var response1 await capabilityLayer.ProcessUserMessage(userMsg1);Console.WriteLine($[助手] {response1}\n);// 第二轮用户需要创建工单var userMsg2 我的订单 ORD-002 有问题请帮我创建一个工单我的邮箱是 testexample.com;Console.WriteLine($[用户] {userMsg2});var response2 await capabilityLayer.ProcessUserMessage(userMsg2);Console.WriteLine($[助手] {response2}\n);// 第三轮用户要求发送通知邮件var userMsg3 请给 admincompany.com 发送一封邮件主题是系统维护通知内容为系统将于今晚23:00-24:00进行维护。;Console.WriteLine($[用户] {userMsg3});var response3 await capabilityLayer.ProcessUserMessage(userMsg3);Console.WriteLine($[助手] {response3}\n);// 4. 显示完整对话历史capabilityLayer.ShowChatHistory();Console.WriteLine(演示结束按任意键退出...);Console.ReadKey();运行效果预期- 第一轮AI 调用get_order_status工具返回订单状态。- 第二轮AI 调用create_ticket工具创建工单并返回编号。- 第三轮AI 调用send_email工具模拟发送邮件。你可以在控制台看到类似输出 MCP 能力层 - 智能客服演示 [用户] 我想查一下订单 ORD-001 的状态[助手] 订单 ORD-001 的状态是已发货预计3月10日送达[用户] 我的订单 ORD-002 有问题请帮我创建一个工单...[工单系统] 已创建工单 TKT-20250309-5821...[助手] 工单已创建编号为 TKT-20250309-5821...[用户] 请给 admincompany.com 发送一封邮件...[邮件系统] 发送邮件至 admincompany.com...[助手] 邮件已成功发送至 admincompany.com...—## 6. 扩展与优化建议### 6.1 添加记忆能力使用 SK 的VolatileMemoryStore或QdrantMemoryStore实现长期记忆让 AI 记住用户偏好csharpbuilder.Services.AddSingletonIMemoryStore(new VolatileMemoryStore());var memory new SemanticTextMemory(storage, embeddingGenerator);builder.Plugins.AddFromObject(new TextMemoryPlugin(memory));### 6.2 实现动态工具注册从配置文件或数据库中动态加载 Plugin实现热插拔csharpvar pluginConfigs JsonSerializer.DeserializeListPluginConfig(File.ReadAllText(plugins.json));foreach (var pc in pluginConfigs){ var plugin Assembly.Load(pc.Assembly).CreateInstance(pc.TypeName) as object; builder.Plugins.AddFromObject(plugin);}### 6.3 错误处理与重试在KernelFunction内部添加异常捕获或使用 SK 的Filter机制统一处理csharp_builder.Functions.AddFilter(new FunctionFilter(async (context, next) { try { await next(); } catch (Exception ex) { context.Result new FunctionResult(context.Function, 工具调用失败请稍后重试); }}));—## 总结通过本文的实战演示我们成功使用 .NET 8 Semantic Kernel 构建了一个完整的 MCP 能力层系统。核心要点总结如下1.MCP 能力层的本质通过 Plugin 封装外部工具让 AI 模型能够“感知”和“操作”外部世界。2.SK 的关键抽象KernelFunction定义工具接口Plugin组织工具集合FunctionChoiceBehavior实现自动调用。3.最佳实践 - 使用详细的[Description]注释帮助 AI 理解工具用途。 - 通过系统提示词约束 AI 行为边界。 - 维护对话历史以实现上下文感知。4.扩展路径可以轻松集成记忆、动态注册、错误处理等高级特性。这套方案不仅适用于智能客服还可用于自动化运维、数据分析、内容生成等场景。MCP 协议 SK 的组合让你能够像搭积木一样快速构建 AI 应用的能力层是当前 .NET 生态中最推荐的 AI 集成方案之一。