器:C# 實現(xiàn) Model Context Protocol 并接入 TaoToken 統(tǒng)一 Key)
1. 為什么我要自己寫一個 MCP 服務(wù)器MCP 服務(wù)器Model Context Protocol Server說白了就是給大模型外掛的一雙手模型本身只會生成文字但通過 MCP 協(xié)議它可以調(diào)用你注冊好的工具函數(shù)去查數(shù)據(jù)庫、讀文件、發(fā)請求、算數(shù)據(jù)。適合誰適合手里有一堆內(nèi)部接口、想讓 AI 直接調(diào)用的后端和桌面開發(fā)者。我這次用 C# 從零搓一個最小可用的 MCP 服務(wù)器把協(xié)議握手、工具注冊、調(diào)用鏈路全部跑通再通過 TaoToken 的統(tǒng)一 Key 把 AI 工具接進來讓整條鏈路真正能對話、能執(zhí)行。很多人卡在第一步以為 MCP 是個很玄的東西。其實它就是一個約定好的 JSON-RPC 通信規(guī)范客戶端和服務(wù)端按格式交換消息服務(wù)端告訴客戶端我有哪些工具、參數(shù)是什么客戶端把模型的調(diào)用意圖翻譯成請求發(fā)過來服務(wù)端執(zhí)行完把結(jié)果塞回去。你只要把這三件事做對MCP 服務(wù)器就活了。這篇會交付一個可復(fù)制的項目骨架、一份 config.toml 配置示例以及一次完整的本地驗證動作。全程不需要你懂什么高深協(xié)議跟著敲就行。2. TaoToken 前置準(zhǔn)備統(tǒng)一 Key 與通道在寫代碼之前先把 AI 側(cè)的通道準(zhǔn)備好。MCP 服務(wù)器本身只負責(zé)執(zhí)行工具真正發(fā)起對話、決定調(diào)用哪個工具的是模型客戶端。我用 TaoToken 來做統(tǒng)一入口好處是一個 Key 走通模型對話和工具調(diào)用不用在多個平臺之間來回切。你需要先拿到 API Key。打開控制臺頁面登錄后進入 API Keys 管理新建一個 Key 并復(fù)制保存。這個 Key 就是后面配置里要填的憑證??刂婆_入口https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_csharpAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_csharp接入文檔https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_csharpAPI 的基礎(chǔ)地址是https://taotoken.net/api注意這個地址不帶任何查詢參數(shù)配置時直接填這個即可。模型對話、工具調(diào)用都走同一個通道省去了維護多套憑證的麻煩。提示Key 只顯示一次復(fù)制后立刻存到本地配置文件或環(huán)境變量里別直接硬編碼進提交到倉庫的源碼。如果你后面要做長期編碼或 Agent 類任務(wù)可以了解下 Coding Plan它更適合高頻調(diào)用場景只是驗證模型和工具鏈路的話用模型對話頁面配合本地服務(wù)就夠了。3. 可復(fù)制配置項目骨架與 config.toml先建項目。用 .NET CLI 起一個 Web 項目MCP 的 C# SDK 目前以預(yù)覽包形式提供安裝時帶上--prerelease。dotnet new web -n McpDemo cd McpDemo dotnet add package ModelContextProtocol --prerelease項目結(jié)構(gòu)保持簡單McpDemo/ ├── Program.cs ├── Tools/ │ └── MyTools.cs ├── config.toml └── McpDemo.csprojconfig.toml用來放模型通道和服務(wù)器參數(shù)避免散落在代碼里[server] name mcp-demo transport sse port 5180 [ai] base_url https://taotoken.net/api api_key sk-你的Key model claude-3-5-sonnet [tools] enabled [GeneratePraise, Add, GetServerTime]然后在Program.cs里讀取配置、注冊 MCP 服務(wù)并映射路由using ModelContextProtocol.Server; using Tomlyn; var builder WebApplication.CreateBuilder(args); // 讀取 config.toml var configText File.ReadAllText(config.toml); var config Toml.ToModel(configText); builder.Services.AddMcpServer() .WithToolsFromAssembly(); var app builder.Build(); app.MapMcpSse(); app.Run();這里WithToolsFromAssembly()會自動掃描當(dāng)前程序集里所有帶[McpServerToolType]的類把[McpServerTool]標(biāo)注的方法注冊成可調(diào)用工具。你不需要手寫路由映射SDK 幫你做了。工具類長這樣using System.ComponentModel; using ModelContextProtocol.Server; [McpServerToolType] public class MyTools { [McpServerTool] [Description(根據(jù)名字生成一句彩虹屁)] public string GeneratePraise(string name) { return ${name} 老師真是玉樹臨風(fēng)代碼一寫一個準(zhǔn)。; } [McpServerTool] [Description(計算兩個整數(shù)之和)] public int Add(int a, int b) { return a b; } [McpServerTool] [Description(返回服務(wù)器當(dāng)前時間)] public string GetServerTime() { return DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss); } }Description特性很關(guān)鍵它不是寫給人看的注釋而是會隨工具列表一起發(fā)給模型模型靠它判斷這個工具是干嘛的、什么時候該調(diào)。描述寫得越清楚模型選錯工具的概率越低。4. 驗證請求跑通一次完整調(diào)用代碼寫完先本地啟動dotnet run看到監(jiān)聽http://localhost:5180就說明服務(wù)起來了。MCP 的 SSE 端點默認掛在/sse路徑下客戶端連上后會先收到一條 endpoint 事件里面帶著后續(xù)發(fā)消息用的地址。驗證分兩步。第一步確認工具列表能正確暴露用 curl 模擬客戶端握手curl -N http://localhost:5180/sse正常會持續(xù)輸出事件流包含event: endpoint和data: /message?sessionIdxxx。拿到 sessionId 后發(fā)一條初始化請求curl -X POST http://localhost:5180/message?sessionId你的sessionId \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2024-11-05, capabilities: {}, clientInfo: { name: curl-test, version: 1.0 } } }返回里會帶上服務(wù)端的能力聲明。接著請求工具列表curl -X POST http://localhost:5180/message?sessionId你的sessionId \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 2, method: tools/list, params: {} }你應(yīng)該能看到GeneratePraise、Add、GetServerTime三個工具每個都帶著參數(shù) schema。最后真正調(diào)用一次curl -X POST http://localhost:5180/message?sessionId你的sessionId \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 3, method: tools/call, params: { name: Add, arguments: { a: 3, b: 5 } } }返回結(jié)果里content字段會包含8。到這一步MCP 服務(wù)器的握手、工具注冊、調(diào)用鏈路就全部跑通了。整個過程沒有任何魔法就是標(biāo)準(zhǔn)的 JSON-RPC 一來一回。5. 本篇常見錯排查啟動報端口占用config.toml里默認 5180被占了就改port或者用dotnet run --urls http://localhost:5190臨時覆蓋。tools/list 返回空數(shù)組九成是工具類沒加[McpServerToolType]或者方法不是public。SDK 只掃描公開方法私有方法會被忽略。另外確認WithToolsFromAssembly()調(diào)用的是當(dāng)前程序集工具類別放到另一個沒被引用的項目里。調(diào)用工具報 method not found檢查tools/call里的name是否和 C# 方法名完全一致大小寫敏感。如果你用了[McpServerTool(Name xxx)]重命名就要用重命名后的名字。SSE 連上但收不到 endpoint 事件確認路由映射用的是MapMcpSse()而不是別的并且請求路徑是/sse。有些反向代理會緩沖 SSE 流本地直連一般沒這問題。模型側(cè)不調(diào)用工具先確認工具描述是否清晰模糊的描述會讓模型猶豫。再檢查客戶端是否真的把工具列表傳給了模型有些客戶端需要顯式開啟工具調(diào)用能力。用 TaoToken 通道時確認base_url填的是https://taotoken.net/apiKey 沒有多余空格。中文參數(shù)亂碼請求頭帶上Content-Type: application/json; charsetutf-8服務(wù)端默認按 UTF-8 解析一般不會出問題但 curl 在某些終端下需要顯式聲明。6. 把鏈路接到 AI 工具上本地驗證通過后就可以把 MCP 服務(wù)器接到真實的 AI 客戶端里。在客戶端的 MCP 配置中填入你的 SSE 地址http://localhost:5180/sse模型就能看到你注冊的工具。對話時你說幫我算一下 3 加 5模型會自己決定調(diào)用Add工具拿到結(jié)果再組織成自然語言回復(fù)你。模型通道這邊統(tǒng)一走 TaoToken 的 API 地址一個 Key 同時管對話和工具調(diào)用。想先感受下模型對話效果可以直接在模型對話頁面里試要做長期編碼或 Agent 任務(wù)Coding Plan 更合適接入細節(jié)和參數(shù)說明都在接入文檔里。我踩過的一個坑是一開始把工具描述寫得太籠統(tǒng)模型經(jīng)常在該調(diào)用工具的時候選擇直接編答案。后來把每個Description改成什么場景下用、參數(shù)是什么含義命中率明顯上來了。MCP 服務(wù)器的質(zhì)量一半在代碼一半在描述。到這里一個能跑、能調(diào)、能接 AI 的 C# MCP 服務(wù)器就完整了。接下來你可以往MyTools里繼續(xù)加方法每加一個帶[McpServerTool]的公開方法模型就多一項能力。