上个月我在 Claude Code 里写了一个数据库查询工具,写完觉得它不该只在 Claude 里能用,Cursor、TRAE 甚至我自己的 Python 脚本都应该能调。绕一圈发现,MCP 协议把工具层统一了,模型 Key 却依旧各配一把:Claude Code 要 Anthropic 的,Cursor 默认走自己的 Provider,两边还要分别看用量。我最后用 TaoToken 把模型请求统一收拢,先去 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 创建 Key,再把各客户端模型 Provider 的 Base URL 填成 https://taotoken.net/api,钥匙链一下清爽了。下面的步骤基本照着我当时的折腾路线走:先用 FastMCP 写 server.py,再用 mcp dev 调试,最后分别配 claude_desktop_config.json 和 ~/.cursor/mcp.json 接进 Claude Code 和 Cursor。和原文不同的是,我把“客户端 AI 工具的模型请求”也统一改了:MCP Server 注册的自定义技能照常走 STDIO 协议,模型请求则统一走 TaoToken 兼容通道。这样每次 AI 调用 add、get_weather 或 read_project_file 时,底层模型调用的计费都落在一把 Key 上,不用每个工具单独申请官方 Key。
1. MCP 解决“写一套工具处处用”,TaoToken 解决“一把 Key 处处配”
1.1 在 MCP 之前,每个人都在给 AI 写胶水代码
MCP 出现以前,Cursor 的个性化靠 .cursorrules,Claude 的记忆靠 Project Knowledge,VSCode Copilot 靠 extension API。假如我想让三个工具都能“查公司内部 API 文档”,按老办法得写三套互不兼容的插件。MCP 把它们统一成一种协议:你写一个 Server,暴露 Tools、Resources、Prompts,客户端通过 JSON-RPC 2.0 通信。这就像把各种私有充电口统一成了 USB-C,AI 客户端是设备,你的自定义技能是配件,协议一致之后,配件在哪台设备上都能插。
1.2 工具层统一了,钥匙链却更乱了
MCP 的确让“一个工具处处用”变成现实,但注意,它统一的是工具调用,不是模型请求。Claude Code 的模型请求默认走 Anthropic 官方接口,Cursor 走自己的模型 Provider 体系,如果你同时用 TRAE,那又是第三套配置。MCP 把工具代码收敛了,钥匙链却没有收敛。我在接入时多走了一步:把客户端里 AI 模型的请求统一改为走 TaoToken。它提供的是一个统一的 API 兼容通道,各工具的 Base URL 指向同一个地址,Key 也统一用同一把,模型请求集中计费,不用再为每个工具分别申请、分别看用量。
2. 环境准备与第一个 MCP Server:server.py 三十行跑通
2.1 环境:Python 3.10+ 加 mcp[cli]
先建目录和虚拟环境:
mkdir my-mcp-server && cd my-mcp-server python -m venv .venv source .venv/bin/activate pip install "mcp[cli]"mcp[cli] 装的是 MCP Python SDK 加命令行工具,Claude Code 和 Cursor 的接入不需要再装额外依赖。装完确认版本:
python -c "import mcp; print(mcp.__version__)"正常会看到 1.x.x。另外准备材料这里补一步:打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 注册并创建一个 API Key,后面所有客户端的模型 Key 都填这一把。
2.2 server.py:用 FastMCP 注册 add 和 get_weather
新建 server.py:
from mcp.server.fastmcp import FastMCP mcp = FastMCP("FirstMCPServer") @mcp.tool() def add(a: int, b: int) -> int: """对两个整数做加法,返回求和结果。""" return a + b @mcp.tool() def get_weather(city: str) -> str: """返回指定城市的模拟天气数据。""" return f"{city} 今日多云转晴,气温 22℃,湿度 45%" if __name__ == "__main__": mcp.run(transport="stdio")FastMCP 的装饰器风格和 Flask 有几分神似,@mcp.tool() 注册的就是可被 AI 调用的工具。函数签名里类型注解和 docstring 会自动变成工具 Schema,所以描述写得越清楚,AI 调用越准。运行:
python server.py终端没输出?这很正常。STDIO 模式下 Server 通过标准输入输出和客户端通信,没有请求时就是静默等待。按 Ctrl+C 退出。
2.3 用 mcp dev 调试,先别急着接客户端
想确认 Server 是否真的工作,用 MCP CLI 自带的调试界面:
mcp dev server.py默认启动一个 Web 调试面板,地址是 http://localhost:5173。浏览器打开能看到 add 和 get_weather 两个 Tool 已经暴露,可以直接在页面上试调用,入参和返回值都可视化。这一步比手动构造 JSON-RPC 请求快得多,我把调试放在接客户端之前。
3. 实用升级:让 AI 自己读项目文件
3.1 read_project_file 和 list_directory
加法和天气只是验证协议。真正有用的工具是让 AI 读你当前项目里的代码。把 server.py 改成这样:
import os from mcp.server.fastmcp import FastMCP mcp = FastMCP("ProjectFileReader") @mcp.tool() def read_project_file(filepath: str) -> str: """读取指定文件内容,供 AI 分析源码或文档。""" if not os.path.exists(filepath): return f"文件不存在: {filepath}" if os.path.isdir(filepath): return f"目标是目录不是文件: {filepath}" try: with open(filepath, "r", encoding="utf-8") as f: return f.read() except Exception as e: return f"读取失败: {str(e)}" @mcp.tool() def list_directory(dirpath: str = ".") -> str: """列出指定目录下的文件和文件夹,返回各项的名称与类型。""" if not os.path.exists(dirpath): return f"目录不存在: {dirpath}" lines = [] for item in os.listdir(dirpath): full = os.path.join(dirpath, item) kind = "目录" if os.path.isdir(full) else "文件" lines.append(f"[{kind}] {item}") return "\n".join(lines) if lines else "目录为空" if __name__ == "__main__": mcp.run(transport="stdio")3.2 AI 自己调工具,不用复制粘贴
这个 Server 跑起来之后,AI 就能直接读你项目里的代码文件了。你只需要说一句“读取当前目录下所有 Python 文件”,Claude Code 会自己先调 list_directory 找到文件名,再调 read_project_file 拿内容,全程不需要你手动把代码贴进对话框。这正对应 MCP 的设计理念:让 AI 学会用你的工具,而不是你为 AI 写胶水代码。
4. 接入 Claude Code 和 Cursor:MCP 配置照抄,模型入口换成 TaoToken
4.1 先拿 Key,再分清楚两个地址
在配置任何客户端之前,先去 TaoToken 注册并创建 API Key。有两个地址必须分清楚:网页落地页 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 用于注册、创建 Key、查看模型广场和用量;真正填进工具的是接口 Base URL,https://taotoken.net/api,末尾不要加 /v1,也不要带任何 UTM 参数。
模型 ID 怎么填?以 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 的模型广场上列出的为准。我自己的教训是,先到模型广场确认 ID,再填配置文件,不要凭印象写一个名字。
4.2 Claude Code:mcpServers 注册技能,env 换模型入口
Claude 桌面版读 ~/Library/Application Support/Claude/claude_desktop_config.json,Claude Code CLI 读 ~/.claude/settings.json,两个文件结构一致。以 CLI 版为例:
{ "mcpServers": { "my-file-reader": { "command": "/绝对路径/my-mcp-server/.venv/bin/python", "args": ["/绝对路径/my-mcp-server/server.py"] } }, "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "以模型广场为准的模型ID" } }mcpServers 负责把 my-file-reader 这个文件读取技能注册进 Claude Code;env 里三个环境变量负责让 Claude Code 的模型请求走 TaoToken 通道。ANTHROPIC_BASE_URL 填的是 https://taotoken.net/api,不是官网落地页;ANTHROPIC_AUTH_TOKEN 填你从前面官网创建的那把 Key。
重启 Claude Code,输入 /mcp 能看到 my-file-reader 已连接。直接说“读取当前目录下所有 Python 文件”,Claude 会调用 list_directory 和 read_project_file 完成操作。这时候再看模型请求,已经经由 TaoToken 统一计费。
4.3 Cursor:mcp.json 注册技能,模型 Provider 指向 TaoToken
Cursor 可以直接编辑 ~/.cursor/mcp.json:
{ "mcpServers": { "my-file-reader": { "command": "/绝对路径/my-mcp-server/.venv/bin/python", "args": ["/绝对路径/my-mcp-server/server.py"] } } }然后在 Cursor 的 Settings → Models 里,把模型 Provider 的 Base URL 指到 TaoToken:在 OpenAI API Key 区域配置刚创建的 Key,并打开 Override Base URL 填写 https://taotoken.net/api。这样 Cursor 的模型请求统一走 TaoToken,mcp.json 只负责技能注册,两者互不干扰。
配置完成后,在 Cursor 的 Composer 里对 AI 说“帮我重构这个文件,先读一下 server.py”,它会自动通过 MCP 读取文件内容,再基于 TaoToken 通道上的模型给出重构建议,全程零手动复制。
5. STDIO 与 HTTP:本机用 STDIO,团队共享切 HTTP
5.1 两种通信方式怎么选
MCP 支持 STDIO 和 HTTP 两种通信模式。STDIO 下 Server 是客户端的一个子进程,通过标准输入输出通信,零网络配置,只能本机访问,适合个人开发。HTTP 模式(Streamable HTTP)下 Server 作为一个 Web 服务运行,客户端通过 HTTP 连接,可以远程访问、多客户端共享,适合团队统一部署。这里要特别说一句:MCP Server 走 STDIO 还是 HTTP,影响的是工具调用链路;而模型请求走不走 TaoToken,由客户端的 Provider 配置决定,两者是独立的。你完全可以在本机用 STDIO 跑 Server,同时让每个客户端的模型请求都走 TaoToken。
5.2 切到 HTTP 只改一行
把 server.py 末尾改成:
if __name__ == "__main__": mcp.run(transport="streamable-http", port=8000)客户端配置里把 command 和 args 换成 url:
{ "mcpServers": { "my-file-reader": { "url": "http://your-server:8000/mcp" } } }HTTP 模式部署到公网时,前面一定要加认证,不要让裸的 MCP Server 暴露在公网上。生产环境建议放在内网,或者用带鉴权的反向代理。
6. 调试避坑与进阶:print 污染、绝对路径与知识库搜索
6.1 print 会毁掉 STDIO 通道
STDIO 模式下,标准输出是留给 JSON-RPC 协议消息的。你写的 print() 会把输出打到标准输出上,客户端拿到后当作协议消息解析,立刻报“协议解析错误”。想打日志,明确写到标准错误流:
import sys print("add 被调用了", file=sys.stderr)6.2 绝对路径、虚拟环境和热更新
客户端配置里的路径一定要写绝对路径。相对路径在不同工作目录下表现不一致,Claude Code 可能找不到你的 server.py。如果 Server 跑在虚拟环境里,command 要指向虚拟环境里的 python:
{ "command": "/绝对路径/my-mcp-server/.venv/bin/python", "args": ["/绝对路径/my-mcp-server/server.py"] }改完 server.py 记得重启客户端。Claude Code 里输入 /restart,Cursor 需要重启进程,否则客户端还拿着旧的工具列表。另外,注册 Tool 时要克制,exec_shell_command、delete_file_recursive 这类危险操作不要注册到生产环境的 MCP Server 上。STDIO 模式只对本机可见问题不大,但 HTTP 部署到公网时,必须加认证,而且最小化暴露的工具集合。
6.3 接入 TaoToken 后报 401 或 404 怎么查
模型请求报 401,先检查 Key:ANTHROPIC_AUTH_TOKEN 或 Cursor 里填的是不是完整的 YOUR_API_KEY,复制的时候有没有带上空格或换行。报 404,大概率是 Base URL 填错了。正确的接口地址只有 https://taotoken.net/api,末尾不要加 /v1,也不要把官网落地页 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 当成接口地址填进去。官网落地页是注册、创建 Key、看模型广场和用量记录的地方,和接口地址不是一回事。
6.4 进阶:搭一个知识库搜索 Server
把文件读取工具稍作扩展,就能变成一个团队知识库 MCP Server。原理是扫描指定目录下的 Markdown 文件,构建一个简单的倒排索引,让 AI 能按关键词搜索文档:
import os import re from collections import defaultdict from mcp.server.fastmcp import FastMCP mcp = FastMCP("TeamKnowledgeBase") KB_DIR = "/path/to/your/knowledge-base" def build_index(): index = defaultdict(list) for root, _, files in os.walk(KB_DIR): for name in files: if name.endswith(".md"): path = os.path.join(root, name) with open(path, "r", encoding="utf-8") as fh: words = set(re.findall(r"\w+", fh.read().lower())) for w in words: index[w].append(path) return index index = build_index() @mcp.tool() def search_knowledge(query: str) -> str: """在知识库中检索关键词,返回匹配文档列表和第一行摘要。""" query_words = re.findall(r"\w+", query.lower()) if not query_words: return "请输入搜索关键词" hits = set() for w in query_words: hits.update(index.get(w, [])) if not hits: return f"未找到包含「{query}」的文档" results = [] for path in sorted(hits)[:5]: with open(path, "r", encoding="utf-8") as f: first_line = f.readline().strip() results.append(f"{path} -> {first_line}") return "\n".join(results) if __name__ == "__main__": mcp.run(transport="stdio")当团队共享这个 Server 时,每个人在自己的 Claude Code 或 Cursor 里把模型 Provider 指向 TaoToken,各自用自己的 Key。工具注册统一走 MCP,模型计费统一落在 TaoToken,管理成本远低于每人分别申请官方 Key。
7. 从这 30 行 Server 开始,让 AI 读懂你的项目
MCP 把“让 AI 学会用你的工具”这件事标准化了,写一次 Server,Claude Code、Cursor、TRAE 都能用。但工具层统一不解决模型 Key 的分散问题。我在跑通原文那套 FastMCP 流程后,把模型入口也收拢了:TaoToken 提供统一的兼容通道,Base URL 指向 https://taotoken.net/api,Key 统一用一把,每次模型请求的计费落在一个地方。
从今天这个 30 行的文件读取 Server 开始,先让它跑起来,再往里面加 @mcp.tool() 装饰的函数。下一步很直接:打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 注册、创建你的 API Key,按第 4 章的配置把 Claude Code 或 Cursor 的 Base URL 填好,然后对 AI 说一句“读取当前目录下所有 Python 文件”。完成这次调用后,回到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 看用量记录,你会发现模型请求真的统一记在那把 Key 名下了。