MCP Server可以算是LLM模型的外掛,補足不足的知識,或者是抓取即時的資料,例如最新的股票價格。最近才開始研究MCP,其實也是因為微軟之前的套件都還在preveiw階段,想等穩定一點後再來學,另一方面也是不想跟風,現在AI相關的東西太多學不完,一有新的就馬上跟風,個人覺得容易有資訊焦慮。不過目前微軟各方面的AI套件都開始穩定,覺得也該是時候了。

以下會示範如何寫一個MCP Server,以及如何對它介接,下面是Server的相關程程式碼:

var builder = WebApplication.CreateBuilder(args);

// 設定固定監聽位址與 port
builder.WebHost.UseUrls("http://localhost:5000");
builder.Logging.AddConsole(consoleLogOptions =>
{
    consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
});

// 註冊 MCP 伺服器,並啟用 HTTP (SSE) 傳輸
builder.Services.AddMcpServer(options =>
{
    options.ServerInfo = new ModelContextProtocol.Protocol.Implementation
    {
        Name = "MCP Server Demo Console App",
        Version = "1.0.0",
        Description = "A simple MCP server implemented in a console application."
    };
})
.WithHttpTransport()
.WithToolsFromAssembly(); // 這會自動掃描並註冊你在專案中定義的工具

var app = builder.Build();
app.MapMcp();
await app.RunAsync();

這部份很單純,就是啟動一個伺服器,其中WithToolsFromAssembly會自動把MCP相關的類別自動載入,不用像DI那類的要手動加(其實也可以自動,但比較麻煩),接下來是MCP類別:

[McpServerToolType]
public class ProductInfoTool
{
    [McpServerTool, Description("查詢筆電價格")]
    public int Price([Description("筆電名稱")] string productName)
    {
        return productName switch
        {
            "Apple筆電" => 32000,
            "Dell筆電" => 50000,
            "Acer筆電" => 25000,
            _ => throw new ArgumentException("Unknown product")
        };
    }
}

簡單寫一個查詢筆電價格的類別,因為是測試用,所以裡面的資料都是寫死的,只要記得將相關的attribute貼上就可以了。

然後是LLM這邊接入MCP的部份:

var serverBase = new Uri("http://localhost:5000/");
// 自動處理與伺服器之間的雙向連線
var transport = new HttpClientTransport(new HttpClientTransportOptions
{
    Endpoint = serverBase
});
// 使用 await using 確保程式結束時,連線資源會被正確釋放
await using var client = await McpClient.CreateAsync(transport);
Console.WriteLine("連線成功!\n");

// 取得並列出伺服器上所有可用的工具
var toolsResult = await client.ListToolsAsync();
var otherAIFunctions = new List<AITool>();
Console.WriteLine("【伺服器提供的工具列表】");
foreach (var tool in toolsResult)
{
    Console.WriteLine($"- {tool.Name} : {tool.Description}");
    otherAIFunctions.Add(tool);
}
Console.WriteLine();

上面是連接MCP的程式碼,將遠端MCP可用的工具列出來,下面的程式碼則是實際載入並使用MCP的程式碼:

string model = @"llama3.1:latest";
IChatClient chatClient = new OllamaSharp.OllamaApiClient(new Uri("http://localhost:11434"), model);
IChatClient clientWithTools = new FunctionInvokingChatClient(chatClient);
var chatOptions = new ChatOptions
{
    Tools = otherAIFunctions
};

await foreach (var update in clientWithTools.GetStreamingResponseAsync("告訴我Apple筆電的價格是多少?", chatOptions))
{
    Console.Write(update);
}

參考資料