來寫個MCP Server吧

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);
}
參考資料