
根据 MCP 协议的规定在 MCP 协议中有以下对象MCP Hosts: 如 Claude Desktop、IDE 或 AI 工具希望通过 MCP 访问数据的程序MCP Clients: 维护与服务器一对一连接的协议客户端MCP Servers: 轻量级程序通过标准的 Model Context Protocol 提供特定能力本地数据源: MCP 服务器可安全访问的计算机文件、数据库和服务远程服务: MCP 服务器可连接的互联网上的外部系统如通过 APIsMCP Host 就是一个 AI 应用跟用户交互的应用程序一般是桌面程序而 MCP Host 跟 MCP Client 可能是放在一起做的自身即与用户交互也具有直接调用 MCP Server 的能力。MCP Server 就是提供 Tool 、资源内容、提示词、对话补全等功能的服务端MCP Server 的功能或职责是多种多样的比如高德地图 MCP Server 只提供了 Tool即接口调用。本地数据源、远程服务者两个跟 MCP 本身没有关联而是 MCP Server 自身实现功能的一部分或者说是支撑 MCP Server 的基础设施和外部依赖。由于 MCP 概念和功能比较多因此笔者将一步步使用案例和项目的方式讲解其中的细节建议读者将示例项目仓库拉下来根据本文教程尝试自行编写代码以及跑通案例。核心概念MCP 协议定义了以下功能模块ResourcesPromptsToolsSamplingRootsTransports由于 Roots 没有多少案例并且 C# 的 SDK 还没有完善因此本文只介绍其它功能模块。本文知识并不是线性讲解以上 MCP 功能。TransportTransport 指传输处理消息发送和接收的底层机制MCP 主要包含两个标准传输实现标准输入输出 (stdio)主要对象是本地集成和命令行工具使用 stdio 传输通过标准输入和输出流进行通信服务器发送事件 (SSE)SSE 传输通过 HTTP POST 请求长连接实现服务器到客户端的流式通信当然还有一个 Streamable 但是由于社区支持还不算完善并且本文也不讲解。以下是 MCPModel Context Protocol协议中stdio、sse、streamable三者的优缺点和差异的简要说明stdio优点平台兼容性高stdio标准输入输出是操作系统底层的功能几乎所有操作系统和编程语言都支持。简单直接用于进程间通信通常是脚本和命令行工具的通信方式易于实现。缺点缺乏高级功能stdio只能处理简单的文本和二进制数据流没有内建的消息结构或格式。不适合在网络环境中的实时交互stdio对于网络通信来说不够灵活和可靠通常用于本地通信。sse优点实时更新**允许服务器通过HTTP连接主动向客户端发送更新消息适合实时推送的应用场景。简单实现基于HTTP协议不需要复杂的传输层协议客户端通过 EventSource API 可以很容易地接收。轻量级相比WebSocketSSE更轻量级适合简单的消息推送场景。缺点单向通信只能服务器向客户端发送消息客户端如果需要发送消息必须通过标准的HTTP请求回服务器。连接限制浏览器对同时建立的SSE连接数限制较严格不适合大量连接的应用场景。streamable优点效率高可以处理大数据或连续的数据流不需要等待整个数据集传输完毕。实时性好可以在数据生成时逐步传输在数据消费时逐步处理提高实时响应能力。灵活性高**支持长时间的连接和传输适合视频、音频、实时数据库同步等应用。缺点复杂性高实现和管理流式传输协议、处理数据流的逻辑复杂度较高需要确保数据的顺序和完整性。资源消耗长时间的连接和持续的数据传输可能会消耗较多的服务器和网络资源需要优化处理。ModelContextProtocol CSharp 中提供了三种 Transport 其核心代码在三个类中StdioClientTransportSseClientTransportStreamClientTransport下面笔者将会详细讲解 stdio、sse 两种 Transport。stdio通过本地进程间通信实现客户端以子进程形式启动 MCP Server 程序双方通过stdin/stdout交换 JSON-RPC 消息传输每条消息时以换行符分隔。本节示例项目参考 TransportStdioServer、TransportStdioClient。当使用 stdio 时McpServer 只需要实现静态方法并配置特性注解即可然后需要将该程序编译为.exe。TransportStdioServer 添加 Tool 后面讲解 Tool 这里先跳过。[McpServerToolType] public class EchoTool { [McpServerTool, Description(Echoes the message back to the client.)] public static string Echo(string message) $hello {message}; }然后创建 MCP Server 服务并使用WithStdioServerTransport()暴露接口能力。using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using TransportStdioServer; var builder Host.CreateApplicationBuilder(args); builder.Services.AddMcpServer() .WithStdioServerTransport() .WithToolsEchoTool(); builder.Logging.AddConsole(options { options.LogToStandardErrorThreshold LogLevel.Trace; }); await builder.Build().RunAsync();编译 TransportStdioServer 项目在 Windows 下会生成.exe文件复制.exe文件的绝对路径在编写 Client 时要用。C# 编写 Client 时需要通过命令行参数导入.exe文件示例如下using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using ModelContextProtocol.Client; using ModelContextProtocol.Protocol.Transport; var builder Host.CreateApplicationBuilder(args); builder.Configuration .AddEnvironmentVariables() .AddUserSecretsProgram(); var clientTransport new StdioClientTransport(new() { Name Demo Server, // 要使用绝对路径这里笔者省略了 Command E:/../../TransportStdioServer.exe }); await using var mcpClient await McpClientFactory.CreateAsync(clientTransport); var tools await mcpClient.ListToolsAsync(); foreach (var tool in tools) { Console.WriteLine($Connected to server with tools: {tool.Name}); }启动 TransportStdioClient控制台会打印 TransportStdioServer 中的所有 Mcp tool。StdioClientTransport 原理是基于命令行参数启动 TransportStdioServerStdioClient 会将命令行参数拼接起来然后以子进程方式启动 MCP Server命令行示例cmd.exe/c E:/../TransportStdioServer.exeStdioClientTransport 核心代码启动子进程SSE本节参考示例项目TransportSseServer、TransportSseClient。SSE 是通过 HTTP 长连接实现远程通信的在使用各种 AI 对话应用时AI 会像打字机一样逐个输出字符这种通过 HTTP 长连接、由 HTTP Server 服务器持续推送内容的方式就叫 sse。SSE Server 需提供两个端点/sseGET请求建立长连接接收服务器推送的事件流。/messagesPOST请求客户端发送请求至该端点。在 TransportSseServer 实现简单的 EchoTool。[McpServerToolType] public sealed class EchoTool { [McpServerTool, Description(Echoes the input back to the client.)] public static string Echo(string message) { return hello message; } }配置 MCP Server 支持 SSEusing TransportSseServer.Tools; var builder WebApplication.CreateBuilder(args); builder.Services.AddMcpServer() .WithHttpTransport() .WithToolsEchoTool() .WithToolsSampleLlmTool(); var app builder.Build(); app.MapMcp(); app.Run(http://0.0.0.0:5000);TransportSseClient 实现客户端连接 Mcp Server其代码非常简单连接到 MCP Server 后将对方支持的 Tool 列出来。using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using ModelContextProtocol.Client; using ModelContextProtocol.Protocol.Transport; var defaultOptions new McpClientOptions { ClientInfo new() { Name IntegrationTestClient, Version 1.0.0 } }; var defaultConfig new SseClientTransportOptions { Endpoint new Uri($http://localhost:5000/sse), Name Everything, }; // Create client and run tests await using var client await McpClientFactory.CreateAsync( new SseClientTransport(defaultConfig), defaultOptions, loggerFactory: NullLoggerFactory.Instance); var tools await client.ListToolsAsync(); foreach (var tool in tools) { Console.WriteLine($Connected to server with tools: {tool.Name}); }