MCP for .NET:能够真正做事的 AI 代理
Source: Dev.to
Crysta 是一款 AI 应用,您可以为真实的业务场景构建自己的 AI 代理。
与普通聊天机器人不同,您可以连接不同的 MCP 服务器,为您的代理赋予实用功能,如日程安排、预订以及数据访问。简而言之,Crysta 帮助您构建一个不仅能聊天、还能真正完成工作的 AI 代理。
用户可以连接的内容
- Google 日历工作流
- 预订和排程系统
- 通过 MCP 暴露的业务数据工具
- 类似 DeepWiki 的知识工具(通过 MCP)
因此,代理不仅只能回答诸如“预订会议”之类的请求,还可以通过已连接的工具实际执行该操作。
为什么这对 .NET 开发者很重要
MCP 为 .NET 开发者提供了一种直接的方式,将真实功能添加到 AI 代理,而无需自行构建每个集成。与其将每个 API 直接接入你的应用,不如连接 MCP 兼容的工具,让代理通过相同的函数调用流程使用它们。
好处
- 更快的开发速度: 新功能来自添加 MCP 工具,而不是编写新的集成。
- 更清晰的架构: 你的代理通过添加工具而成长,而不是通过增加更多提示逻辑或自定义胶水代码。
我们是如何构建的(高层概述)
- 用户向代理添加 MCP 服务器链接。
- 系统验证链接并读取工具元数据。
- 已连接的 MCP 工具成为该代理可用操作的一部分。
- 在聊天过程中,模型可以在需要时调用这些工具。
- 失败和连接健康状况会被跟踪,以便用户快速修复失效的链接。
我们使用的包
ModelContextProtocolMicrosoft.Extensions.AIMicrosoft.Extensions.AI.OpenAIAzure.AI.OpenAI
这种组合在 .NET 中提供了 MCP 工具发现以及稳健的函数调用管道。
小型代码示例(基于我们的代码)
1) MCP 客户端 + 验证服务
using ModelContextProtocol.Client;
public class McpServerService : IMcpServerService
{
public async Task ValidateAndGetMcpInfoAsync(string mcpUrl)
{
if (!Uri.TryCreate(mcpUrl, UriKind.Absolute, out _))
{
return new StoredMcpServer { IsValid = false, ErrorMessage = "Invalid URL format" };
}
try
{
var transport = new HttpClientTransport(
new HttpClientTransportOptions { Endpoint = new Uri(mcpUrl) },
loggerFactory: null);
var client = await McpClient.CreateAsync(transport);
var serverInfo = client.ServerInfo;
return new StoredMcpServer
{
Url = mcpUrl,
Title = serverInfo?.Name ?? "Unknown MCP Server",
Description = serverInfo?.Title ?? "No description available",
AddedDate = DateTime.Now,
IsValid = serverInfo is not null
};
}
catch (Exception ex)
{
return new StoredMcpServer { IsValid = false, ErrorMessage = ex.Message };
}
}
public async Task CreateClientAsync(string mcpUrl, CancellationToken cancellationToken = default)
{
var transport = new HttpClientTransport(
new HttpClientTransportOptions { Endpoint = new Uri(mcpUrl) },
loggerFactory: null);
return await McpClient.CreateAsync(transport);
}
}
2) 在运行时从代理技能加载 MCP 工具
using Microsoft.Extensions.AI;
using ModelContextProtocol.Client;
private async Task> GetMcpToolsAsync()
{
if (interactiveAgent?.Skills == null) return [];
var allTools = new List();
using var scope = ServiceScopeFactory.CreateScope();
var mcpServerService = scope.ServiceProvider.GetRequiredService();
foreach (var skill in interactiveAgent.Skills)
{
if (skill.SkillType != SkillType.MCP) continue;
if (skill.SkillJson is null) continue;
var check = await mcpServerService.ValidateAndGetMcpInfoAsync(skill.SkillJson);
if (!check.IsValid) continue;
var client = await mcpServerService.CreateClientAsync(skill.SkillJson);
var tools = await client.ListToolsAsync();
allTools.AddRange(tools);
}
return allTools;
}
3) 将 MCP 工具附加到 Microsoft.Extensions.AI 聊天管道
using System.ClientModel;
using Azure.AI.OpenAI;
using Microsoft.Extensions.AI;
var azureChatClient = new AzureOpenAIClient(
new Uri(endpoint),
new ApiKeyCredential(apiKey))
.GetChatClient(deployment)
.AsIChatClient();
var mcpTools = await GetMcpToolsAsync();
var chatClient = new ChatClientBuilder(azureChatClient)
.ConfigureOptions(options =>
{
options.Tools ??= [];
foreach (var tool in mcpTools)
{
options.Tools.Add(tool);
}
})
.UseFunctionInvocation(c => c.AllowConcurrentInvocation = true)
.Build();
这正是我们使用的思路:验证 MCP 链接、发现工具,然后将这些工具传递给聊天客户端,使代理能够调用它们。
Closing
MCP 将我们的产品从“能回答的 AI”转变为“能行动的 AI”。
这就是用户立刻注意到的区别。
如果你想看到最终结果,请在此查看: