尧图精选

第一个MCP服务:用TaoToken统一Key跑通fastmcp最小闭环

🕒 发布时间:2026/10/1 15:08:08 📁 来源:尧图网络
1. 从零理解 MCP 与 fastmcp第一个 MCP 服务到底在解决什么问题如果你最近在折腾 AI 应用开发大概率被 MCP 这个词刷屏了。MCP 全称 Model Context Protocol直白点说它就是一套让大模型能调用外部工具的标准协议。你可以把它想象成 USB 接口以前每个 AI 应用想连数据库、连文件系统、连第三方 API都得自己写一套私有对接逻辑现在有了 MCP工具提供方按统一协议暴露能力AI 客户端按统一协议去发现和调用双方解耦。那 fastmcp 又是什么它是 Python 生态里把 MCP 服务端封装得最轻量的框架之一。你不需要手写 JSON-RPC 的握手细节只要用装饰器把普通 Python 函数标记成mcp.tool()fastmcp 就帮你生成符合 MCP 规范的服务描述、参数 schema 和调用入口。对第一次接触 MCP 的开发者来说fastmcp 是理解一个 MCP 服务长什么样的最短路径。这篇文章面向的就是第一次搭 MCP 服务的你。我会带你走完一条完整闭环装环境、写一个带两个工具的 fastmcp 服务、本地用 STDIO 和 HTTP 两种模式启动、用 curl 和 MCP 客户端验证调用成功。同时因为 MCP 服务里经常要调用大模型能力比如让工具内部再去做一次语义处理我会把 TaoToken 的统一 Key 和 API 通道接进来这样你后面无论换哪个模型都不用改代码里的鉴权逻辑。先说清楚适合谁会一点 Python、装过 pip 包、能看懂命令行输出就足够了。不需要你懂 MCP 协议细节也不需要你有 GPU。整个流程在一台普通开发机上十几分钟能跑通。跑通之后你会得到一个可复用的最小骨架后面加工具就是往文件里再写几个函数的事。我试过把 MCP 服务想复杂结果卡在协议到底怎么握手上半天。后来发现 fastmcp 已经把这一层吃掉了你真正要关心的只有两件事工具函数写对没有服务启动模式选对没有。剩下的交给框架。2. TaoToken 前置准备统一 Key 与 API 通道怎么配在写服务代码之前先把模型调用通道这件事定下来。MCP 服务本身不强制你连大模型但真实场景里工具函数经常需要调用 LLM比如做一个总结文本的工具、一个翻译的工具。如果每个工具里都硬编码不同厂商的 Key 和 Base URL维护起来会很痛苦。TaoToken 的价值就在这里它提供一个统一的 API 入口和统一 Key你换模型只改一个 Model ID鉴权部分不动。你需要准备三样东西我把它叫三件套Base URL、API Key、Model ID。这三样在后面的配置片段里会反复出现务必先拿到。第一步打开 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册并登录。登录后进入控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。在控制台里你能看到账户额度和可用的模型列表。第二步生成 API Key。进入 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 点新建复制那串以sk-开头的 Key。注意这串 Key 只显示一次复制后先存到本地环境变量里别直接写进代码提交到 Git。第三步确认 Base URL。TaoToken 的 API 入口是 https://taotoken.net/api 注意这个地址后面不加任何 UTM 参数直接用它作为 OpenAI 兼容的 base_url。Model ID 则从控制台的模型列表里挑一个比如你常用某个对话模型就把它对应的 ID 记下来。配置方式我推荐用环境变量这样代码里读os.environ就行不泄露密钥。在 Linux/macOS 的~/.bashrc或~/.zshrc里加export TAOTOKEN_API_KEYsk-你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_MODEL_ID你选的模型IDWindows PowerShell 用户用$env:TAOTOKEN_API_KEYsk-你的Key $env:TAOTOKEN_BASE_URLhttps://taotoken.net/api $env:TAOTOKEN_MODEL_ID你选的模型ID改完记得source ~/.zshrc或重开终端然后echo $TAOTOKEN_API_KEY确认能打印出来。这一步别跳过后面服务里读不到环境变量会直接报 401。注意不要把 Key 写进任何会提交到公开仓库的文件。如果你用.env文件记得把.env加进.gitignore。到这里前置就完成了。你手里有了统一 Key、统一 Base URL 和一个 Model ID接下来写服务代码时模型调用部分就靠这三样。3. 可复制配置fastmcp 服务代码与 settings 片段现在进入正题写第一个 fastmcp 服务。先装依赖pip install fastmcp openaifastmcp提供服务框架openai用来调用 TaoToken 的兼容接口。装完可以pip show fastmcp看下版本确认装上了。新建一个文件demo_mcp.py把下面这段完整代码复制进去。这段代码定义了两个工具greet做简单问候summarize调用 TaoToken 的模型做文本总结正好演示工具内部调 LLM的典型写法。import os import asyncio import sys import fastmcp from fastmcp import FastMCP from openai import OpenAI # 全局设置HTTP/SSE 模式监听的地址和端口 fastmcp.settings.host 0.0.0.0 fastmcp.settings.port 8001 # 创建 MCP 实例 mcp FastMCP(demo.mcp) # 从环境变量读取 TaoToken 三件套 TAOTOKEN_API_KEY os.environ.get(TAOTOKEN_API_KEY) TAOTOKEN_BASE_URL os.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api) TAOTOKEN_MODEL_ID os.environ.get(TAOTOKEN_MODEL_ID) # 初始化 OpenAI 兼容客户端指向 TaoToken 统一通道 client OpenAI( api_keyTAOTOKEN_API_KEY, base_urlTAOTOKEN_BASE_URL, ) mcp.tool() def greet(name: str) - str: 简单的问候工具 return fHello, {name} mcp.tool() def summarize(text: str) - str: 调用 TaoToken 统一通道的模型对输入文本做一句话总结 resp client.chat.completions.create( modelTAOTOKEN_MODEL_ID, messages[ {role: system, content: 你是一个简洁的总结助手只输出一句话总结。}, {role: user, content: text}, ], temperature 0.3, ) return resp.choices[0].message.content async def start_server(mode: str stdio): 根据指定模式启动服务 print(f启动MCP服务{mode}模式...) print(f服务名称: demo.mcp) if mode stdio: print( STDIO模式 ) await mcp.run_stdio_async() elif mode http: print(fHTTP服务地址: http://{fastmcp.settings.host}:{fastmcp.settings.port}) await mcp.run_http_async() elif mode sse: print(fSSE服务地址: http://{fastmcp.settings.host}:{fastmcp.settings.port}/sse) await mcp.run_sse_async() elif mode streamable: print(fStreamable HTTP服务地址: http://{fastmcp.settings.host}:{fastmcp.settings.port}) await mcp.run_streamable_http_async() else: print(f错误: 不支持的模式 {mode}) print(支持的模式: stdio, http, sse, streamable) return print(按CtrlC停止服务) if __name__ __main__: mode stdio if len(sys.argv) 1: mode sys.argv[1].lower() asyncio.run(start_server(mode))几个关键点解释一下。fastmcp.settings.host和port是全局设置只有 HTTP/SSE/streamable 模式才用得上STDIO 模式忽略它们。FastMCP(demo.mcp)里的字符串是服务名客户端连接时会看到。mcp.tool()装饰器把普通函数变成 MCP 工具函数签名和 docstring 会自动转成工具的参数描述所以 docstring 要写清楚客户端展示给模型看的就是它。summarize里用OpenAI客户端指向 TaoToken 的 Base URL这就是统一通道的用法。你以后想换模型只改环境变量TAOTOKEN_MODEL_ID代码一行不动。如果你更习惯用配置文件管理可以建一个settings.toml[taotoken] base_url https://taotoken.net/api model_id 你选的模型ID [fastmcp] host 0.0.0.0 port 8001然后在代码里用tomllib读进来替换环境变量。两种方式都行环境变量更适合本地快速验证配置文件更适合团队共享结构。4. 验证请求STDIO 与 HTTP 两种模式跑通成功结果代码写好了先跑 STDIO 模式这是 MCP 客户端最常用的本地连接方式。在终端执行python demo_mcp.py stdio你会看到类似输出启动MCP服务stdio模式... 服务名称: demo.mcp STDIO模式 此时服务在等待标准输入上的 MCP 消息。STDIO 模式不适合直接用 curl 测因为它走的是标准输入输出而不是网络端口。要验证它最直接的方式是用一个 MCP 客户端连上来。你可以用 Claude Code 或任何支持 MCP 的客户端在配置里加一个 stdio server命令填python /绝对路径/demo_mcp.py stdio。连上后客户端会列出greet和summarize两个工具调用greet传{name: MCP}返回Hello, MCP就说明通了。不过对第一次搭服务的人来说HTTP 模式更容易用 curl 直接验证。另开一个终端启动 HTTP 模式python demo_mcp.py http输出启动MCP服务http模式... 服务名称: demo.mcp HTTP服务地址: http://0.0.0.0:8001服务监听在 8001 端口。fastmcp 的 HTTP 模式走的是 MCP 的 streamable HTTP 传输请求体是 JSON-RPC 格式。先用 curl 做一次初始化握手curl -s -X POST http://127.0.0.1:8001/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2024-11-05, capabilities: {}, clientInfo: {name: curl-client, version: 1.0} } }如果返回里带serverInfo和capabilities说明握手成功。接着列出工具curl -s -X POST http://127.0.0.1:8001/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 2, method: tools/list, params: {} }你应该能看到greet和summarize两个工具的定义包括参数 schema。最后调用greetcurl -s -X POST http://127.0.0.1:8001/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 3, method: tools/call, params: { name: greet, arguments: {name: MCP} } }返回里result.content[0].text是Hello, MCP闭环就跑通了。再测summarize传一段长文本进去它会走 TaoToken 通道调模型返回一句话总结。这一步成功说明你的 MCP 服务既能暴露工具又能通过统一 Key 调模型。提示如果 curl 返回空或连接被拒先确认服务进程还在前台运行且端口没被占用。lsof -i :8001可以查端口占用。5. 本篇常见错排查401、local proxy failed、reading choices 与 OAuth第一次跑报错几乎必然。下面这几个是我和身边人踩过的对照着看。401 Unauthorized。这个最常见基本是 TaoToken 的 Key 没读到或写错。先echo $TAOTOKEN_API_KEY确认环境变量在当前终端可见。如果你在 IDE 里跑IDE 可能没继承 shell 的环境变量需要在运行配置里手动加。还有一种情况是 Key 复制时带了空格或换行strip()一下再传。401 也可能出现在summarize工具里因为那是唯一真正发起模型请求的地方greet不碰网络所以如果greet通而summarize报 401问题一定在 Key 或 Base URL。local proxy failed。这个报错通常出现在客户端连接 MCP 服务时意思是客户端尝试连本地服务但连不上。检查三件事服务是否真的在跑、地址端口是否和客户端配置一致、防火墙是否拦了本地回环。STDIO 模式下不会出现这个错因为它不走网络HTTP 模式下如果客户端配的是localhost:8001而服务监听在0.0.0.0:8001一般没问题但如果你把 host 改成了某个具体网卡地址客户端就得跟着改。reading choices 相关报错。这个出现在summarize里典型信息是NoneType object has no attribute choices或list index out of range。原因通常是模型返回结构和你预期不一致或者TAOTOKEN_MODEL_ID是空的导致请求根本没发出去。先打印resp看原始返回确认resp.choices存在。如果 Model ID 写错有些通道会返回错误对象而不是抛异常所以加一层判断更稳if not resp.choices: return f模型调用失败: {resp} return resp.choices[0].message.contentOAuth 相关报错。如果你用的是 Claude Code 这类客户端连接 MCP 时可能提示 OAuth 或鉴权失败。这通常不是 MCP 服务本身的问题而是客户端侧的登录态过期。重新在客户端里完成一次登录或者检查客户端的 MCP 配置里有没有多余的 auth 字段。MCP 服务本身在 STDIO 模式下不需要 OAuthHTTP 模式如果没开鉴权也不需要所以看到 OAuth 报错先怀疑客户端配置而不是服务代码。Codex auth.json 场景。如果你在用 Codex 类工具它的鉴权信息存在auth.json里。当 MCP 服务和 Codex 共用模型通道时确保auth.json里的 base_url 指向 TaoToken 的 API 入口Key 和 Model ID 与本文三件套一致。三件套缺一不可Base URL 决定请求发到哪Key 决定能不能过鉴权Model ID 决定用哪个模型。任何一件写错表现都是调用失败但报错信息各不相同对照上面几条定位。排查顺序建议固定下来先确认服务进程活着再确认端口/命令对再确认三件套环境变量最后看模型返回结构。按这个顺序九成问题能在两分钟内定位。6. 继续往下走把最小闭环扩展成你的工具集跑通这个闭环之后你手里其实已经有了一个可复用的骨架。加新工具就是往demo_mcp.py里再写几个带mcp.tool()的函数docstring 写清楚参数含义重启服务客户端重新连接就能看到。如果你想让工具内部调用模型直接复用那个client对象三件套不用再配一遍。下一步可以试的方向把summarize换成更具体的业务工具比如从一段日志里提取错误码或者给工具加上参数校验让 schema 更严格再或者把 STDIO 模式接进你日常用的编码客户端让它在写代码时能直接调你的工具。这些都不需要改协议层fastmcp 已经处理好了。如果你打算长期做 MCP 服务和 Agent 相关开发建议了解一下 Coding Plan它更适合需要持续调用模型、跑长任务的场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。想直接在网页里试模型效果可以用模型对话https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 。接入细节和参数说明都在文档里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。需要新建或管理 Key 就去 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。最后留一个实用技巧把启动命令写成一个run.sh里面先source环境变量再启动服务这样每次不用手动 export。服务跑起来后先用greet这种不依赖网络的工具确认链路通再测summarize这种依赖模型的工具能把服务问题和模型通道问题分开定位。这个习惯能帮你省下大量排查时间。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →