1. 从零构建 MCP Server:为什么值得折腾
如果你正在用 Claude、Cursor 或 Trae 这类 AI 工具,大概率遇到过这样的场景:想让模型读一下本地某个目录的日志、查一下内部接口的状态、或者把一段结构化数据塞进对话里,结果发现模型只能靠你手动复制粘贴。Model Context Protocol(MCP)就是来解决这个问题的——它把「模型能调用的工具」标准化成一个轻量服务,AI 客户端通过协议去请求,你只需要维护一个 Server。
MCP 常被类比成 AI 应用的 USB-C 接口:客户端是电脑,Server 是外设,插上就能用,不用为每个模型单独写适配。它适合三类人:一是想让 Claude Desktop 直接操作本地文件或数据库的开发者;二是想把内部 API 包装成工具给 LLM 用的后端同学;三是正在做 Agent、需要统一工具入口的团队。本文会从 FastMCP 骨架开始,写一个可运行的工具服务,再把它接到 TaoToken 的统一 Key/API 通道上,最后给出 settings.json 与 config.toml 的可复制配置和连通性验证动作。全程按「能跑通」的标准来,不堆概念。
2. 前置准备:TaoToken 通道与 MCP 运行环境
MCP Server 本身是本地进程,它不直接跟模型通信,而是被客户端调用。真正跟模型对话的那一层,需要一个稳定的 API 入口。我这边统一用 TaoToken 来做这件事:它提供一个兼容常见协议的统一 Key 和 API 地址,Claude、Codex 这类工具只要把 base_url 指过去就能用,省得每个工具单独配一套凭证。
你需要先拿到两样东西:
- 一个 API Key:在控制台创建,地址是 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite
- 确认 API 基地址:https://taotoken.net/api(这个地址不加 UTM,直接填进配置)
环境侧,MCP 的 Python SDK 要求 Python 3.10 以上,推荐用 uv 管理虚拟环境,因为它启动快、依赖隔离干净。装 uv 的命令:
curl -LsSf https://astral.sh/uv/install.sh | sh装完重开终端,确认uv --version能输出。Windows 用户可以用powershell -c "irm https://astral.sh/uv/install.ps1 | iex"。这一步别跳过,后面uv run启动 Server 全靠它。
注意:MCP Server 跑在本地,客户端通过 stdio 或 HTTP 跟它通信。所以你的 API Key 是配在「客户端调用模型」那一层,不是配在 Server 里。两者别混。
3. 可复制配置:FastMCP 骨架与工具注册
先建项目。下面这套命令会创建目录、虚拟环境和依赖:
uv init mcp-demo cd mcp-demo uv venv source .venv/bin/activate uv add "mcp[cli]" httpx touch server.pyserver.py里写一个最小可用的 Server,包含两个工具:一个读本地文件行数,一个查 HTTP 接口状态。工具注册靠@mcp.tool()装饰器,函数签名和 docstring 会自动变成模型看到的工具描述。
from typing import Any import httpx from mcp.server.fastmcp import FastMCP mcp = FastMCP("demo-server") @mcp.tool() async def count_lines(path: str) -> str: """统计指定文本文件的行数。 Args: path: 文件的绝对路径 """ try: with open(path, "r", encoding="utf-8") as f: n = sum(1 for _ in f) return f"{path} 共 {n} 行" except Exception as e: return f"读取失败: {e}" @mcp.tool() async def check_status(url: str) -> str: """请求一个 URL 并返回 HTTP 状态码。 Args: url: 要检查的完整 URL """ async with httpx.AsyncClient(timeout=10.0) as client: try: r = await client.get(url) return f"{url} -> {r.status_code}" except Exception as e: return f"请求异常: {e}" if __name__ == "__main__": mcp.run(transport="stdio")跑起来验证一下:
uv run server.py如果没报错、进程挂起等待输入,说明 Server 正常。stdio 模式下它不会打印欢迎语,这是预期行为。
接下来是客户端配置。Claude Desktop 的配置文件在 macOS 是~/Library/Application Support/Claude/claude_desktop_config.json,Windows 是%AppData%\Claude\claude_desktop_config.json。把 Server 注册进去:
{ "mcpServers": { "demo": { "command": "uv", "args": [ "--directory", "/ABSOLUTE/PATH/TO/mcp-demo", "run", "server.py" ] } } }路径必须是绝对路径,相对路径会静默失败。如果你用的是支持 TOML 配置的客户端(比如某些 CLI 工具),等价写法是:
[mcp_servers.demo] command = "uv" args = ["--directory", "/ABSOLUTE/PATH/TO/mcp-demo", "run", "server.py"]模型通道那边,把 base_url 指向 TaoToken,Key 填你创建的那串。以 Claude 系工具为例,环境变量方式:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="你的Key"这样客户端调模型走 TaoToken,调工具走本地 MCP Server,两条链路互不干扰。
4. 验证请求:从工具列表到真实调用
配置保存后完全重启客户端。以 Claude Desktop 为例,界面上会出现一个工具图标,点开应该能看到count_lines和check_status两个工具。如果看不到,先别急着改代码,八成是配置路径或 JSON 语法问题。
验证分三步走:
第一步,确认工具被识别。在对话里直接问「你有哪些工具」,模型会列出注册的工具名和描述。这一步验证的是 MCP 握手成功。
第二步,触发一次真实调用。输入「帮我统计 /tmp/test.log 有多少行」,模型会请求调用count_lines,你批准后返回结果。这一步验证的是 stdio 通信和函数执行。
第三步,验证模型通道。问一个纯对话问题,比如「用一句话解释 MCP」,如果正常返回,说明 TaoToken 的 API 通道是通的。想单独测模型连通性,可以用模型对话页面直接发一条消息:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite
命令行侧也可以用 curl 快速探一下 API 是否可达:
curl -s -o /dev/null -w "%{http_code}\n" https://taotoken.net/api返回 200 或 401 都说明网络层通了,401 只是没带 Key。带上 Key 的完整请求按你所用协议的格式来,Anthropic 协议大致是:
curl https://taotoken.net/api/v1/messages \ -H "x-api-key: 你的Key" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{"model":"claude-sonnet-4-20250514","max_tokens":64,"messages":[{"role":"user","content":"ping"}]}'能拿到 JSON 响应就说明通道没问题。如果这里报模型名错误,换成你账号下可用的模型标识即可。
5. 常见报错排查:Server 不显示、工具静默失败
工具图标不出现。九成是claude_desktop_config.json的 JSON 语法错了,比如多了个逗号、路径没转义。用python -m json.tool claude_desktop_config.json校验一下。另外确认路径是绝对路径,Windows 下反斜杠要写成\\。
Server 启动即退出。在终端手动跑uv run server.py,看有没有 traceback。常见原因是 Python 版本低于 3.10,或者mcp[cli]没装进当前虚拟环境。用uv run python -c "import mcp; print(mcp.__version__)"确认。
工具调用静默失败。模型说要用工具但没结果,通常是函数抛异常被吞了。把工具函数里的异常都 catch 住并返回字符串,别让它往上抛。另外检查 docstring 是否清晰——模型靠它判断该不该调用。
改了代码不生效。MCP Server 是客户端启动时拉起的子进程,改完代码必须完全退出客户端再重开,光关窗口不够。
API 返回 401/403。Key 没带对,或者 base_url 写成了带路径的形式。基地址就是https://taotoken.net/api,别自己拼/v1,具体路径由协议决定。
长时间编码任务想省心。如果你打算把 MCP 工具接进日常编码流、频繁调用模型,可以看下 Coding Plan,它按订阅方式给额度,比单次调用更适合高频场景:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite
6. 把 MCP 接进你的工作流
跑通之后,真正有价值的是把重复动作沉淀成工具。我的做法是:凡是「每次都要手动复制一段数据给模型」的操作,就抽成一个 MCP 工具。比如读 CI 日志、查数据库某张表的行数、拉内部接口的健康状态。工具描述写清楚参数含义,模型自己会判断什么时候调。
配置层面,把 Server 的启动命令和 TaoToken 的通道配置分开管理:Server 配置放客户端的 mcpServers 段,模型通道放环境变量或客户端自己的 provider 设置。这样换模型、换 Key 都不影响工具层。接入文档里有各协议的详细字段说明,配之前扫一眼能少踩坑:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
最后提醒一句:MCP Server 能访问本地文件和内网接口,权限边界要自己把控。别把生产库的写操作直接暴露成工具,读操作也尽量加白名单。工具是给模型用的,但批准权始终在你手里。