器運維助手:把本地 MCP 服務(wù)改到 TaoToken)
1. 凌晨三點的告警和那個不想起床的你服務(wù)器 CPU 突然飆到 98%手機在床頭柜上震個不停。你爬起來打開電腦SSH 連上去top看一眼進程tail -f翻日志再去內(nèi)網(wǎng) Wiki 搜一下這個報錯以前有沒有出現(xiàn)過——這套動作你做過不下五十次閉著眼都能敲完。問題是它消耗的不是技術(shù)能力而是你的睡眠和耐心。大模型現(xiàn)在寫代碼、讀日志、做推理的能力已經(jīng)足夠強為什么還要人肉去執(zhí)行這些標準化步驟我想要的是一段 Python 腳本收到告警后自動拉取服務(wù)器狀態(tài)、讀取錯誤日志、結(jié)合本地運維手冊最后把一份“診斷報告”推給我。我只需要看一眼結(jié)論決定要不要回滾。這就是本文要手搓的東西一個基于 Python MCP LLM 的智能服務(wù)器運維助手。MCPModel Context Protocol負責把本地服務(wù)器操作封裝成標準工具接口LLM 負責推理和決策Python 負責把兩者粘起來。適合誰適合有一定 Python 基礎(chǔ)、手頭管著幾臺 Linux 服務(wù)器、想用 AI 把重復(fù)運維動作自動化掉的開發(fā)者。但這里有個現(xiàn)實問題當你真正開始寫 Agent 的時候會發(fā)現(xiàn)模型調(diào)用的 Key 管理很煩。今天用 DeepSeek 試推理明天想換 Claude 做長日志分析后天團隊里另一個人用 GPT 跑同樣的流程——每個模型一套 Key、一套 Base URL、一套計費散落在各個.env文件里。切換一次要改代碼、改環(huán)境變量、重啟服務(wù)。我試過在三個項目里維護四套 Key最后自己都記不清哪個 Key 對應(yīng)哪個模型。所以這篇教程的重點不只是“怎么搭一個 MCP 運維助手”而是“怎么把本地 MCP 服務(wù)的 endpoint 和鑒權(quán)統(tǒng)一改到 TaoToken 通道”讓多模型切換變成改一個 Model ID 的事。下面從環(huán)境準備開始一步步跑通從本地工具調(diào)用到模型響應(yīng)的完整閉環(huán)。2. 把 MCP 服務(wù)接到 TaoToken環(huán)境準備與依賴安裝在寫代碼之前先把思路理清楚。整個系統(tǒng)分三層工具層是一個 MCP Server用 Python 寫暴露get_server_status和read_last_error_logs兩個工具大腦層是一個 Python Agent 主程序它作為 MCP Client 連接 Server同時調(diào)用 LLM 做推理通道層就是 TaoToken統(tǒng)一管理模型訪問。為什么要把 MCP 服務(wù)的模型調(diào)用改到 TaoToken因為 MCP 協(xié)議本身只規(guī)定了“工具怎么暴露、怎么調(diào)用”它不關(guān)心你背后用哪個模型。但你的 Agent 主程序在調(diào)用 LLM 時需要填base_url和api_key。如果每個模型都單獨配代碼里就會散落一堆 if-else。TaoToken 提供統(tǒng)一的 API 入口你只需要把base_url指向https://taotoken.net/api然后用同一個 Key 就能訪問不同模型。切換模型時只改model參數(shù)不動鑒權(quán)邏輯。先裝依賴。Python 版本建議 3.10 以上MCP 的 Python SDK 對異步支持要求較高。pip install mcp openai psutilmcp是官方 SDKopenai用來調(diào)用兼容 OpenAI 格式的接口TaoToken 的 API 就是這種格式psutil用來讀 CPU 和內(nèi)存。接下來配置環(huán)境變量。我習慣用一個.env文件管理但為了演示清晰這里直接寫在 shell 里。你需要去 TaoToken 控制臺創(chuàng)建一個 API Key然后設(shè)置export TAOTOKEN_API_KEYsk-你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/api注意base_url后面不要加/v1OpenAI SDK 會自動拼接。如果你用的是其他兼容庫確認一下它的拼接規(guī)則。我踩過的坑是有些教程寫https://taotoken.net/api/v1結(jié)果請求變成/api/v1/v1/chat/completions直接 404。MCP Server 的配置也需要一個環(huán)境變量模板。如果你打算把 Server 和 Agent 分開部署比如 Server 跑在目標服務(wù)器上Agent 跑在本地可以用一個mcp_config.json來管理連接參數(shù){ mcpServers: { ops-watchdog: { command: python, args: [/opt/ops/server_mcp.py], env: { TAOTOKEN_API_KEY: sk-你的Key, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } }這個 JSON 片段可以直接被支持 MCP 的客戶端讀取。如果你用 Claude Code 或 Cline它們的配置文件格式類似把command和args換成你的實際路徑即可。這里的關(guān)鍵是MCP Server 本身不直接調(diào)用 LLM它只負責執(zhí)行工具LLM 調(diào)用發(fā)生在 Agent 主程序里。所以TAOTOKEN_API_KEY其實是給 Agent 用的放在 Server 的 env 里只是為了統(tǒng)一管理實際讀取時要注意作用域。如果你用 Codex 的auth.json做鑒權(quán)格式是這樣的{ api_key: sk-你的Key, base_url: https://taotoken.net/api }但 Codex 的auth.json通常放在~/.codex/目錄下而我們的 Agent 是獨立 Python 程序直接讀環(huán)境變量更簡單。所以下面的代碼里我用os.getenv讀取不依賴外部配置文件。依賴裝好、Key 配好之后先寫 MCP Server。新建server_mcp.pyimport sys import psutil import subprocess from mcp.server.fastmcp import FastMCP mcp FastMCP(OpsWatchdog) mcp.tool() def get_server_status() - str: 獲取服務(wù)器當前的 CPU 和內(nèi)存使用率。返回格式化字符串。 cpu_percent psutil.cpu_percent(interval1) memory psutil.virtual_memory() return fCPU使用率: {cpu_percent}%\n內(nèi)存使用率: {memory.percent}% mcp.tool() def read_last_error_logs(lines: int 50) - str: 讀取應(yīng)用日志文件的最后 N 行用于分析報錯原因。 log_path /var/log/syslog try: result subprocess.check_output([tail, -n, str(lines), log_path]) return result.decode(utf-8) except Exception as e: return f讀取日志失敗: {str(e)} if __name__ __main__: print(MCP Server Running..., filesys.stderr) mcp.run()這段代碼里FastMCP是 SDK 提供的快捷類mcp.tool()裝飾器把普通 Python 函數(shù)注冊成 MCP 工具。mcp.run()默認用 stdio 傳輸也就是通過標準輸入輸出和 Client 通信。注意print要寫到stderr因為stdout被 MCP 協(xié)議占用了寫錯地方會導(dǎo)致協(xié)議解析失敗。Server 寫完后先單獨測一下它能不能啟動python server_mcp.py如果看到MCP Server Running...并且沒有報錯說明 Server 端沒問題。按CtrlC退出接下來寫 Agent 主程序。3. 可復(fù)制配置Agent 主程序與 TaoToken 接入Agent 主程序的核心邏輯是啟動 MCP Server 子進程 → 建立 ClientSession → 獲取工具列表 → 把工具描述注入 System Prompt → 調(diào)用 LLM → 解析 LLM 的工具調(diào)用意圖 → 執(zhí)行工具 → 把結(jié)果喂回 LLM → 輸出最終診斷。新建agent_main.pyimport asyncio import os import json from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from openai import OpenAI client OpenAI( api_keyos.getenv(TAOTOKEN_API_KEY), base_urlos.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api) ) async def run_agent(): server_params StdioServerParameters( commandpython, args[server_mcp.py], ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await session.list_tools() tool_descriptions \n.join( [f- {t.name}: {t.description} for t in tools.tools] ) system_prompt f你是一個資深 SRE 運維專家。你可以使用以下工具排查服務(wù)器問題 {tool_descriptions} 當收到報警時請先調(diào)用工具獲取信息然后分析原因。 輸出格式要求先給出診斷結(jié)論再給出修復(fù)建議。 user_query 服務(wù)器 CPU 突然飆升請排查原因并給出建議。 print(f用戶指令: {user_query}) response client.chat.completions.create( modeldeepseek-chat, messages[ {role: system, content: system_prompt}, {role: user, content: user_query} ] ) llm_thought response.choices[0].message.content print(fAgent 思考: {llm_thought}) if get_server_status in llm_thought: print( Agent 決定調(diào)用工具: get_server_status) tool_result await session.call_tool(get_server_status) result_text tool_result.content[0].text print(f 工具返回結(jié)果: {result_text}) final_response client.chat.completions.create( modeldeepseek-chat, messages[ {role: system, content: system_prompt}, {role: user, content: user_query}, {role: assistant, content: llm_thought}, {role: user, content: f工具執(zhí)行結(jié)果: {result_text}} ] ) print(fAgent 最終診斷: {final_response.choices[0].message.content}) if __name__ __main__: asyncio.run(run_agent())這段代碼里modeldeepseek-chat是你要根據(jù)實際需求改的。TaoToken 支持多種模型你可以在控制臺看到可用的 Model ID 列表。想換成 Claude 做長日志分析就把model改成對應(yīng)的 IDbase_url和api_key不用動。這就是統(tǒng)一通道的價值鑒權(quán)邏輯只寫一次模型切換只改一個字符串。如果你用 Cline 或 Claude Code 的 MCP 配置把上面的server_params換成對應(yīng)的 JSON 配置即可。Cline 的 MCP 設(shè)置里command填pythonargs填[server_mcp.py]env里加上TAOTOKEN_API_KEY和TAOTOKEN_BASE_URL。Claude Code 的配置類似但它的 MCP 配置文件通常在~/.claude/claude_desktop_config.json格式和前面的mcp_config.json一致。這里有個細節(jié)要注意MCP Server 的env和 Agent 的env是兩套。Server 不需要調(diào) LLM所以它的env里其實不需要TAOTOKEN_API_KEY。但如果你把 Server 和 Agent 寫在同一個進程里比如用FastMCP的run方法直接啟動那 Key 就在同一個環(huán)境里。我建議分開寫職責清晰排障也容易。配置寫完后先別急著跑。檢查一下server_mcp.py的路徑是否正確args里的文件名要和實際一致。如果你把兩個文件放在不同目錄args要寫絕對路徑否則stdio_client找不到文件會報FileNotFoundError。4. 驗證請求一次真實的運維指令端到端跑通現(xiàn)在跑一次完整的流程。確保你在agent_main.py和server_mcp.py所在的目錄下并且環(huán)境變量已經(jīng)設(shè)置好export TAOTOKEN_API_KEYsk-你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/api python agent_main.py如果一切正常你會看到類似下面的輸出用戶指令: 服務(wù)器 CPU 突然飆升請排查原因并給出建議。 Agent 思考: 我需要先查看當前的服務(wù)器狀態(tài)確認 CPU 使用率。調(diào)用 get_server_status。 Agent 決定調(diào)用工具: get_server_status 工具返回結(jié)果: CPU使用率: 98.5% 內(nèi)存使用率: 72.3% Agent 最終診斷: [高危警告] 檢測到服務(wù)器 CPU 使用率高達 98.5%。 結(jié)合知識庫判斷可能是計算密集型任務(wù)卡死。 建議立即 SSH 登錄使用 top 命令定位具體 PID并考慮執(zhí)行 kill 操作。這個輸出說明閉環(huán)跑通了Agent 收到自然語言指令 → LLM 決定調(diào)用工具 → MCP Client 通過 stdio 調(diào)用 Server → Server 執(zhí)行psutil讀取真實 CPU 數(shù)據(jù) → 結(jié)果返回給 LLM → LLM 生成診斷報告。但這里有個問題上面的代碼只演示了一次工具調(diào)用。真實的運維場景可能需要多輪先查 CPU發(fā)現(xiàn)高再查日志發(fā)現(xiàn)某個進程報錯再查知識庫給出修復(fù)建議。要實現(xiàn)多輪 ReAct 循環(huán)需要解析 LLM 返回的工具調(diào)用意圖而不是簡單用if get_server_status in llm_thought判斷。更健壯的做法是讓 LLM 輸出 JSON 格式的工具調(diào)用請求。修改 System Promptsystem_prompt f你是一個資深 SRE 運維專家。你可以使用以下工具排查服務(wù)器問題 {tool_descriptions} 當收到報警時請先調(diào)用工具獲取信息然后分析原因。 如果你需要調(diào)用工具請輸出 JSON 格式{{tool: 工具名, args: {{參數(shù)名: 參數(shù)值}}}} 如果不需要調(diào)用工具直接輸出診斷結(jié)論。然后在 Agent 里解析 JSONimport json def parse_tool_call(text): try: start text.find({) end text.rfind(}) 1 if start ! -1 and end ! 0: return json.loads(text[start:end]) except json.JSONDecodeError: pass return None這樣就能支持多輪循環(huán)。你可以把run_agent改成一個while循環(huán)每次 LLM 返回后檢查是否有工具調(diào)用請求有就執(zhí)行把結(jié)果追加到消息歷史里繼續(xù)下一輪直到 LLM 輸出最終診斷。驗證的時候你可以故意制造一個場景把read_last_error_logs的log_path改成一個不存在的文件看 Agent 怎么處理錯誤。正常情況下工具會返回讀取日志失敗: ...LLM 應(yīng)該能識別這個錯誤并給出“日志路徑可能配置錯誤”的建議。這能測試整個鏈路的容錯能力。如果你在驗證時遇到401錯誤說明TAOTOKEN_API_KEY沒設(shè)置對或者 Key 已經(jīng)失效。去 TaoToken 控制臺重新生成一個然后export一下。如果遇到local proxy failed檢查你的網(wǎng)絡(luò)環(huán)境是否能正常訪問https://taotoken.net/api。如果遇到reading choices相關(guān)的報錯通常是model參數(shù)填錯了去控制臺確認一下可用的 Model ID。5. 本篇常見錯排查401、local proxy failed、reading choices、OAuth排障這部分我按真實遇到的報錯來寫每個都給出定位方法和修復(fù)步驟。401 Unauthorized這是最常見的。報錯信息通常是openai.AuthenticationError: Error code: 401 - {error: {message: Invalid API key}}原因有三個Key 沒設(shè)置、Key 寫錯了、Key 被禁用了。先檢查環(huán)境變量echo $TAOTOKEN_API_KEY如果輸出為空說明沒export成功。如果你是在.env文件里寫的確認代碼里有沒有l(wèi)oad_dotenv()。如果 Key 看起來正常去 TaoToken 控制臺確認一下這個 Key 的狀態(tài)是不是被刪了或者過期了。local proxy failed這個報錯通常出現(xiàn)在網(wǎng)絡(luò)層openai.APIConnectionError: Connection error: local proxy failed意思是 SDK 嘗試通過本地代理訪問 API但代理不可用。檢查你的環(huán)境變量里有沒有HTTP_PROXY或HTTPS_PROXYenv | grep -i proxy如果有而且你不需要代理直接unset掉unset HTTP_PROXY unset HTTPS_PROXY然后重新跑。如果你確實需要代理才能訪問外網(wǎng)確認代理服務(wù)是否正常運行。但注意TaoToken 的 API 地址是https://taotoken.net/api確保你的網(wǎng)絡(luò)環(huán)境能正常解析和訪問這個域名。reading choices 報錯這個報錯通常長這樣KeyError: choices或者IndexError: list index out of range原因是response.choices[0]取不到值。可能是model參數(shù)填錯了API 返回了一個錯誤對象而不是正常的 completion 對象。打印完整的response看看print(response)如果看到error字段里面會寫明具體原因。常見的是 Model ID 不存在比如你寫了deepseek但實際應(yīng)該是deepseek-chat。去 TaoToken 控制臺的模型列表里核對一下。OAuth 相關(guān)報錯如果你用 Claude Code 或 Cline 的 OAuth 流程接入可能會遇到OAuth token expired或者Invalid OAuth callback這類問題通常出現(xiàn)在客戶端工具的鑒權(quán)環(huán)節(jié)不是 MCP Server 本身的問題。檢查你的客戶端工具版本確認 OAuth 配置里的client_id和redirect_uri是否正確。如果你只是用 Python 腳本調(diào) API不走 OAuth可以忽略這類報錯。MCP 連接失敗如果 Agent 啟動時報FileNotFoundError: [Errno 2] No such file or directory: server_mcp.py說明StdioServerParameters里的args路徑不對。改成絕對路徑args[/full/path/to/server_mcp.py]如果報mcp.server.fastmcp.exceptions.MCPError: Tool not found說明 LLM 請求的工具名和 Server 注冊的不一致。檢查mcp.tool()裝飾的函數(shù)名確保和 System Prompt 里描述的一致。排障的核心思路是先確認 Key 和 Base URL 正確再確認模型 ID 存在最后確認 MCP 工具注冊和調(diào)用匹配。這三步過了基本不會有大問題。6. 從本地工具到模型響應(yīng)把閉環(huán)用起來跑通一次驗證之后你可以把這個 Agent 掛到定時任務(wù)或 Webhook 上。比如用cron每五分鐘檢查一次 CPU超過閾值就觸發(fā) Agent 診斷把結(jié)果推到釘釘或飛書。MCP Server 那邊只需要加一個新的mcp.tool()函數(shù)比如restart_service(service_name)Agent 就能學(xué)會新技能。如果你想讓 Agent 支持更多模型比如用 Claude 做長日志分析、用 GPT 做代碼修復(fù)建議只需要在 TaoToken 控制臺確認對應(yīng)的 Model ID然后在client.chat.completions.create里改model參數(shù)。base_url和api_key始終不變。這就是統(tǒng)一通道的意義把鑒權(quán)收斂到一處把模型選擇變成配置項。如果你還沒有 TaoToken 的 Key可以去控制臺創(chuàng)建一個然后從 API Keys 頁面復(fù)制。接入文檔里有不同語言的調(diào)用示例Python 的示例和本文的代碼結(jié)構(gòu)一致。想先試試模型對話效果可以直接在模型對話頁面發(fā)一條運維相關(guān)的指令看看不同模型的響應(yīng)差異。如果你打算長期跑編碼或 Agent 任務(wù)Coding Plan 的額度更劃算適合把這類自動化腳本部署到生產(chǎn)環(huán)境。最后留一個實用技巧把server_mcp.py和agent_main.py放在同一個 Git 倉庫里用requirements.txt鎖定依賴版本。MCP SDK 還在快速迭代不同版本的 API 可能有細微差異。我遇到過升級 SDK 后FastMCP的導(dǎo)入路徑變了導(dǎo)致 Server 啟動失敗。鎖定版本能避免這類問題。