中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

使(shi)用MCP C# SDK開發MCP Server + Client

大(da)家好,我是Edison。

近日(ri)被MCP刷屏了,剛好看到張(zhang)隊發了一(yi)篇文章(zhang)提到MCP的官方C# SDK發布了預覽版,于是手癢(yang)癢(yang)嘗了一(yi)下鮮(xian),寫了一(yi)個DEMO分享給大家(jia)。

MCP是什么鬼?

MCP,全稱是“模型上下文協(xie)議(yi)(yi)”(Model Context Protocol),是(shi)Anthropic開(kai)源的(de)一個標準協(xie)議(yi)(yi)。打個比方(fang),它(ta)就像(xiang)是(shi)AI世界的(de)“USB-C”接口。你知道USB-C吧?一根線(xian)就能連接手機、電腦、充電器(qi),超級方(fang)便(bian)。MCP的(de)作用也差不多,它(ta)讓AI模型(比如(ru)Anthropic的(de)Claude)可以輕松(song)地跟外部的(de)數據源和工具(ju)連接起來,比如(ru)數據庫、文件系統(tong)、API等(deng)等(deng)。以前,如果想讓AI訪問你的數據庫或(huo)者調(diao)用(yong)(yong)某(mou)個工具,得專門寫一堆代碼,特別麻煩。現(xian)在(zai)有了MCP,就像是(shi)插上USB-C線那么簡單,AI模型通過這個標(biao)準協議就能直(zhi)接獲(huo)取(qu)數據或(huo)執行(xing)操作,不用(yong)(yong)每(mei)次都重(zhong)新開(kai)發(fa)連接方式。這樣,開(kai)發(fa)AI應用(yong)(yong)就變得更(geng)快、更(geng)省事了。

MCP是如何工作的?

MCP是一個(ge)典型的C/S架構模(mo)式,即客戶端(duan) 和 服務端(duan),它們之間(jian)采用一種標準的消(xiao)息(xi)格式(JSON-RPC)進行通信,大模(mo)型可以通過(guo)這些消(xiao)息(xi)進行:

(1)獲取數據(ju):例(li)如通過SQL從DB中查詢訂單(dan)數據(ju);

(2)執(zhi)行操作:例如通過API調用發個消息通知;

(3)理解指令:例如(ru)通過一(yi)些提示詞模板,LLM可以知(zhi)道如(ru)何(he)使(shi)用數據和(he)工(gong)具;

簡(jian)單來說(shuo),MCP就是AI的“萬能(neng)(neng)(neng)接(jie)口”。有了它,AI模型(xing)就能(neng)(neng)(neng)像插上USB-C線一(yi)樣,輕松連接(jie)到各種外部(bu)數據源(yuan)和工具,變(bian)得更(geng)聰明(ming)、更(geng)實(shi)用。不(bu)管是開發者還是普通用戶,都能(neng)(neng)(neng)通過(guo)MCP讓AI干(gan)更(geng)多(duo)事,而且過(guo)程(cheng)簡(jian)單又(you)安全(quan)。未(wei)來隨著MCP的普及(ji),我們可能(neng)(neng)(neng)會看到更(geng)多(duo)能(neng)(neng)(neng)干(gan)實(shi)事兒的AI應用冒出來!

創建一個MCP Server

這里我們(men)使用MCP C# SDK來(lai)實現,使用標準的IO傳輸方式。

(1)創建一個.NET 8.0控制臺應(ying)用,假(jia)設命名(ming)為:EDT.McpServer.ConsoleHost

(2)安裝MCP SDK

ModelContextProtocol 0.1.0-preview.4

(3)創建一個Tools目錄(lu),然后添(tian)加一個TimeTool.cs

using ModelContextProtocol.Server;
using System.ComponentModel;

namespace EDT.McpServer.Tools.ConsoleHost;

[McpServerToolType]
public static class TimeTool
{
    [McpServerTool, Description("Get the current time for a city")]
    public static string GetCurrentTime(string city) =>
        $"It is {DateTime.Now.Hour}:{DateTime.Now.Minute} in {city}.";
}

這個(ge)TimeTool就是我們定義(yi)的基于(yu)(yu)MCP的Tool,可(ke)以(yi)看(kan)到基于(yu)(yu)SDK提(ti)供(gong)的Attribute,可(ke)以(yi)方便地將(jiang)其指定為(wei)MCP Server Tools。

(3)修改(gai)Program.cs設置為啟動(dong)MCP Server

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using EDT.McpServer.Tools.ConsoleHost;

try
{
    Console.WriteLine("Starting MCP Server...");

    var builder = Host.CreateEmptyApplicationBuilder(settings: null);
    builder.Services
        .AddMcpServer()
        .WithStdioServerTransport()
        .WithToolsFromAssembly();

    await builder.Build().RunAsync();
    return 0;
}
catch (Exception ex)
{
    Console.WriteLine($"Host terminated unexpectedly : {ex.Message}");
    return 1;
}

同樣,也是很方便地就完成了(le)MCP Server的創(chuang)建,重點關注(zhu)WithToolsFromAssembly這(zhe)個擴展方法,它會掃描程序集中添加(jia)了(le)McpServerTool標簽(qian)的類進行注(zhu)冊。

這時我們已經(jing)完成了(le)MCP Server的創建,可以把它啟(qi)動(dong)起來(lai)了(le)。

但(dan)是,要完(wan)成今天的目標(biao),連(lian)接起來測試,我(wo)們還得(de)實現一個Client來調用Server。

創建一個MCP Client

(1)創建一(yi)個(ge).NET 8.0控制(zhi)臺應用,假設命名為:EDT.McpServer.Client

(2)安裝MCP SDK

ModelContextProtocol 0.1.0-preview.4

(3)修(xiu)改Program.cs,實現以下步驟:

創建MCP Client:

await using var mcpClient = await McpClientFactory.CreateAsync(new()
{
    Id = "time",
    Name = "Time MCP Server",
    TransportType = TransportTypes.StdIo,
    TransportOptions = new()
    {
        ["command"] = @"..\..\..\..\EDT.McpServer\bin\Debug\net8.0\EDT.McpServer.exe"
    }
});

需要注意的(de)是(shi)(shi):這里(li)我們(men)MCP Server使用的(de)是(shi)(shi)標準IO傳輸方(fang)式,因此指定(ding)TransportType為StdIo,同時(shi)指定(ding)command為MCP Server應用程序所在的(de)exe的(de)目錄位置。當然(ran),這里(li)的(de)這種方(fang)式有(you)點不是(shi)(shi)很(hen)規范,但你(ni)只需要了解它是(shi)(shi)需要訪(fang)問MCP Server的(de)程序地址就行了。

列出可用的Tools:

var tools = await mcpClient.ListToolsAsync();
foreach (var tool in tools)
{
    Console.WriteLine($"{tool.Name} ({tool.Description})");
}

直接執行Tool:(一般情況下不會這樣用,而是在LLM中來調用)

var result = await mcpClient.CallToolAsync(
    "GetCurrentTime",
    new Dictionary<string, object?>() { ["city"] = "Chengdu" },
    CancellationToken.None);
Console.WriteLine(result.Content.First(c => c.Type == "text").Text);

通過LLM來調用Tool:這里基(ji)于Microsoft.Extensions.AI核心庫來實現的,你也可以用Semantic Kernel庫來做這個事,都行!

var apiKeyCredential = new ApiKeyCredential(config["LLM:ApiKey"]);
var aiClientOptions = new OpenAIClientOptions();
aiClientOptions.Endpoint = new Uri(config["LLM:EndPoint"]);
var aiClient = new OpenAIClient(apiKeyCredential, aiClientOptions)
    .AsChatClient(config["LLM:ModelId"]);
var chatClient = new ChatClientBuilder(aiClient)
    .UseFunctionInvocation()
    .Build();
IList<ChatMessage> chatHistory =
[
    new(ChatRole.System, """
       You are a helpful assistant delivering time in one sentence
       in a short format, like 'It is 10:08 in Paris, France.'
       """),
];
// Core Part: Get AI Tools from MCP Server
var mcpTools = await mcpClient.ListToolsAsync();
var chatOptions = new ChatOptions()
{
    Tools = [..mcpTools]
};
// Prompt the user for a question.
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Assistant> How can I assist you today?");
while (true)
{
    // Read the user question.
    Console.ForegroundColor = ConsoleColor.White;
    Console.Write("User> ");
    var question = Console.ReadLine();
    // Exit the application if the user didn't type anything.
    if (!string.IsNullOrWhiteSpace(question) && question.ToUpper() == "EXIT")
        break;

    chatHistory.Add(new ChatMessage(ChatRole.User, question));
    Console.ForegroundColor = ConsoleColor.Green;
    var response = await chatClient.GetResponseAsync(chatHistory, chatOptions);
    var content = response.ToString();
    Console.WriteLine($"Assistant> {content}");
    chatHistory.Add(new ChatMessage(ChatRole.Assistant, content));

    Console.WriteLine();
}

最后的(de)效果如下圖所示:

創建(jian)一(yi)個(ge)基于ASP.NET的MCP Server

除了使(shi)用標準的IO協議(yi),我們還(huan)可以實現一個基于(yu)ASP.NET Core的MCP SSE Server,顧名思義它就是(shi)使(shi)用SSE傳(chuan)輸方(fang)式。

(1)創(chuang)建(jian)一個.NET 8.0 ASP.NET WebAPI應用,假設命(ming)名(ming)為(wei):EDT.McpServer.WebHost

(2)安裝MCP SDK

ModelContextProtocol 0.1.0-preview.4
ModelContextProtocol.AspNetCore 0.1.0-preview.4

(3)創(chuang)建(jian)一(yi)個Tools目錄,然后添加一(yi)個TimeTool.cs

這里和上面的一樣,不再贅(zhui)述。

(4)修改Program.cs完成MCP Server配置:

using EDT.McpServer.WebHost.Tools;
using ModelContextProtocol.AspNetCore;

try
{
    Console.WriteLine("Starting MCP Server...");

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddMcpServer().WithToolsFromAssembly();
    var app = builder.Build();

    app.UseHttpsRedirection();
    app.MapGet("/", () => "Hello MCP Server!");
    app.MapMcp();

    app.Run();
    return 0;
}
catch (Exception ex)
{
    Console.WriteLine($"Host terminated unexpectedly : {ex.Message}");
    return 1;
}

可以看(kan)到,就(jiu)是(shi)(shi)這么簡單,通(tong)過(guo)MapMcp實現了/sse端點(dian)(dian)的(de)(de)(de)映射。后續MCP Client要連接的(de)(de)(de)就(jiu)是(shi)(shi)這個(ge)/sse的(de)(de)(de)端點(dian)(dian)。

(5)這時,你就可以把這個ASP.NET WebAPI應用啟動起來,假設我們這里是 //localhost:8443,你就可以(yi)通過(guo)下面(mian)的一(yi)點點修改,讓之前的這(zhe)個(ge)MCP Client連接上這(zhe)個(ge)MCP Server:

await using var mcpClient = await McpClientFactory.CreateAsync(new()
{
    Id = "time",
    Name = "Time MCP Server",
    TransportType = TransportTypes.Sse,
    Location = "//localhost:8443/sse"
});

可以看到,僅(jin)(jin)僅(jin)(jin)修改TransportType為(wei)SSE,然后指(zhi)定Server的BaseUrl即可。

OK,讓我們再來(lai)運行一下(xia)Client看看能(neng)否再次(ci)成功(gong)調用Tool:

看來這次使用(yong)(yong)SSE傳輸方式也(ye)能調用(yong)(yong)成(cheng)功了!Perfect!

小結

本(ben)(ben)文介紹了MCP的基本(ben)(ben)概念和工作模式,然后演示了如何通(tong)過MCP C# SDK創建MCP Server和Client,以(yi)及基于(yu)ASP.NET WebAPI創建SSE Server,相(xiang)信(xin)會對你(ni)有所幫助。

如果(guo)你也是.NET程序員希望參(can)與AI應(ying)用的開(kai)發,那就快快了解(jie)和使用基于Microsoft.Extensioins.AI + MCP C# SDK 的生態組(zu)件庫吧。

示例(li)源(yuan)碼

GitHub:

參考內容

MCP C# SDK Samples 《》

推薦(jian)內容

 

posted @ 2025-04-02 19:11  EdisonZhou  閱讀(6174)  評論(6)    收藏  舉報