尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MCP Server/Tool 开发指南:用 TaoToken 统一 Key 打通工具调用链路

MCP Server/Tool 开发指南:用 TaoToken 统一 Key 打通工具调用链路 1. 从零写一个 MCP Server为什么先要解决 Key 管理MCP Server 说白了就是给 AI 宿主Claude Desktop、Cursor、VS Code Copilot 这类挂一个「外挂工具箱」。AI 通过 JSON-RPC 2.0 协议问你的 Server你有哪些工具然后按需调用。工具本身可以是查数据库、读文件、调第三方 API甚至跑一段沙箱代码。问题出在「调第三方 API」这一步。你写一个get_weather工具背后要请求某个天气服务写一个search_github工具背后要请求 GitHub。每个服务一套 Key、一套鉴权头、一套限流规则。工具一多Key 散落在.env、config.toml、settings.json里换台机器就得重新配一遍团队协作时还得把 Key 传来传去。TaoToken 在这里的角色是「统一 Key 通道」你只维护一个 API KeyMCP Server 里所有需要调用大模型或外部 AI 能力的工具都走同一个入口。官网在 https://taotoken.netAPI 入口是 https://taotoken.net/api。这样你的 MCP Server 代码里只需要读一个环境变量工具注册和调用链路都干净。这篇面向的是「已经会写 Python、想跑通 MCP 工具链路」的开发者。我会给出config.toml和settings.json的可复制骨架把 TaoToken 的 Key 配置位置标清楚最后用一次真实的工具注册 调用验证整条链路。全程本地可复现不需要任何特殊网络环境。2. TaoToken 前置Key 与通道准备在写 MCP Server 之前先把「统一 Key」这件事落地。TaoToken 的定位是给开发者提供一个统一的模型调用入口你拿到的 Key 可以同时用于对话、代码补全、Agent 工具调用等场景。对 MCP Server 来说最关键的是两件事Key 存在哪、请求发到哪。2.1 拿到 API Key登录 TaoToken 控制台后进入 API Keys 页面创建一个新 Key。建议按用途命名比如mcp-server-dev方便后面在多个 MCP Server 之间区分。创建后立刻复制保存页面刷新后就不再完整显示。控制台地址https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_server_guideAPI Keys 管理页https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_server_guide2.2 确认 API 入口TaoToken 的 API 基础地址是https://taotoken.net/api。注意这个地址不带任何查询参数直接作为base_url使用。MCP Server 里如果某个工具需要调用模型就把请求发到这里鉴权头用Authorization: Bearer 你的Key。注意不要把 Key 硬编码进mcp_server.py。MCP Server 经常以子进程方式被宿主拉起硬编码的 Key 会随代码进版本库。统一走环境变量或配置文件。2.3 环境变量约定我习惯用三个变量把配置和代码解耦# .env TAOTOKEN_API_KEYsk-xxxxxxxxxxxxxxxx TAOTOKEN_BASE_URLhttps://taotoken.net/api MCP_SERVER_PORT18001Python 侧用python-dotenv加载这样本地开发和部署到容器时行为一致。如果你更倾向用config.toml管理下一节给出等价写法。3. 可复制配置config.toml 与 settings.json 骨架MCP 生态里配置文件分两层一层是 MCP Server 自己的运行配置端口、传输方式、Key另一层是 AI 宿主侧的 MCP 客户端配置怎么找到你的 Server。前者我用config.toml后者用settings.json。3.1 config.tomlServer 侧运行配置# config.toml [server] name taotoken-mcp-demo version 1.0.0 transport sse # 可选: stdio / sse / streamable-http host 127.0.0.1 port 18001 sse_path /sse [taotoken] api_key_env TAOTOKEN_API_KEY # 从环境变量读取不写明文 base_url https://taotoken.net/api timeout 30 [tools] enable_weather true enable_calc true enable_model_chat true这里的关键设计是api_key_env配置文件里只存「去哪个环境变量取 Key」不存 Key 本身。这样config.toml可以安全提交到仓库.env加进.gitignore。3.2 settings.json宿主侧 MCP 客户端配置不同宿主的配置文件路径不一样。VS Code 的 Copilot 默认在%APPDATA%\Code\User\mcp.jsonClaude Desktop 在各自的claude_desktop_config.json。结构大同小异下面这份是通用骨架{ mcpServers: { taotoken-demo: { url: http://127.0.0.1:18001/sse, transport: sse, env: { TAOTOKEN_API_KEY: sk-xxxxxxxxxxxxxxxx, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } }如果你用 stdio 模式把url换成commandargs{ mcpServers: { taotoken-demo-stdio: { command: python, args: [D:/Workspace/mcp/mcp_server.py], env: { TAOTOKEN_API_KEY: sk-xxxxxxxxxxxxxxxx } } } }提示SSE 模式适合「Server 常驻、多个宿主共享」stdio 模式适合「宿主自己拉起子进程、用完即走」。开发阶段我建议先用 SSE因为可以用 curl 单独验证不依赖宿主。3.3 读取配置的 Python 代码# config_loader.py import os import tomllib from dotenv import load_dotenv load_dotenv() def load_config(path: str config.toml) - dict: with open(path, rb) as f: cfg tomllib.load(f) # 把 api_key_env 解析成真实 Key key_env cfg[taotoken][api_key_env] cfg[taotoken][api_key] os.getenv(key_env, ) if not cfg[taotoken][api_key]: raise RuntimeError(f环境变量 {key_env} 未设置) return cfgtomllib是 Python 3.11 起内置的3.10 及以下用tomli替代接口一样。4. 写 MCP Server工具注册与 TaoToken 通道接入配置就绪后开始写 Server 本体。我用官方mcpSDK 的FastMCP它把工具注册简化成装饰器适合快速验证。4.1 安装依赖pip install mcp[cli] python-dotenv httpxhttpx用来在工具内部请求 TaoToken 的 API。4.2 完整 Server 代码# mcp_server.py import httpx from mcp.server import FastMCP from config_loader import load_config cfg load_config() app FastMCP( cfg[server][name], portcfg[server][port], sse_pathcfg[server][sse_path], ) TAOTOKEN_BASE cfg[taotoken][base_url] TAOTOKEN_KEY cfg[taotoken][api_key] app.tool() def add(a: int, b: int) - int: 加法运算返回 a b return a b app.tool() def minus(a: int, b: int) - int: 减法运算返回 a - b return a - b app.tool() async def ask_model(prompt: str) - str: 通过 TaoToken 统一通道调用模型返回文本回复 headers { Authorization: fBearer {TAOTOKEN_KEY}, Content-Type: application/json, } payload { model: gpt-4o-mini, messages: [{role: user, content: prompt}], } async with httpx.AsyncClient(timeoutcfg[taotoken][timeout]) as client: resp await client.post( f{TAOTOKEN_BASE}/v1/chat/completions, headersheaders, jsonpayload, ) resp.raise_for_status() data resp.json() return data[choices][0][message][content] if __name__ __main__: app.run(transportcfg[server][transport])三个工具add、minus是纯本地计算用来验证协议链路ask_model走 TaoToken 通道用来验证统一 Key 是否生效。这样分层的好处是如果调用失败你能快速判断是 MCP 协议层的问题还是 API 层的问题。4.3 启动 Serverpython mcp_server.py正常输出类似INFO: Started server process [28956] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:18001 (Press CTRLC to quit)看到Uvicorn running就说明 SSE 端点已经起来了默认路径/sse。5. 验证请求一次完整的工具注册与调用Server 起来后别急着往宿主里塞。先用 curl 手动走一遍 JSON-RPC 流程确认工具列表和调用结果都对。5.1 建立 SSE 连接拿 sessionId开一个终端窗口执行curl -N http://127.0.0.1:18001/sse-N参数禁用缓冲能立刻看到服务器推送。输出里会有一行event: endpoint data: /messages/?session_id2dcb98b6eaa74e2eade0e07160af6610把这个session_id记下来后面所有 POST 请求都要带上它。5.2 初始化会话另开一个终端SESSION_ID2dcb98b6eaa74e2eade0e07160af6610 curl -X POST http://127.0.0.1:18001/messages/?session_id$SESSION_ID \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2024-11-05, capabilities: {}, clientInfo: {name: test-client, version: 1.0.0} } }返回Accepted同时第一个终端会推回serverInfo里面能看到你的 Server 名称和版本。5.3 列出工具curl -X POST http://127.0.0.1:18001/messages/?session_id$SESSION_ID \ -H Content-Type: application/json \ -d {jsonrpc:2.0,id:2,method:tools/list,params:{}}第一个终端会推送工具列表应该包含add、minus、ask_model三个每个都带inputSchema。5.4 调用本地工具curl -X POST http://127.0.0.1:18001/messages/?session_id$SESSION_ID \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 3, method: tools/call, params: {name: minus, arguments: {a: 3, b: 4}} }推送结果里structuredContent应该是{result: -1}isError为false。5.5 调用走 TaoToken 的工具curl -X POST http://127.0.0.1:18001/messages/?session_id$SESSION_ID \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 4, method: tools/call, params: {name: ask_model, arguments: {prompt: 用一句话解释什么是 MCP}} }如果 TaoToken Key 配置正确推送结果里会带模型返回的文本。这一步跑通说明「MCP 协议链路 统一 Key 通道」都通了。5.6 用 Python 客户端再验一次curl 验证完用官方客户端 SDK 写个脚本模拟宿主行为# mcp_client.py import asyncio from mcp.client.sse import sse_client from mcp import ClientSession async def main(): async with sse_client(http://127.0.0.1:18001/sse) as streams: async with ClientSession(*streams) as session: await session.initialize() tools await session.list_tools() print(工具列表:, [t.name for t in tools.tools]) res await session.call_tool(add, {a: 10, b: 20}) print(add 结果:, res.structuredContent) if __name__ __main__: asyncio.run(main())输出工具列表: [add, minus, ask_model]和add 结果: {result: 30}就对了。6. 本篇常见错排查跑不通的时候按下面顺序排查能覆盖九成问题。6.1 连接被拒 / Connection refused先确认 Server 真的在监听netstat -ano | findstr 18001Windows 下如果端口被占用换config.toml里的port。Linux/macOS 用lsof -i :18001。另外确认host是127.0.0.1而不是0.0.0.0时curl 也用127.0.0.1别混用localhost导致 IPv6 解析问题。6.2 session_id 失效SSE 连接断开后 session 就没了。如果你在第一个终端按了 CtrlC第二个终端的 POST 会返回 404 或 400。重新执行curl -N拿新 session_id 即可。开发时建议把 SSE 连接放在独立终端别和 POST 混在一起。6.3 工具列表为空检查装饰器是不是app.tool()不是app.tool少了括号。另外FastMCP实例名和app.run的 transport 要匹配SSE 模式下sse_path默认/sse客户端 URL 要带这个路径。6.4 ask_model 返回 401说明 TaoToken Key 没读到或不对。检查三处.env里TAOTOKEN_API_KEY是否有值config.toml里api_key_env拼写是否一致启动 Server 的终端是否加载了.envload_dotenv()要在load_config()之前调用。如果 Key 刚创建确认没有多余空格。6.5 ask_model 返回 404大概率是base_url拼错。TaoToken 的 API 入口是https://taotoken.net/api代码里拼接的是{base_url}/v1/chat/completions。如果你在config.toml里把base_url写成了带/v1的地址就会变成/v1/v1/...。保持base_url为纯入口地址。6.6 宿主里看不到工具宿主侧的settings.json改完要重启宿主。VS Code 的 Copilot 需要重新加载窗口Claude Desktop 要完全退出再启动。另外确认url里的端口和 Server 一致SSE 模式必须带/sse路径。6.7 中文乱码curl 在 Windows 终端下可能显示乱码但数据本身是对的。用 Python 客户端验证更可靠。如果确实需要 curl 看中文加--compressed并确认终端编码是 UTF-8。7. 下一步把链路接到真实宿主本地 curl 和 Python 客户端都通了之后把settings.json里的配置填进你常用的宿主。VS Code Copilot 的配置文件在%APPDATA%\Code\User\mcp.jsonClaude Desktop 在各自的配置目录。填完重启在对话里问「你有哪些工具」宿主应该能列出add、minus、ask_model。如果你打算长期跑编码类 Agent或者让 MCP Server 常驻给多个宿主共享建议了解一下 Coding Plan它更适合这种持续调用的场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_server_guide只想先验证模型通道是否通可以直接在模型对话页试一条请求https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_server_guide接入过程中如果遇到鉴权或协议层报错接入文档里有各语言的请求示例https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_server_guideKey 需要重新生成或管理多个用途时回到 API Keys 页面操作https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_server_guide我自己的习惯是每加一个新工具先用 curl 单独调一次tools/call确认返回结构对了再往宿主里塞。这样出问题时能立刻定位是工具逻辑还是宿主配置比在宿主日志里翻半天快得多。
返回列表