1. 从零写一个 MCP Server,为什么我建议先解决 Key 分散问题
MCP Server 这个词最近出现频率很高,但很多人第一次接触会有点懵:它到底是什么、能做什么、适合谁。用一句话说,MCP(Model Context Protocol)是一套让大模型客户端(比如 Claude Desktop、Cline、Cherry Studio)去调用你本地自定义工具的协议,而 MCP Server 就是你用 Python 写出来的那个“工具提供方”。它把函数、资源、提示词注册成标准接口,客户端连上来之后,模型就能像调用内置能力一样调用你的代码。
我这次要做的场景很具体:本地有一堆小工具,比如算数、查天气、读文件、格式化文本,每个工具如果都单独配一套密钥和 API 地址,维护起来会非常痛苦。所以我打算用 Python 从零实现一个 MCP Server 自定义案例,再把它接入 TaoToken 的统一 Key/API 通道,让所有工具调用都走同一个入口。这样客户端只需要认一个 Base URL 和一个 Key,模型侧也统一走 TaoToken 的模型对话能力。
适合读这篇的人:写过一点 Python、装过 conda 或 venv、用过 Cline 或 Cherry Studio 这类客户端插件、被多份密钥配置折磨过的人。整篇我会给出可复制的 server 配置片段、依赖清单,以及一次端到端调用验证步骤,保证你在本地能跑通自定义工具注册与调用。踩过的坑我也会写清楚,尤其是路径和 401 这两类高频问题。
先说结论:MCP Server 本身不复杂,复杂的是“怎么让客户端稳定连上、怎么让模型调用走统一通道”。前者靠绝对路径和正确的启动命令,后者靠 TaoToken 的 Base URL + Key + Model ID 三件套。下面按顺序来。
2. TaoToken 前置准备:统一 Key 与 API 通道怎么配
在写代码之前,先把 TaoToken 这一侧准备好。你可以把它理解成一个统一的模型调用入口:不管你的 MCP Server 里要调用哪个模型,客户端和工具侧都只需要认同一个 API 地址和同一个 Key。官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api (这个不加 UTM,直接填到配置里)。
第一步,进控制台创建 API Key。打开 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在 API Keys 页面新建一个 Key,复制出来先存到本地环境变量里,别直接硬编码进代码。我一般这样写:
# Linux / macOS export TAOTOKEN_API_KEY="sk-你的key" # Windows PowerShell $env:TAOTOKEN_API_KEY="sk-你的key"第二步,确认你要用的 Model ID。不同客户端对模型名的写法略有差异,但核心就是 Base URL + Key + Model ID 三件套。你可以先在模型对话页面 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 里试一下,确认这个 Key 能正常出结果,再去接 MCP Server。这一步很关键,因为后面如果 MCP 调用报 401,你至少能判断是 Key 本身的问题还是配置写错了。
第三步,如果你打算长期跑编码类或 Agent 类任务,可以看下 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,它更适合高频调用场景。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,遇到参数不确定的时候直接查这里。
这里有个细节要注意:MCP Server 本身是本地进程,它不直接“连”TaoToken,真正连 TaoToken 的是调用模型的客户端(比如 Cline、Cherry Studio)或者你 Server 内部发起的 HTTP 请求。所以统一 Key 的意义在于——客户端侧只配一次,Server 侧如果需要调模型也只读同一个环境变量。这样就不会出现“这个工具用 A Key、那个工具用 B Key”的混乱。
把这三样准备好:API Key、Base URL(https://taotoken.net/api)、Model ID。后面所有配置都围绕它们展开。
3. 可复制配置:server_test.py 与客户端 JSON 片段
现在开始写代码。先装依赖,官方 Python SDK 是 mcp 包:
pip install mcp如果你用 conda 环境,先激活再装,避免装到全局去。我用的环境路径后面会体现在客户端配置里,你换成自己的即可。
新建server_test.py,内容如下,这是一个包含 tool、resource、prompt 三类注册的最小可用案例:
from mcp.server.fastmcp import FastMCP mcp = FastMCP("Echo") @mcp.resource("echo://{message}") def echo_resource(message: str) -> str: """Echo a message as a resource""" return f"Resource echo: {message}" @mcp.tool() def echo_tool(message: str) -> str: """Echo a message as a tool""" return f"Tool echo: {message}" @mcp.prompt() def echo_prompt(message: str) -> str: """Create an echo prompt""" return f"Please process this message: {message}" @mcp.tool() def add(a: int, b: int) -> int: """计算两个数和""" return a + b @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """Get a personalized greeting""" return f"Hello, {name}!" if __name__ == "__main__": mcp.run()直接运行:
python server_test.py进程会挂起等待客户端连接,这是正常的。开发阶段可以用mcp dev server_test.py启动一个调试页面,方便你手动点一下工具看返回。
接下来是客户端配置。以 Cline(VS Code 插件)为例,在 MCP 配置里写:
{ "mcpServers": { "mcp-server": { "command": "C:\\Users\\loong\\.conda\\envs\\agent\\python.exe", "args": [ "E:\\code\\agent\\server_test.py" ] } } }注意两点:command指向你环境里的 python.exe 绝对路径,args里的脚本路径也必须是绝对路径。这是最容易翻车的地方,相对路径在客户端拉起子进程时经常解析不到,表现就是连接失败或者报 32000 之类的错误。
如果你用的是 Cherry Studio,配置结构类似,同样把 python 解释器路径和脚本路径写成绝对路径。模型侧统一填 TaoToken 的三件套:
{ "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的key", "model": "你的ModelID" }这样客户端连本地 MCP Server 拿工具,模型调用走 TaoToken 统一通道,两边职责清晰。Server 里如果某个工具需要调模型,也读同一个TAOTOKEN_API_KEY环境变量,不要另起一套。
4. 验证请求:一次端到端调用与成功结果
配置写完,怎么确认真的通了?分三步验证。
第一步,单独跑 Server,确认进程能起来、没有语法错误:
python server_test.py如果卡住不报错,说明 FastMCP 正常启动。如果报ModuleNotFoundError: No module named 'mcp',说明依赖装到了别的环境,回到第 3 步用绝对路径的解释器重装。
第二步,用mcp dev server_test.py打开调试页面,手动调用add工具,传a=3, b=5,预期返回8。再调echo_tool,传message="hi",预期返回Tool echo: hi。这一步能过,说明工具注册没问题。
第三步,回到客户端(Cline 或 Cherry Studio),在对话里让模型调用add。比如输入“用 add 工具算一下 12 加 30”,模型应该会触发工具调用,返回 42。同时观察客户端日志,确认模型请求打到了https://taotoken.net/api,而不是别的地址。
成功的结果长这样:工具调用有返回、模型能读到返回值并继续回答、日志里 Base URL 是 TaoToken 的地址。如果工具能调但模型没反应,多半是模型侧配置没生效;如果模型能答但工具没触发,多半是 MCP Server 没连上。分开排查,别混在一起看。
我实测下来,最容易出问题的是“客户端拉起了 Server,但 Server 用的解释器不对”。表现是工具列表为空。解决办法就是第 3 步里那个绝对路径,一定要指向装了 mcp 包的那个 python。
5. 本篇常见错排查:401、local proxy failed、32000 怎么解
把几个高频报错对照着说,方便你快速定位。
401 Unauthorized:模型侧 Key 无效或没带上。检查apiKey是不是复制完整、有没有多余空格、环境变量有没有生效。如果 Key 是对的还报 401,确认 Base URL 写的是https://taotoken.net/api,不要漏掉/api,也不要自己拼别的路径。可以先去模型对话页面用同一个 Key 试一次,排除 Key 本身的问题。
local proxy failed / connection refused:客户端连不上本地 MCP Server。常见原因是 Server 没启动、启动命令路径错、或者端口被占。先手动python server_test.py确认能跑,再检查客户端配置里的command和args是不是绝对路径。Windows 上路径反斜杠要转义成\\,这是 JSON 语法要求。
reading 'choices' 相关报错:一般是模型返回结构不符合预期,常见于 Base URL 或 Model ID 写错,请求打到了不兼容的接口。核对三件套,确认 Model ID 是你在 TaoToken 侧真实可用的那个。
32000 报错:客户端添加 MCP Server 时路径解析失败。原文里特别提到过——server 源码里如果有路径地址,全部用绝对路径,用相对路径客户端添加就会报 32000。把args里的脚本路径改成E:\\code\\agent\\server_test.py这种完整形式。
OAuth 相关提示:如果你在客户端里看到 OAuth 字样,通常是客户端把某个远程服务当成了需要授权的端点。本地 MCP Server 不需要 OAuth,检查是不是配置里混入了别的 server 条目,或者 Base URL 填成了需要鉴权的地址。清理掉多余配置,只留本地 server 和 TaoToken 三件套。
工具列表为空:Server 起来了但客户端读不到工具。检查@mcp.tool()装饰器有没有漏、函数有没有语法错误、解释器是不是装 mcp 的那个。用mcp dev能看到的工具,客户端理论上都能看到。
排查顺序建议:先确认 Server 单独能跑 → 再确认客户端能拉起 Server → 最后确认模型侧三件套正确。一层一层来,比一上来就改一堆配置高效得多。
6. 把统一 Key 用起来:后续扩展与接入入口
跑通这个最小案例之后,你可以往 Server 里继续加工具,比如读本地文件、调内部接口、做数据清洗。每加一个工具,只要用@mcp.tool()注册,客户端重新连一次就能看到。模型侧不用改,还是那套 TaoToken 三件套。
如果你要把这套东西接到 Claude Code 这类编码场景,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有 Base URL、Key、Model ID 的完整说明。需要新建或轮换 Key 就去 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。想先验证模型通不通,用模型对话页面最快。长期跑 Agent 或高频编码任务,Coding Plan 更合适。
最后留一个实用技巧:把TAOTOKEN_API_KEY写进系统环境变量而不是代码里,Server 和客户端都读同一个变量。这样换 Key 的时候只改一处,所有工具链自动生效——这正是“统一 Key 打通本地工具链”最省事的地方。