MCP C# SDK

Model Context Protocol 的官方 C# SDK,可让 .NET 应用程序、服务和库实现 MCP 客户端与服务端及两者的交互。有关可用功能的更多详细信息,请访问我们的 API 文档。

该SDK包含三个核心包:

  • ModelContextProtocol NuGet 预览版 - 包含托管和依赖注入扩展的主要软件包。适用于大多数不需要 HTTP 服务器功能的项目。本 README 文件即为此软件包的文档。
  • ModelContextProtocol.AspNetCore NuGet 预览版 - 用于基于 HTTP 的 MCP 服务端的库。
  • ModelContextProtocol.Core NuGet 预览版 - 适用于仅需使用客户端或底层服务端 API,且希望依赖项最少的用户

备注

该项目处于预览阶段,可能会在没有事先通知的情况下引入破坏性变更。


关于MCP

模型上下文协议(Model Context Protocol,简称 MCP)是一种开放协议,用于规范应用程序向大语言模型(LLMs)提供上下文的方式。它实现了 LLM 与各种数据源和工具之间的安全集成。

有关 MCP 的更多信息:

安装

请从NuGet安装该程序包以开始使用。

dotnet add package ModelContextProtocol --prerelease

客户端快速入门

要开始编写客户端,需使用 McpClientFactory.CreateAsync 方法来实例化 IMcpClient 并将其连接到服务端。获得 IMcpClient 实例后,即可通过其进行交互操作,例如枚举所有可用工具并调用这些工具。

var clientTransport = new StdioClientTransport(new StdioClientTransportOptions
{
    Name = "Everything",
    Command = "npx",
    Arguments = ["-y", "@modelcontextprotocol/server-everything"],
});

var client = await McpClientFactory.CreateAsync(clientTransport);

// Print the list of tools available from the server.
foreach (var tool in await client.ListToolsAsync())
{
    Console.WriteLine($"{tool.Name} ({tool.Description})");
}

// Execute a tool (this would normally be driven by LLM tool invocations).
var result = await client.CallToolAsync(
    "echo",
    new Dictionary<string, object?>() { ["message"] = "Hello MCP!" },
    cancellationToken:CancellationToken.None);

// echo always returns one and only one text content object
Console.WriteLine(result.Content.First(c => c.Type == "text").Text);

您可以在 samples 目录中找到展示如何将 ModelContextProtocol 与 LLM SDK 结合使用的示例,也可以参考 tests 项目获取更多实例。更多示例和文档将在近期陆续添加。

客户端可连接至任何 MCP 服务端,而不仅限于使用本库创建的服务端。该协议设计为与服务端实现无关,因此您可以使用本库连接任何符合规范的服务端。

工具可轻松暴露给 IChatClients 即时调用,因为 McpClientTool 继承自 AIFunction。

// Get available functions.
IList<McpClientTool> tools = await client.ListToolsAsync();

// Call the chat client using the tools.
IChatClient chatClient = ...;
var response = await chatClient.GetResponseAsync(
    "your prompt here",
    new() { Tools = [.. tools] },

服务端快速入门

以下示例演示如何创建MCP服务端并注册当前应用程序中的所有工具。示例包含一个简单的回声工具(为便于复制粘贴,此处将其与主代码置于同一文件,但实际无需放在同一文件中...所使用的WithTools重载方法会扫描当前程序集,查找带有McpServerToolType特性的类,并将所有具有McpTool特性的方法注册为工具。)

dotnet add package ModelContextProtocol --prerelease
dotnet add package Microsoft.Extensions.Hosting
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using System.ComponentModel;

var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(consoleLogOptions =>
{
    // Configure all logs to go to stderr
    consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
});
builder.Services
    .AddMcpServer()
    .WithStdioServerTransport()
    .WithToolsFromAssembly();
await builder.Build().RunAsync();

[McpServerToolType]
public static class EchoTool
{
    [McpServerTool, Description("Echoes the message back to the client.")]
    public static string Echo(string message) => $"hello {message}";
}

工具可通过方法形参注入代表服务端的IMcpServer实例,并借助该实例与连接的客户端进行交互。同样地,实参也可通过依赖注入方式注入。例如:以下工具将使用注入的IMcpServer向客户端发起采样请求,从而通过依赖注入的HttpClient从指定URL下载内容并进行汇总。

[McpServerTool(Name = "SummarizeContentFromUrl"), Description("Summarizes content downloaded from a specific URI")]
public static async Task<string> SummarizeDownloadedContent(
    IMcpServer thisServer,
    HttpClient httpClient,
    [Description("The url from which to download the content to summarize")] string url,
    CancellationToken cancellationToken)
{
    string content = await httpClient.GetStringAsync(url);

    ChatMessage[] messages =
    [
        new(ChatRole.User, "Briefly summarize the following downloaded content:"),
        new(ChatRole.User, content),
    ];
    
    ChatOptions options = new()
    {
        MaxOutputTokens = 256,
        Temperature = 0.3f,
    };

    return $"Summary: {await thisServer.AsSamplingChatClient().GetResponseAsync(messages, options, cancellationToken)}";
}

提示词可以使用 [McpServerPrompt] 特性以类似的方式公开,例如:

[McpServerPromptType]
public static class MyPrompts
{
    [McpServerPrompt, Description("Creates a prompt to summarize the provided message.")]
    public static ChatMessage Summarize([Description("The content to summarize")] string content) =>
        new(ChatRole.User, $"Please summarize this content into a single sentence: {content}");
}

还可实现更精细的控制,对服务端的配置及其处理客户端请求的方式进行细粒度的管理。例如:

using ModelContextProtocol;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using System.Text.Json;

McpServerOptions options = new()
{
    ServerInfo = new Implementation { Name = "MyServer", Version = "1.0.0" },
    Capabilities = new ServerCapabilities
    {
        Tools = new ToolsCapability
        {
            ListToolsHandler = (request, cancellationToken) =>
                ValueTask.FromResult(new ListToolsResult
                {
                    Tools =
                    [
                        new Tool
                        {
                            Name = "echo",
                            Description = "Echoes the input back to the client.",
                            InputSchema = JsonSerializer.Deserialize<JsonElement>("""
                                {
                                    "type": "object",
                                    "properties": {
                                      "message": {
                                        "type": "string",
                                        "description": "The input to echo back"
                                      }
                                    },
                                    "required": ["message"]
                                }
                                """),
                        }
                    ]
                }),

            CallToolHandler = (request, cancellationToken) =>
            {
                if (request.Params?.Name == "echo")
                {
                    if (request.Params.Arguments?.TryGetValue("message", out var message) is not true)
                    {
                        throw new McpException("Missing required argument 'message'");
                    }

                    return ValueTask.FromResult(new CallToolResult
                    {
                        Content = [new TextContentBlock { Text = $"Echo: {message}", Type = "text" }]
                    });
                }

                throw new McpException($"Unknown tool: '{request.Params?.Name}'");
            },
        }
    },
};

await using IMcpServer server = McpServerFactory.Create(new StdioServerTransport("MyServer"), options);
await server.RunAsync();

 

posted @ 2025-09-12 14:42  菜鸟吊思  阅读(20)  评论(0)    收藏  举报