高运 發表於 2025-4-15 11:42:55

.NET MCP 文档详细指南

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">MCP 概述</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">MCP 的主要特点</a></li><li><a href="#_lab2_0_1">MCP 服务器</a></li><li><a href="#_lab2_0_2">MCP 客户端</a></li></ul><li><a href="#_label1">.NET MCP 实现项目对比</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_3">官方 C# SDK:csharp-sdk</a></li><li><a href="#_lab2_1_4">MCPSharp</a></li><li><a href="#_lab2_1_5">mcpdotnet</a></li></ul><li><a href="#_label2">服务器端实现</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_6">基本结构</a></li><li><a href="#_lab2_2_7">工具注册与实现</a></li><li><a href="#_lab2_2_8">服务配置</a></li></ul><li><a href="#_label3">客户端实现</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_9">连接到 MCP 服务器</a></li><li><a href="#_lab2_3_10">工具调用</a></li><li><a href="#_lab2_3_11">与 Claude 模型集成</a></li></ul><li><a href="#_label4">Cursor 配置与集成</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_12">MCP Server 添加步骤</a></li><li><a href="#_lab2_4_13">传输类型配置</a></li><li><a href="#_lab2_4_14">工具使用示例:</a></li></ul><li><a href="#_label5">最佳实践与示例</a></li><ul class="second_class_ul"><li><a href="#_lab2_5_15">服务器端最佳实践</a></li><li><a href="#_lab2_5_16">客户端最佳实践</a></li><li><a href="#_lab2_5_17">集成示例</a></li></ul><li><a href="#_label6">结论</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>MCP 概述</h2>
<p>MCP(Model Context Protocol)是由 Anthropic 推出的一种开放协议,类似 AI 的 USB-C 扩展坞,用于在大模型和数据源之间建立安全的通信(授权),让 AI 应用能够安全地访问和操作本地或远程数据,例如操作本地文件、浏览器和 Web 服务。</p>
<p>为了更好地理解 MCP,我们可以用一个简单的类比:如果把 AI 比作电脑主机,那么 MCP 就相当于 USB 协议,而 MCP Server 则类似于各种 USB 设备(如摄像头、麦克风等)。通过实现 MCP Server,我们可以让 AI 轻松连接到各种数据源,大大扩展其功能范围。</p>
<p>MCP 协议的核心价值在于标准化了 AI 模型与外部工具和数据源的交互方式,使开发者能够创建可被多种 AI 应用程序使用的工具和服务。这种标准化的接口极大地简化了 AI 应用的开发过程,并提高了工具和服务的可重用性。</p>
<p class="maodian"><a name="_lab2_0_0"></a></p><h3>MCP 的主要特点</h3>
<ul><li>标准化的工具调用接口</li><li>安全的双向通信</li><li>支持多种传输方式(stdio、SSE、WebSocket 等)</li><li>丰富的数据类型支持</li><li>与主流 LLM 的无缝集成</li><li>跨平台和跨语言支持</li></ul>
<p class="maodian"><a name="_lab2_0_1"></a></p><h3>MCP 服务器</h3>
<p>MCP 服务器是实现 MCP 协议的服务端,负责注册和提供工具,处理客户端的工具调用请求,并返回结果。服务器可以使用多种传输方式与客户端通信,如标准输入输出、SSE 或 WebSocket。</p>
<p class="maodian"><a name="_lab2_0_2"></a></p><h3>MCP 客户端</h3>
<p>MCP 客户端是实现 MCP 协议的客户端,负责连接到 MCP 服务器,获取可用工具列表,调用工具,并处理返回结果。客户端通常与 LLM 集成,使 LLM 能够使用 MCP 工具。</p>
<p class="maodian"><a name="_label1"></a></p><h2>.NET MCP 实现项目对比</h2>
<p>在 .NET 生态系统中,目前有几个主要的 MCP 实现项目,它们各有特点。以下是这些项目的对比分析:</p>
<p class="maodian"><a name="_lab2_1_3"></a></p><h3>官方 C# SDK:csharp-sdk</h3>
<p>这是 Model Context Protocol(MCP)官方提供的 C# SDK,为 MCP 服务器和客户端提供简单易用的接口,主要由微软维护。该项目已经成为 MCP 社区的官方 SDK 项目,最近发布了 0.1.0-preview 版本。</p>
<p><strong>GitHub 仓库:</strong>&nbsp;</p>
<p><code>https://github.com/modelcontextprotocol/csharp-sdk</code></p>
<p class="maodian"><a name="_lab2_1_4"></a></p><h3>MCPSharp</h3>
<p>MCPSharp 是一个 .NET 库,旨在帮助开发者构建 Model Context Protocol(MCP)服务器和客户端。它提供了创建 MCP 合规的工具和函数、连接现有 MCP 服务器、将 .NET 方法暴露为 MCP 端点、处理 MCP 协议细节和 JSON-RPC 通信等功能。</p>
<p>特点:</p>
<ul><li>与 Microsoft.Extensions.AI 集成</li><li>Semantic Kernel 支持</li><li>动态工具注册</li><li>工具变更通知</li><li>复杂对象参数支持</li><li>错误处理</li><li>易用的基于属性的 API</li><li>内置 JSON-RPC 支持</li><li>自动参数验证和类型转换</li></ul>
<p><strong>GitHub 仓库:</strong>&nbsp;</p>
<p><code>https://github.com/afrise/MCPSharp</code></p>
<p class="maodian"><a name="_lab2_1_5"></a></p><h3>mcpdotnet</h3>
<p>mcpdotnet 是一个 .NET 实现的模型上下文协议(MCP),使 .NET 应用程序能够与 MCP 客户端和服务器进行交互。该项目已经进入归档状态,相关的开发工作都集中到了官方的 csharp-sdk。</p>
<p>特点:</p>
<ul><li>支持多种 MCP 功能</li><li>遵循规范的实现</li><li>提供全面的日志支持</li><li>兼容 .NET 8.0 及以上版本</li></ul>
<p><strong>GitHub 仓库:</strong>&nbsp;</p>
<p><code>https://github.com/PederHP/mcpdotnet</code></p>
<p>ModelContextProtocol.NET</p>
<p>ModelContextProtocol.NET 是一个 C# SDK,实现了模型上下文协议(MCP)。</p>
<p>特点:</p>
<ul><li>标准输入输出通信</li><li>工具集成框架</li><li>原生 AOT 兼容</li><li>计算器演示实现</li><li>开发中功能:WebSocket 支持、资源管理和提示系统</li></ul>
<p><strong>GitHub仓库:</strong></p>
<pre><code>https://github.com/salty-flower/ModelContextProtocol.NET</code></pre>
<p class="maodian"><a name="_label2"></a></p><h2>服务器端实现</h2>
<p class="maodian"><a name="_lab2_2_6"></a></p><h3>基本结构</h3>
<p>使用官方的 C# SDK (csharp-sdk) 实现 MCP 服务器的基本结构如下:</p>
<p>这段代码展示了如何创建一个基本的 MCP 服务器,它使用标准输入输出(stdio)作为传输方式,并自动注册当前程序集中的所有工具。</p>
<p>关键组件说明:</p>
<p><code>AddMcpServer()</code></p>
<p>&nbsp;- 向依赖注入容器添加 MCP 服务器服务</p>
<p><code>WithStdioServerTransport()</code></p>
<p>&nbsp;- 配置服务器使用标准输入输出作为传输方式</p>
<p><code>WithToolsFromAssembly()</code></p>
<p>&nbsp;- 自动注册当前程序集中的所有 MCP 工具</p>
<p class="maodian"><a name="_lab2_2_7"></a></p><h3>工具注册与实现</h3>
<p>在 MCP 服务器中,工具是通过特性(Attribute)来注册的。下面是一个简单的工具实现示例:</p>
<div class="jb51code"><pre class="brush:csharp;">
public static class EchoTool
{
   
    public static string Echo(string message) =&gt; $"hello {message}";
}</pre></div>
<p>更复杂的工具可以使用依赖注入和服务器交互:</p>
<p>在 QuickstartWeatherServer 示例中,我们可以看到更实际的工具实现:</p>
<div class="jb51code"><pre class="brush:csharp;">
public static class WeatherTools
{
   
    public static async Task GetAlerts(
      HttpClient client,
       string state)
    {
      var jsonElement = await client.GetFromJsonAsync($"/alerts/active/area/{state}");
      var alerts = jsonElement.GetProperty("features").EnumerateArray();
      if (!alerts.Any())
      {
            return "No active alerts for this state.";
      }
      return string.Join("\n-\n", alerts.Select(alert =&gt;
      {
            JsonElement properties = alert.GetProperty("properties");
            return $"""
                Event: {properties.GetProperty("event").GetString()}
                """;
      }));
    }
}</pre></div>
<p>工具注册特性说明: <code></code></p>
<p>&nbsp;- 标记一个类包含 MCP 工具</p>
<p><code></code></p>
<p>&nbsp;- 标记一个方法作为 MCP 工具</p>
<p><code></code></p>
<p>&nbsp;- 提供工具和参数的描述信息</p>
<p class="maodian"><a name="_lab2_2_8"></a></p><h3>服务配置</h3>
<p>MCP 服务器的配置主要通过 .NET 的依赖注入系统完成。以下是一个配置 HttpClient 的示例:</p>
<div class="jb51code"><pre class="brush:csharp;">builder.Services.AddSingleton(_ =&gt;
{
    var client = new HttpClient() { BaseAddress = new Uri("https://api.weather.gov") };
    client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("weather-tool", "1.0"));
    return client;
});</pre></div>
<p>高级配置选项:</p>
<ul><li>自定义传输方式:除了标准的 stdio 传输方式,还可以配置 SSE 或 WebSocket 传输</li><li>工具过滤:可以选择性地注册特定的工具,而不是注册所有工具</li><li>中间件:可以添加自定义中间件来处理请求和响应</li><li>错误处理:可以配置全局错误处理策略</li><li>日志记录:可以配置详细的日志记录选项</li></ul>
<p class="maodian"><a name="_label3"></a></p><h2>客户端实现</h2>
<p class="maodian"><a name="_lab2_3_9"></a></p><h3>连接到 MCP 服务器</h3>
<p>使用官方的 C# SDK 连接到 MCP 服务器的基本代码如下:</p>
<div class="jb51code"><pre class="brush:csharp;">var mcpClient = await McpClientFactory.CreateAsync(new()
{
    Id = "demo-server",
    Name = "Demo Server",
    TransportType = TransportTypes.StdIo,
    TransportOptions = new()
    {
      ["command"] = command,
      ["arguments"] = arguments,
    }
});</pre></div>
<p>这段代码创建了一个 MCP 客户端,并连接到指定的服务器。<code>TransportType</code>&nbsp;指定了通信方式(这里是标准输入输出),<code>TransportOptions</code>&nbsp;提供了额外的配置选项。</p>
<p>支持的传输类型: <code>TransportTypes.Stdio</code></p>
<p>&nbsp;- 使用标准输入输出进行通信</p>
<p><code>TransportTypes.Sse</code></p>
<p>&nbsp;- 使用服务器发送事件 (SSE) 进行通信</p>
<p><code>TransportTypes.WebSocket</code></p>
<p>&nbsp;- 使用 WebSocket 进行通信</p>
<p class="maodian"><a name="_lab2_3_10"></a></p><h3>工具调用</h3>
<p>连接到服务器后,客户端可以列出可用的工具并调用它们:</p>
<div class="jb51code"><pre class="brush:csharp;">var tools = await mcpClient.ListToolsAsync();
foreach (var tool in tools)
{
    Console.WriteLine($"Connected to server with tools: {tool.Name}");
}
// 调用工具示例
var result = await mcpClient.CallToolAsync(
    "echo",
    new Dictionary() { ["message"] = "Hello MCP!" },
    CancellationToken.None);
// 输出结果
Console.WriteLine(result.Content.First(c =&gt; c.Type == "text").Text);</pre></div>
<p>工具调用参数说明: <code>toolName</code></p>
<p>&nbsp;- 要调用的工具名称</p>
<p><code>parameters</code></p>
<p>&nbsp;- 工具参数字典,键为参数名,值为参数值</p>
<p><code>cancellationToken</code></p>
<p>&nbsp;- 取消令牌,用于取消操作</p>
<p>结果处理:</p>
<p>工具调用结果包含一个&nbsp;<code>Content</code>&nbsp;集合,每个内容项都有一个&nbsp;<code>Type</code>&nbsp;和一个&nbsp;<code>Text</code>。常见的内容类型包括:</p>
<p><code>text</code></p>
<p>&nbsp;- 纯文本内容</p>
<p><code>application/json</code></p>
<p>&nbsp;- JSON 格式的内容</p>
<p><code>image/*</code></p>
<p>&nbsp;- 图像内容(如 image/png、image/jpeg 等)</p>
<p class="maodian"><a name="_lab2_3_11"></a></p><h3>与 Claude 模型集成</h3>
<p>MCP 客户端可以与 Claude 等 AI 模型集成,使模型能够使用 MCP 工具:</p>
<div class="jb51code"><pre class="brush:csharp;">var anthropicClient = new AnthropicClient(new APIAuthentication(builder.Configuration["ANTHROPIC_API_KEY"]))
    .Messages
    .AsBuilder()
    .UseFunctionInvocation()
    .Build();
var options = new ChatOptions
{
    MaxOutputTokens = 1000,
    ModelId = "claude-3-5-sonnet-20240229",
    Tools = [.. tools]
};
// 使用 Claude 模型处理用户查询
await foreach (var message in anthropicClient.GetStreamingResponseAsync(query, options))
{
    Console.Write(message);
}</pre></div>
<p>集成步骤说明:</p>
<ul><li>创建 Anthropic 客户端并配置 API 密钥</li><li>启用函数调用功能</li><li>创建聊天选项,包括模型 ID、最大输出令牌数和工具列表</li><li>使用流式响应 API 处理用户查询</li><li>处理模型返回的消息,包括工具调用和文本响应</li></ul>
<p class="maodian"><a name="_label4"></a></p><h2>Cursor 配置与集成</h2>
<p class="maodian"><a name="_lab2_4_12"></a></p><h3>MCP Server 添加步骤</h3>
<p>在 Cursor 中配置 MCP Server 的步骤如下:</p>
<ul><li>导航至&nbsp;<code>Cursor Settings</code>&nbsp;&gt;&nbsp;<code>Features</code>&gt;&nbsp;<code>MCP</code></li><li>点击<code>+ Add New MCP Server</code>按钮</li><li>在配置窗口中:<ul><li>选择传输类型</li><li>配置服务器信息</li></ul></li><li>完成添加后,服务器将显示在 MCP 服务器列表中</li><li>如需更新工具列表,可能需要手动点击刷新按钮</li></ul>
<p>Cursor MCP 服务器配置界面示例</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202504/202504151131109.png" /></p>
<p class="maodian"><a name="_lab2_4_13"></a></p><h3>传输类型配置</h3>
<p>Cursor 支持两种主要的传输类型:</p>
<p>stdio</p>
<p>用于标准输入输出通信,适用于本地运行的 MCP 服务器。</p>
<p>配置方式:输入可执行命令<br />示例:</p>
<div class="jb51code"><pre class="brush:bash;">npx -y @smithery/cli@latest run @mzxrai/mcp-webresearch --config "{}"</pre></div>
<p>sse</p>
<p>用于服务器发送事件通信,适用于远程 MCP 服务器。</p>
<p>配置方式:输入服务器 URL<br />示例:</p>
<div class="jb51code"><pre class="brush:plain;">https://example.com/mcp</pre></div>
<p>工具使用方法</p>
<p>在 Cursor 的 Composer 中使用 MCP 工具时,你可以:</p>
<ul><li>让 Composer Agent 自动选择合适的工具</li><li>明确指定使用特定工具</li><li>查看工具调用的详细信息</li><li>对工具调用进行管理:<ul><li>检查调用参数</li><li>决定是否批准调用</li><li>查看调用结果</li></ul></li></ul>
<p class="maodian"><a name="_lab2_4_14"></a></p><h3>工具使用示例:</h3>
<p>用户:&nbsp;搜索关键词 cursor mcp server,列出 Top 5 热度的关键词</p>
<p>Claude:&nbsp;我将使用 Web Search 工具来搜索这些关键词。</p>
<div class="jb51code"><pre class="brush:plain;">工具调用:Web Search
参数:{"query": "cursor mcp server"}</pre></div>
<p>Claude:&nbsp;根据搜索结果,关于 &quot;cursor mcp server&quot; 的 Top 5 热度关键词是:</p>
<p>Model Context Protocol (MCP) Integration</p>
<p>Custom MCP Server Development</p>
<p>MCP Server Templates</p>
<p>Database Integration</p>
<p>Desktop Application Integration</p>
<p class="maodian"><a name="_label5"></a></p><h2>最佳实践与示例</h2>
<p class="maodian"><a name="_lab2_5_15"></a></p><h3>服务器端最佳实践</h3>
<p><strong>使用依赖注入:</strong></p>
<p>利用 .NET 的依赖注入系统管理服务和工具的依赖关系。</p>
<p><strong>适当的错误处理:</strong></p>
<p>确保工具实现中包含适当的错误处理逻辑。</p>
<p><strong>详细的工具描述:</strong></p>
<p>使用<code>Description</code>特性为工具和参数提供清晰的描述。</p>
<p><strong>模块化设计:</strong></p>
<p>将不同功能的工具分组到不同的类中。</p>
<p class="maodian"><a name="_lab2_5_16"></a></p><h3>客户端最佳实践</h3>
<p><strong>异步操作:</strong></p>
<p>使用异步方法处理 MCP 客户端的所有操作。</p>
<p><strong>资源管理:</strong></p>
<p>确保适当释放客户端资源。</p>
<p><strong>错误处理:</strong></p>
<p>实现适当的错误处理逻辑,处理服务器连接和工具调用中可能出现的问题。</p>
<p><strong>用户体验:</strong></p>
<p>提供清晰的用户反馈,特别是在工具调用过程中。</p>
<p class="maodian"><a name="_lab2_5_17"></a></p><h3>集成示例</h3>
<p>以下是一个将 MCP 客户端与 Claude 模型集成的完整示例:</p>
<div class="jb51code"><pre class="brush:java;">using Anthropic.SDK;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol.Transport;
using System.ComponentModel;
var builder = Host.CreateApplicationBuilder(args);
builder.Configuration
    .AddEnvironmentVariables()
    .AddUserSecrets();
var (command, arguments) = GetCommandAndArguments(args);
await using var mcpClient = await McpClientFactory.CreateAsync(new()
{
    Id = "demo-server",
    Name = "Demo Server",
    TransportType = TransportTypes.StdIo,
    TransportOptions = new()
    {
      ["command"] = command,
      ["arguments"] = arguments,
    }
});
var tools = await mcpClient.ListToolsAsync();
foreach (var tool in tools)
{
    Console.WriteLine($"Connected to server with tools: {tool.Name}");
}
var anthropicClient = new AnthropicClient(new APIAuthentication(builder.Configuration["ANTHROPIC_API_KEY"]))
    .Messages
    .AsBuilder()
    .UseFunctionInvocation()
    .Build();
var options = new ChatOptions
{
    MaxOutputTokens = 1000,
    ModelId = "claude-3-5-sonnet-20240229",
    Tools = [.. tools]
};
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("MCP Client Started!");
Console.ResetColor();
PromptForInput();
while(Console.ReadLine() is string query &amp;&amp; !("exit".Equals(query, StringComparison.OrdinalIgnoreCase)))
{
    if (string.IsNullOrWhiteSpace(query))
    {
      PromptForInput();
      continue;
    }
    await foreach (var message in anthropicClient.GetStreamingResponseAsync(query, options))
    {
      Console.Write(message);
    }
    Console.WriteLine();
    PromptForInput();
}
static void PromptForInput()
{
    // 提示用户输入
}
static (string, string) GetCommandAndArguments(string[] args)
{
    // 解析命令行参数
}</pre></div>
<p>这个示例展示了如何创建 MCP 客户端,连接到服务器,获取可用工具,并将这些工具与 Claude 模型集成,使模型能够使用这些工具来响应用户查询。</p>
<p class="maodian"><a name="_label6"></a></p><h2>结论</h2>
<p>本文档详细介绍了 .NET 使用 MCP 的相关内容,包括服务器端实现、客户端实现以及 Cursor 集成配置等方面。通过使用 MCP,开发者可以创建强大的工具和服务,使 AI 模型能够安全地访问和操作各种数据源。</p>
<p>随着 MCP 生态系统的不断发展,我们可以期待更多的功能和改进。官方的 C# SDK 提供了一个稳定的基础,使 .NET 开发者能够轻松地实现 MCP 服务器和客户端。</p>
<p>我们鼓励开发者探索 MCP 的各种可能性,创建创新的工具和服务,并为 MCP 社区做出贡献。</p>
頁: [1]
查看完整版本: .NET MCP 文档详细指南