現(xiàn)一個簡單的MCP:從零搭建可調(diào)試的MCP Server與TaoToken接入實(shí)踐)
1. 從零理解 MCPPython 手寫一個可調(diào)試的 MCP Server 到底在做什么MCPModel Context Protocol說白了就是一套“讓模型調(diào)用外部工具”的約定。你可以把它想成模型和你的代碼之間的一份菜單模型看到菜單上有哪些工具、每個工具要什么參數(shù)然后決定點(diǎn)哪道菜你的 MCP Server 負(fù)責(zé)把這道菜做出來再把結(jié)果端回去。Python 實(shí)現(xiàn)一個簡單的 MCP核心就三件事注冊工具、路由請求、把結(jié)果按協(xié)議格式返回。很多人第一次接觸 MCP 會以為它很玄其實(shí)底層交互非常樸素。以常見的客戶端為例你在對話框里提問客戶端把你的問題連同“當(dāng)前可用的 tools 列表”一起發(fā)給模型模型分析后決定調(diào)用哪個 tool并給出參數(shù)客戶端通過 MCP Server 執(zhí)行這個 tool執(zhí)行結(jié)果回傳給模型模型再用自然語言把結(jié)果組織成回答展示給你。整條鏈路里MCP Server 就是那個“真正干活”的角色。這篇面向的是想自己動手寫一個最小可用 MCP Server 的 Python 開發(fā)者。你不需要先精通協(xié)議細(xì)節(jié)只要會寫異步函數(shù)、懂一點(diǎn)類型注解就能跟著把 server.py 骨架搭起來注冊兩個工具本地跑通再把 endpoint 切到 TaoToken 完成一次真實(shí)的工具調(diào)用驗(yàn)證。適合誰適合正在做 Agent、想讓模型調(diào)用自己業(yè)務(wù)接口、又不想被復(fù)雜框架綁住的人。我試過用官方 SDK 的 FastMCP 類來搭體驗(yàn)是它用 Python 的 type hints 和 docstring 自動生成 tool definition省掉了手寫 JSON Schema 的麻煩。你只要寫一個帶類型注解的 async 函數(shù)加個裝飾器它就能被模型識別。下面從環(huán)境準(zhǔn)備開始一步步來。2. TaoToken 前置準(zhǔn)備Python MCP Server 接入大模型 API 的 Base URL 與 Key 配置在寫 Server 之前先把“模型側(cè)”的接入準(zhǔn)備好。MCP Server 本身只負(fù)責(zé)執(zhí)行工具真正決定調(diào)用哪個工具的是模型所以你需要一個能訪問模型 API 的入口。這里用 TaoToken 來做模型接入它的接口兼容主流協(xié)議Base URL 和 Key 配好之后客戶端或你的調(diào)試腳本就能直接調(diào)模型。先拿到 API Key。打開 https://taotoken.net/api-keys 登錄后創(chuàng)建一個 Key復(fù)制保存。注意 Key 只在創(chuàng)建時完整顯示一次丟了就重新建一個。這個 Key 后面會寫進(jìn)配置里別硬編碼進(jìn) Git 倉庫。Base URL 用 https://taotoken.net/api 這是接口根地址不要在后面亂加斜杠。模型 ID 按你實(shí)際要用的填比如 claude 系列或 gpt 系列的模型標(biāo)識具體以控制臺模型列表為準(zhǔn)。你可以到 https://taotoken.net/console 查看可用模型和額度情況。如果你用的是 Claude Code 這類工具配置方式略有不同可以參考接入文檔 https://taotoken.net/doc 里的說明。文檔里對 Base URL、Key、Model ID 三件套的填法講得比較清楚。對于本篇的 MCP 調(diào)試我們主要用 Python 腳本直接請求所以只要保證 Base URL 和 Key 正確即可。這里要強(qiáng)調(diào)一個容易踩的點(diǎn)MCP Server 和模型 API 是兩個獨(dú)立的東西。Server 負(fù)責(zé)執(zhí)行工具模型 API 負(fù)責(zé)決策。很多人把兩者混在一起結(jié)果調(diào)試時不知道是工具沒注冊成功還是模型沒調(diào)通。分開驗(yàn)證問題就好定位。先把模型 API 用 curl 或 Python 請求通再回來調(diào) MCP 工具鏈路。3. 可復(fù)制配置server.py 骨架、依賴清單與 MCP 工具注冊這一節(jié)是核心直接給可復(fù)制的代碼和配置。先建項(xiàng)目目錄用 uv 管理環(huán)境用 conda 也行命令自行替換。uv init mcp-demo cd mcp-demo uv venv # Windows 激活 .venv\Scripts\activate # macOS/Linux 激活 source .venv/bin/activate uv add mcp[cli] httpx依賴清單里mcp[cli] 提供 FastMCP 和命令行調(diào)試能力httpx 用來發(fā)異步 HTTP 請求。裝完后新建 server.py寫入下面的骨架from typing import Any import httpx from mcp.server.fastmcp import FastMCP # 初始化 FastMCP server名字會出現(xiàn)在客戶端工具列表里 mcp FastMCP(demo-server) # 模型 API 配置實(shí)際使用時從環(huán)境變量讀取更安全 TAOTOKEN_BASE_URL https://taotoken.net/api TAOTOKEN_API_KEY sk-你的Key async def call_model(prompt: str) - str: 調(diào)用 TaoToken 模型接口返回文本結(jié)果。 headers { Authorization: fBearer {TAOTOKEN_API_KEY}, Content-Type: application/json, } payload { model: 你的模型ID, messages: [{role: user, content: prompt}], } async with httpx.AsyncClient() as client: resp await client.post( f{TAOTOKEN_BASE_URL}/v1/chat/completions, headersheaders, jsonpayload, timeout60.0, ) resp.raise_for_status() data resp.json() return data[choices][0][message][content] mcp.tool() async def echo(text: str) - str: 原樣返回輸入文本用于驗(yàn)證工具鏈路是否打通。 Args: text: 任意字符串 return fecho: {text} mcp.tool() async def ask_model(question: str) - str: 把問題轉(zhuǎn)發(fā)給 TaoToken 模型并返回回答。 Args: question: 要問模型的問題 try: return await call_model(question) except Exception as e: return f調(diào)用模型失敗: {e} if __name__ __main__: mcp.run(transportstdio)這段代碼里mcp.tool()裝飾器把普通 async 函數(shù)注冊成 MCP 工具函數(shù)名就是工具名docstring 會成為工具描述參數(shù)類型注解會生成參數(shù) schema。echo用來做鏈路自檢ask_model演示在工具內(nèi)部再調(diào)模型 API這是很多 Agent 場景的典型結(jié)構(gòu)。如果你用 Cline 或 Claude Code 這類客戶端配置通常是一個 JSON 片段路徑和字段名要對齊。以常見的 MCP 客戶端配置為例{ mcpServers: { demo-server: { command: uv, args: [run, server.py], env: { TAOTOKEN_API_KEY: sk-你的Key } } } }注意 Base URL、Key、Model ID 三件套要齊全Base URL 是 https://taotoken.net/api Key 從 API Keys 頁面拿Model ID 按控制臺實(shí)際模型填。少任何一個工具調(diào)用都會失敗。4. 驗(yàn)證請求本地啟動 MCP Server 并完成一次工具調(diào)用代碼寫好后先本地跑起來。用官方 CLI 調(diào)試最方便uv run mcp dev server.py這會啟動一個調(diào)試界面能看到已注冊的工具列表。如果echo和ask_model都出現(xiàn)了說明注冊成功。接著在調(diào)試界面里調(diào)用echo輸入hello應(yīng)該返回echo: hello。這一步驗(yàn)證的是 MCP 協(xié)議鏈路本身不涉及模型。然后驗(yàn)證ask_model。調(diào)用它并傳入用一句話解釋什么是 MCP如果返回一段模型生成的解釋說明工具內(nèi)部調(diào)用 TaoToken 模型 API 也通了。這一步同時驗(yàn)證了兩條鏈路MCP 工具執(zhí)行 模型 API 請求。如果你想用腳本方式驗(yàn)證可以寫一個簡單的 stdio 客戶端或者直接用 curl 先單獨(dú)測模型 APIcurl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的Key \ -H Content-Type: application/json \ -d {model:你的模型ID,messages:[{role:user,content:ping}]}返回里有choices字段就說明模型側(cè)沒問題。再回到 MCP 調(diào)試界面調(diào)ask_model成功結(jié)果應(yīng)該是一段自然語言回答。實(shí)測下來把兩條鏈路分開驗(yàn)證排錯效率高很多。成功結(jié)果長這樣調(diào)試界面顯示工具調(diào)用狀態(tài)為 completed返回內(nèi)容是你問的問題的模型回答。如果echo通了但ask_model不通問題一定在模型 API 配置上而不是 MCP 協(xié)議。5. 本篇常見錯排查401、local proxy failed、reading choices 與 OAuth 報錯調(diào)試 MCP Server 時報錯基本集中在幾類。下面按真實(shí)報錯對照排查。第一類401 Unauthorized。這通常是 Key 不對或沒帶上。檢查Authorization頭是不是Bearer sk-xxx格式Key 有沒有多余空格環(huán)境變量有沒有真的傳進(jìn)去。如果你在客戶端配置里寫了env確認(rèn)字段名和代碼里讀取的變量名一致。第二類local proxy failed或連接被拒。這多半是 Base URL 寫錯比如多加了/v1或結(jié)尾斜杠。Base URL 就用 https://taotoken.net/api 路徑拼接交給代碼。另外確認(rèn)本機(jī)網(wǎng)絡(luò)能正常訪問該地址公司網(wǎng)絡(luò)限制也可能導(dǎo)致連接失敗。第三類reading choices相關(guān)報錯比如KeyError: choices或list index out of range。這說明請求返回了但結(jié)構(gòu)不是預(yù)期的 chat completions 格式。常見原因是 Model ID 填錯或者請求體字段名不對。打印完整響應(yīng)體再定位別只看異常信息。第四類OAuth 相關(guān)報錯。如果你用的是 Claude Code 這類帶 OAuth 流程的工具報錯可能出現(xiàn)在授權(quán)環(huán)節(jié)。這時候檢查接入文檔里的配置步驟確認(rèn) Base URL 和 Key 的填法符合要求。OAuth 和 API Key 是兩種不同的鑒權(quán)方式別混用。還有一個隱蔽的坑MCP Server 用 stdio 傳輸時任何print輸出都會污染協(xié)議流導(dǎo)致客戶端解析失敗。調(diào)試信息一律用sys.stderr或日志文件別用print。這個坑我踩過排查了半天才發(fā)現(xiàn)是調(diào)試打印惹的禍。6. 語義一致 CTA把 MCP Server 接到真實(shí)模型與長期編碼場景工具鏈路跑通后下一步就是把它接到真實(shí)使用場景。如果你主要做模型對話驗(yàn)證可以到 https://taotoken.net/chat 直接體驗(yàn)?zāi)P蛯υ挻_認(rèn)模型側(cè)行為符合預(yù)期。如果你要把 MCP 用在長期編碼或 Agent 任務(wù)里建議看 Coding Plan https://taotoken.net/coding-plan 它更適合持續(xù)性的開發(fā)場景。接入文檔在 https://taotoken.net/doc 里面覆蓋了 Base URL、Key、Model ID 的完整配置說明遇到鑒權(quán)或路徑問題先查這里。API Key 管理在 https://taotoken.net/api-keys Key 泄露或額度異常時及時輪換??刂婆_ https://taotoken.net/console 可以看用量和模型列表?;氐酱a本身一個實(shí)用的技巧是把call_model里的模型 ID 和 Base URL 抽成環(huán)境變量這樣本地調(diào)試和線上部署用同一份代碼只換配置。另外給工具函數(shù)加超時和重試模型 API 偶爾抖動時不會直接把整個 MCP 調(diào)用拖死。最后工具描述docstring寫清楚模型選工具的準(zhǔn)確率會明顯提升這比調(diào)參管用。