1. 从一次“工具调用失败”说起:MCP 到底是什么
你可能已经用过带工具调用能力的模型,让它查天气、读文件、跑命令。但真到自己写一个能连本地工具的 Demo 时,问题就来了:模型怎么知道有哪些工具?工具的参数格式谁定义?换一个模型客户端,之前写好的工具是不是要重写一遍?
这就是 MCP 要解决的问题。MCP 全称 Model Context Protocol,是 Anthropic 在 2024 年底推出的开放协议。你可以把它理解成 AI 模型和外部工具之间的“USB-C 接口”:模型是电脑,工具是外设,MCP 就是那根标准线。只要工具按 MCP 协议暴露能力,任何支持 MCP 的客户端都能直接调用,不用为每个模型单独适配。
MCP 的通信结构其实不复杂,核心就三个角色:
- MCP Host:发起请求的一方,通常是 AI 应用或 IDE,比如 Claude Desktop、Cline、Cursor。
- MCP Client:Host 内部用来连接 Server 的组件,负责协议握手和消息收发。
- MCP Server:真正提供工具、资源、提示词的一方,可以跑在本地,也可以跑在远端。
传输层上,本地 Demo 最常用的是 stdio,也就是标准输入输出。Host 启动 Server 进程,双方通过 stdin/stdout 交换 JSON-RPC 消息。这种方式不需要开端口,调试直观,适合第一次跑通链路。另一种是 SSE 或 Streamable HTTP,适合远端部署,但初次上手建议先用 stdio 把流程走通。
MCP Server 能暴露三类能力:Tools 是可被模型调用的函数,Resources 是可读取的数据,Prompts 是预置的提示模板。对 Demo 来说,先写一个 Tool 就够了,比如一个加法工具,让模型调用它算3 + 5,看到返回值,整条链路就活了。
那模型侧怎么接进来?MCP 本身不绑定模型,但工具调用最终要由模型决策。这里我用 TaoToken 作为统一模型入口,一个 Key 就能调通多家模型,省去分别申请和切换的麻烦。下面从环境准备开始,一步步把 Demo 跑起来。
2. 用 TaoToken 统一 Key 接入模型侧:环境与前置准备
在写 MCP Server 之前,先把模型侧通道准备好。MCP 负责“工具怎么暴露”,模型负责“决定调哪个工具”,两者配合才能看到完整往返。TaoToken 在这里的角色是提供兼容 OpenAI 风格的 API 入口,你拿到一个 Key,就能在 MCP 客户端里配置模型。
先确认本地环境。我习惯用 conda 管理 Python 环境,避免依赖冲突。如果你还没装 conda,可以用 miniforge3,它比 Anaconda 轻量,安装过程也简单。装好后执行:
conda create -n mcp_demo python=3.11 -y conda activate mcp_demoPython 版本建议 3.11 及以上,MCP 的 Python SDK 对类型注解和异步支持要求较高,3.10 以下容易遇到兼容问题。
接着安装 uv,它是 Rust 写的 Python 包管理器,速度比 pip 快很多,MCP 官方示例也推荐用它:
pip install uv然后创建工程目录:
uv init mcp-server-demo cd mcp-server-demo此时目录里会有pyproject.toml和main.py。把main.py删掉,我们后面自己建文件。先添加依赖:
uv add mcp[cli] httpxmcp[cli]带上了命令行工具,后面调试会用到;httpx用于需要发 HTTP 请求的工具场景,Demo 里可以先留着。
现在去 TaoToken 控制台创建一个 API Key。地址是https://taotoken.net/api-keys,登录后点创建,复制生成的 Key,形如sk-xxxx。这个 Key 后面要填到 MCP 客户端的配置里。
模型侧需要记三个值:
| 配置项 | 值 |
|---|---|
| Base URL | https://taotoken.net/api |
| API Key | 你创建的sk-xxxx |
| Model ID | 例如gpt-4o-mini或claude-3-5-sonnet |
Base URL 不要加 UTM 参数,直接写https://taotoken.net/api即可。Model ID 按你实际想用的模型填,TaoToken 的模型列表可以在控制台或文档里查到。
如果你用的是 Claude Code 这类工具,配置方式略有不同,需要设置ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY。但本篇 Demo 先用通用 MCP 客户端配置,把 stdio Server 跑通。
环境准备好后,目录结构大概是这样:
mcp-server-demo/ ├── pyproject.toml ├── uv.lock └── (待创建) simple.py下一步写 Server 代码,然后配置客户端连接。
3. 可复制配置:写一个最小 MCP Server 并接入客户端
先创建simple.py,这是我们的 MCP Server 主体。代码不长,但每一行都有作用:
from mcp.server.fastmcp import FastMCP mcp = FastMCP("Simple Server") @mcp.tool() def add(a: int, b: int) -> int: """Add两个数字""" return a + b @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """获取个性化问候""" return f"Hello, {name}!" if __name__ == "__main__": print("mcp服务器启动") mcp.run(transport="stdio")FastMCP是高层封装,省去了手写 JSON-RPC 消息的麻烦。@mcp.tool()装饰器把add函数注册成工具,模型能看到函数名、参数类型和 docstring。@mcp.resource()注册一个资源,客户端可以通过 URI 读取。最后mcp.run(transport="stdio")启动服务,等待 Host 通过标准输入输出发消息。
启动测试一下:
uv run simple.py终端会打印mcp服务器启动,然后进程挂起等待输入。这说明 Server 已经就绪,但直接这样跑没法交互,需要客户端连进来。
接下来配置 MCP 客户端。以 Cline 为例,在 VS Code 里安装 Cline 插件后,打开设置,找到 MCP Servers 配置,填入:
{ "mcpServers": { "simple-server": { "command": "uv", "args": [ "--directory", "/绝对路径/mcp-server-demo", "run", "simple.py" ], "env": { "OPENAI_BASE_URL": "https://taotoken.net/api", "OPENAI_API_KEY": "sk-你的Key", "OPENAI_MODEL": "gpt-4o-mini" } } } }注意--directory后面要写你本地的绝对路径,不能用~或相对路径,否则客户端启动 Server 时会找不到文件。env里的三个变量是给模型侧用的,Cline 会读取它们来发请求。如果你用的客户端字段名不同,比如用baseUrl、apiKey、model,按客户端文档调整,值不变。
保存配置后,Cline 会自动启动这个 MCP Server。你可以在 Cline 的 MCP 面板里看到simple-server的状态,如果显示绿色或 connected,说明 stdio 通道建立成功。
此时模型侧和工具侧都准备好了。下一步发一个真实请求,看工具调用能不能往返。
4. 验证请求:一次完整的工具调用往返
在 Cline 的对话框里输入:
请调用 add 工具计算 3 + 5,并告诉我结果。发送后,观察几个关键动作。
第一,Cline 会把可用工具列表发给模型。你可以在 Cline 的请求日志里看到 tools 字段,里面包含add的定义,参数是a和b,类型 integer。这说明 MCP Server 的工具已经成功暴露给客户端。
第二,模型返回一个 tool_call,内容大概是:
{ "name": "add", "arguments": { "a": 3, "b": 5 } }第三,Cline 把这个调用转发给 MCP Server。Server 执行add(3, 5),返回8。这个返回值通过 stdio 回传给 Cline,Cline 再作为 tool result 发给模型。
第四,模型拿到结果后生成最终回复:“3 + 5 的结果是 8。”
整个过程在几百毫秒到几秒内完成,取决于模型响应速度。如果你在 Cline 里看到类似下面的输出,说明链路完全跑通:
Tool: add Arguments: {"a": 3, "b": 5} Result: 8 Assistant: 3 + 5 的结果是 8。再测一下资源读取。在对话框输入:
请读取 greeting://Alice 这个资源。模型会发起 resource 读取请求,Server 返回Hello, Alice!。这验证了 Resources 通道也正常工作。
如果你想更直观地调试,可以用 MCP Inspector。先安装:
pip install "mcp[cli]"然后运行:
mcp dev simple.py终端会输出:
Starting MCP inspector... Proxy server listening on port 6277 MCP Inspector is up and running at http://127.0.0.1:6274浏览器打开http://127.0.0.1:6274,你能看到 Tools 和 Resources 列表,点击add填入参数直接调用,结果实时显示。这个工具不经过模型,纯粹测 Server 本身,排障时很有用。
到这里,MCP 从请求到响应的完整链路已经验证完毕。接下来整理几个我实际踩过的报错,帮你少走弯路。
5. 常见报错排查:401、local proxy failed 与 reading choices
401 Unauthorized
这是模型侧鉴权失败。检查 Cline 配置里的OPENAI_API_KEY是否填了 TaoToken 的 Key,有没有多余空格。如果 Key 正确但仍报 401,确认OPENAI_BASE_URL是不是https://taotoken.net/api,末尾不要加/v1或斜杠,有些客户端会自动拼接路径,多一层就 404 或 401。另外,Key 如果被删除或过期,也会返回 401,去控制台重新创建一个即可。
local proxy failed / connection refused
这个报错通常出现在客户端启动 MCP Server 时。原因一般是command或args路径不对。检查--directory后面的路径是否存在,simple.py文件名是否拼错。如果你用uv run,确认 uv 已安装且在 PATH 里。另一个常见原因是 Python 环境不对,客户端调用的uv可能指向了另一个环境,导致mcp包找不到。可以在配置里把command写成 uv 的绝对路径,比如/Users/你的用户名/.local/bin/uv,避免歧义。
reading choices 相关报错
这类报错通常来自模型返回格式解析失败。比如客户端期望 OpenAI 格式的choices数组,但模型返回了非标准结构。先确认 Model ID 是否拼写正确,TaoToken 支持的模型名要完全匹配。如果模型名对了还报错,检查客户端版本是否过旧,老版本可能不支持某些模型的返回格式。升级 Cline 或换一个模型试试,比如从gpt-4o-mini换成claude-3-5-sonnet,能快速判断是模型侧还是客户端侧的问题。
OAuth 相关报错
如果你在配置里误加了 OAuth 相关字段,或者客户端尝试用 OAuth 流程连接,会报 token 获取失败。MCP 的 stdio 模式不需要 OAuth,把配置里多余的auth字段删掉,只保留command、args、env即可。TaoToken 的 API Key 认证是直接放在 header 里的,不需要额外授权流程。
工具调用返回空或超时
如果模型一直不调用工具,检查add函数的 docstring 是否清晰。模型靠 docstring 判断工具用途,写得太模糊可能不触发。另外,参数类型要标注准确,a: int和b: int不能省。如果调用后超时,看 Server 进程是否还在运行,stdio 模式下 Server 崩溃会导致客户端一直等。
排查时建议按顺序:先确认 Server 能单独启动,再用 Inspector 测工具,最后接客户端测模型。分层定位,比一上来就查模型快得多。
6. 把 Demo 变成日常工具:下一步怎么走
跑通这个 Demo 后,你可以把add换成真实工具,比如读本地文件、查数据库、调内部 API。MCP 的价值在于,你写一次 Server,所有支持 MCP 的客户端都能用,不用为每个 IDE 或聊天工具重写适配层。
模型侧继续用 TaoToken 的统一 Key,换模型只改一个 Model ID,Base URL 和 Key 不动。这样你在不同场景下可以灵活切换:写代码用擅长代码的模型,做总结用长上下文模型,成本可控。
如果你打算长期做编码类 Agent,可以看看 TaoToken 的 Coding Plan,它针对高频调用场景做了额度优化。接入文档在https://taotoken.net/doc,里面有各客户端的配置示例。想先验证模型效果,直接去https://taotoken.net/chat对话测试。API Key 管理在https://taotoken.net/api-keys,随时可以创建和吊销。
下一步我建议你试着自己写一个read_file工具,让模型读取指定路径的文件内容。注意加路径校验,别让它读到敏感目录。写完用 Inspector 测一遍,再接到客户端里让模型调用。这个练习能把 MCP 的 Tools 机制吃透,后面上生产也有底。