🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度
TaoToken 在这条链路里只承担一个角色:MCP 客户端的默认供应商。今天要验证的东西很小——在一个 MCP 客户端里注册一个天气查询 Skill,然后看模型能不能把「上海现在冷不冷」自动折叠成 get_weather(city="上海") 这样干净的 JSON 参数,拿到工具返回的数据之后再组织成人话。天气准不准不是重点,重点是 tool calling 这一圈有没有闭上:模型认得出该调工具、参数名和类型对得上 schema、工具结果回来之后它不再自己编温度。
选 Kimi K2.7 Code 配这个任务,是因为天气 Skill 的参数面极窄——就一个 city 字符串。参数越窄,越容易看出模型是真的在读工具描述,还是靠猜。如果它把「上海现在冷不冷」整句话塞进 city 字段,你在日志里一眼就能抓到;换成参数复杂的 SQL 类工具,反而容易被一堆形参掩盖问题。
环境清单其实就四样东西,而且每一样都能替换:MCP 客户端用 Cline,VS Code 里的扩展,自带 MCP Servers 面板,改 JSON 就能加工具;模型用 Kimi K2.7 Code,请求走统一 API 通道;天气 Skill 是一个本地 stdio 进程,Python 起一个,调用 open-meteo 的公开接口,不需要另外申请 Key;运行依赖是 Python 3.10+ 和 uv,或者直接用 pip 装 mcp 与 httpx。
一条链路上有三个可能卡住的地方——MCP 进程要不要预装依赖、请求打到网关的路径对不对、天气接口自己慢不慢。十分钟不是花在写代码上,是花在这三段上。下面每一步都给可复制的配置和一句自检命令,哪里断了能立刻定位。
本文不含排行分数,也不比较各家模型的能力;这里的「跑通」只指 MCP 工具调用闭环。数字只出现在调用日志里,而且天气数值每次都不一样。
2. 注册天气 Skill:MCP Server 代码与客户端配置 JSON
2.1 一个只做一件事的天气 MCP Server
社区里现成的天气 MCP Server 不少,但版本和工具名经常变,配置抄过来容易对不上。这里给一个四十行左右的本地实现,参数面固定成一个 city 字符串,方便你复现,也方便随手改。
# weather_mcp.py
import json
import httpx
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather")
GEO = "https://geocoding-api.open-meteo.com/v1/search"
FORECAST = "https://api.open-meteo.com/v1/forecast"
WMO = {
0: "晴", 1: "少云", 2: "多云", 3: "阴",
45: "雾", 48: "雾凇",
51: "毛毛雨", 53: "小雨", 55: "中雨",
61: "小雨", 63: "中雨", 65: "大雨",
71: "小雪", 73: "中雪", 75: "大雪",
80: "阵雨", 81: "强阵雨", 82: "暴雨", 95: "雷暴",
}
@mcp.tool()
def get_weather(city: str) -> str:
"""查询一个城市的当前天气。city 传中文城市名,例如 上海。"""
with httpx.Client(timeout=10) as client:
geo = client.get(GEO, params={
"name": city, "count": 1, "language": "zh", "format": "json",
}).json()
hits = geo.get("results") or []
if not hits:
return json.dumps({"error": f"未找到城市:{city}"}, ensure_ascii=False)
hit = hits[0]
cur = client.get(FORECAST, params={
"latitude": hit["latitude"],
"longitude": hit["longitude"],
"current": "temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m",
}).json()["current"]
return json.dumps({
"city": hit["name"],
"temperature_c": cur["temperature_2m"],
"humidity_pct": cur["relative_humidity_2m"],
"wind_kmh": cur["wind_speed_10m"],
"condition": WMO.get(cur["weather_code"], f"code={cur['weather_code']}"),
}, ensure_ascii=False)
if __name__ == "__main__":
mcp.run()
保存成 weather_mcp.py。三个细节决定了后面会不会踩雷:装饰器 @mcp.tool() 会自动把函数名当工具名、把 docstring 当工具描述,描述里写了「中文城市名,例如 上海」,模型把「上海」映射到 city 字段的成功率会明显高一点;返回值统一是 json.dumps(..., ensure_ascii=False) 的字符串,中文不会被转义成 \uXXXX,模型读起来更省 token;找不到城市时返回一个带 error 字段的 JSON 而不是抛异常,模型能读懂失败原因,再决定要不要换个城市名重试。
2.2 把 server 注册进 Cline 的 MCP 配置 JSON
Cline 的 MCP 配置文件叫 cline_mcp_settings.json,放在扩展的 globalStorage 目录下,Windows 一般在 %APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\,macOS 在 ~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/。也可以在 MCP Servers 面板里点 Configure 直接打开。往里加一段:
{
"mcpServers": {
"weather": {
"type": "stdio",
"command": "uv",
"args": [
"run",
"--with", "mcp",
"--with", "httpx",
"D:/mcp/weather_mcp.py"
],
"disabled": false,
"autoApprove": ["get_weather"],
"timeout": 90
}
}
}
字段解释尽量短。command 用 uv,是为了让它顺带把依赖装进临时环境;你本机如果已经 pip 装了 mcp 和 httpx,把 command 换成 python、args 只留脚本绝对路径也完全可以。timeout 单位是秒,Cline 默认偏短,第一次启动要拉依赖,先给到 90 更稳。autoApprove 只放 get_weather,别图省事写 true——天气工具是只读的,但以后你往里加别的 server,全自动批准会变成隐患。
args 里的脚本路径建议写绝对路径。相对路径在客户端切换工作区之后经常找不到文件,表现出来就是面板上一直转圈,或者直接显示 disconnected,而你不会第一时间想到是路径问题。
2.3 启动自检:先手动跑一遍
在把 JSON 交给客户端之前,先在终端跑一次:
uv run --with mcp --with httpx weather_mcp.py
stdio 类型的 MCP Server 正常启动后不会打印任何东西,光标停住不退出就是对的状态,按 Ctrl+C 结束。如果它吐了 Traceback,那就是脚本自己的问题,跟客户端和网关都无关。这一步不做,你会在客户端里看到一句没有信息量的 "MCP server disconnected",然后开始怀疑网络——方向就偏了。
3. 让 Kimi K2.7 Code 走 TaoToken:Base URL、Key 与模型 ID
MCP 工具注册好之后,模型这边只差三样东西:Key、Base URL、模型 ID。Key 在 TaoToken 控制台创建,创建完立刻复制,页面关掉之后明文就不再显示,只能重建一条。三样东西里最容易填错的是 Base URL,因为它错的方式很安静。
3.1 Cline 侧的三件套
Cline 的设置面板里,API Provider 选 OpenAI Compatible,然后逐项填:
| 配置项 | 填什么 |
|---|---|
| Base URL | https://taotoken.net/api |
| API Key | YOUR_API_KEY |
| Model ID | kimi-k2.7-code(以模型广场为准) |
| Context Window | 按广场标注的值填,别随手写大 |
| 流式输出 | 排障阶段先关掉,少一个变量 |
Base URL 只写到 https://taotoken.net/api,末尾不要自己补 /v1。有些客户端会在你填的地址后面自动追加 /v1,两边一叠就变成 /api/v1/v1/...,返回 404,而报错信息通常只有一句 not found,很容易被误判成 Key 失效。真遇到 404,先翻日志里客户端实际请求的完整路径,再决定是改客户端设置还是改填写方式。
模型 ID 不要凭记忆写。各家模型在广场上的 ID 和官方页面上的名字未必一致,带不带日期后缀、用连字符还是点号,都可能差一个字符。填之前打开模型广场对一眼,把 Kimi K2.7 Code 对应的那串 ID 复制过来,粘贴比手打可靠得多。
3.2 Claude Code 当 MCP 客户端时的写法
如果你习惯用 Claude Code,它本身也是一个 MCP 客户端,环境变量写在 ~/.claude/settings.json 的 env 里:
{
"env": {
"ANTHROPIC_BASE_URL": "https://taotoken.net/api",
"ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY",
"ANTHROPIC_MODEL": "kimi-k2.7-code"
}
}
注册天气 server 用一条命令就行,注意 -- 后面全部是要执行的进程:
claude mcp add weather -- uv run --with mcp --with httpx /绝对路径/weather_mcp.py
claude mcp list
claude mcp list 能看到 weather 且状态是 connected,就说明注册成功。也可以用官方 CLI 一次把三件套写好:
npm install -g @taotoken/taotoken
taotoken cc -k YOUR_API_KEY -u https://taotoken.net/api -m kimi-k2.7-code
三个变量里,ANTHROPIC_BASE_URL 同样只写 https://taotoken.net/api。ANTHROPIC_MODEL 要和模型广场上的 ID 完全一致,Claude Code 不做模糊匹配,名字差一个字符就是一次 400,而且错误信息里不会告诉你「可能是模型名写错了」。
4. 一次成功调用长什么样:从 tool_use 到城市天气
判断跑没跑通,不看它答得多漂亮,只看两段日志:模型发出的工具调用参数,以及工具真正的返回值。这两段对得上,链路就是闭的;对不上,回答再通顺也是模型在自由发挥。
4.1 调用日志
跑通之后,客户端里一次完整调用的记录形态大致是这样:
[user] 上海现在冷不冷?
[tool_use] get_weather
{ "city": "上海" }
[tool_result]
{"city": "上海", "temperature_c": 27.4, "humidity_pct": 71,
"wind_kmh": 12.6, "condition": "多云"}
[assistant] 上海现在 27.4℃,多云,湿度 71%,风速 12.6 km/h,
体感偏闷,短袖够用,早晚备一件薄外套。
日志里的温度是那次运行时接口返回的真实数值,天气每小时都在变,你跑出来的数字不会和这里一样。
值得盯的是 tool_use 的 input:它是一个只有 city 一个键的合法 JSON,值是「上海」两个字,没有把整句问话塞进去,也没有多出模型自己编的参数。参数干净,说明模型读懂了工具 schema;参数脏,后面天气接口返回什么都是碰运气——你甚至可能看到它把「上海现在冷不冷」整段当城市名传进去,然后 server 返回「未找到城市」,模型再一本正经地解释说查不到。
tool_result 那一行是 server 的返回值。工具返回值进了上下文之后,模型的最终回答里不应该出现日志中没有的数字。如果它答「上海 26 度,适合穿毛衣」,而日志里明明是 27.4 和多云,那问题就不是配置,是模型没有忠实使用工具结果。这种回答在 Agent 场景里比直接报错更麻烦,因为它看起来是对的。
4.2 三条验证 Prompt
一条成功不算跑通,至少过三条:
| 输入 | 期望行为 | 出问题的信号 |
|---|---|---|
| 上海现在冷不冷? | 调用 get_weather,city=上海 | 直接编一个温度,或把整句塞进参数 |
| 帮我看看北京和深圳 | 连续两次调用,各自带城市名 | 只查一个城市,另一个靠猜 |
| 你好,介绍一下你自己 | 不调用任何工具 | 无意义地调一次天气工具 |
第三条最容易被忽略。工具描述写得越宽泛,模型越容易在不该调的时候调一次,白花一次往返,还多占一轮上下文。把 docstring 收窄到「查询指定城市的当前天气」,误触发会明显减少。另外,工具描述本身每轮请求都要带,工具数量涨上来之后,上下文会被 schema 挤占,天气这种小工具描述越短越好。
5. 超时排查:MCP 天气 Skill 的四层时间线
MCP 链路超时不是一个点,是四段串起来的:进程启动、客户端到网关、工具内部的 HTTP 调用、客户端等待整个 tool loop 结束。按时间顺序查,比反复重启客户端有效得多,也省得同时改三处配置还不知道是哪一处生效了。
5.1 第一层:MCP 进程启动
客户端点开 server 之后,先要 fork 一个进程、装依赖、初始化 stdio。uv run --with mcp --with httpx 第一次执行会下载包,几十秒很正常,而 Cline 默认的 MCP timeout 撑不到那么久,结果就是面板报超时,实际上进程还在老老实实下载。处理办法有三个:把 timeout 调到 90 到 120;先在终端手动跑一次把依赖缓存下来;或者提前 pip install mcp httpx,配置里的 command 直接写 python。这三种做任何一种,这一层的超时基本就消失了。
5.2 第二层:客户端到网关的请求
这一段报错通常不是超时,是 401 或 404。401 对应 Key——有没有多余的引号、有没有把别处的 Key 复制过来、控制台里这条 Key 是不是已经被删。404 先怀疑路径:Base URL 写成 https://taotoken.net/api 之后,客户端再自动补一次 /v1,请求就会落到不存在的路径上。模型 ID 写错则常见 400 或提示 model not found,含义完全不同,别混在一起改。
还有一种「像超时但不是超时」的情况:上下文窗口填得比实际大,客户端按大窗口去发请求,服务侧一直等不到完整输出,看起来就是卡住。排障阶段把上下文窗口按模型广场标注的值填,别往大写,这一条能省掉很多莫名其妙的等待。
5.3 第三层:天气接口本身
本地 server 里的 httpx 调用如果没有设 timeout,Open-Meteo 偶发慢响应时,整个 MCP 调用会一直挂在那里,客户端看起来像卡死,其实是在等一个不会来的响应。上面代码里 httpx.Client(timeout=10) 就是干这个的。更稳的做法是把异常也转成 JSON 返回:
try:
# 原有的地理编码与天气请求
...
except Exception as e:
return json.dumps({"error": f"天气接口暂时不可用:{e}"}, ensure_ascii=False)
工具返回一段能读懂的错误,模型会明确告诉用户「这次查询失败了」,而不是让整条链路悬在半空等你手动中断。
5.4 第四层:日志到底在哪看
- Cline:MCP Servers 面板里点 server 名,能看到进程输出和每次工具调用的耗时
- Claude Code:用
claude --debug启动,MCP 的连接、工具列表、往返都会打出来;claude mcp list只看连接状态 - 判断超时发生在哪一层,看日志最后一条停在哪:停在 server 启动就是第一层,停在发请求就是第二层,停在工具执行就是第三层
实测下来,最常见的组合是「第一次装依赖」加上「timeout 没调」,两件事各做一次,后面基本就顺了。还有个容易忘的点:改完 JSON 配置要重启客户端或重新加载 MCP 面板,不然你以为改了配置,其实跑的还是旧的进程。
6. 用同一把 Key 复现 MCP 天气调用
复现的时候尽量只改一个变量:同一把 Key、同一份 weather_mcp.py、同一条「上海现在冷不冷」,换模型或换客户端再跑一次,你就能分清到底是模型不会调工具,还是客户端没把工具注册进去。只改一个变量这件事听起来啰嗦,但它是把「跑不通」拆成可判断小问题的唯一办法。
复现清单按这个顺序走:先在 TaoToken 创建一条 Key,Base URL 填 https://taotoken.net/api;保存 weather_mcp.py,终端手动启动一次确认没有 Traceback;把 MCP 配置 JSON 写进客户端,timeout 给到 90;模型 ID 从模型广场复制,别手打;最后三条验证 Prompt 全过一遍,重点看 tool_use 的 input 是不是合法 JSON。
这次调用到底有没有入账、扣了多少,去 模型对话 对一眼记录;要长期挂着跑 MCP 工具,Coding Plan 比按次更省事;Key 在 控制台 建。Claude Code 的三件套对照 接入文档。
整条链路跑完之后,你手里就有了一个最小可用的 MCP 测试台:工具只有一个、参数只有一个字段,任何模型接进来,几分钟就能看出它会不会按 JSON 参数调用工具。天气 Skill 只是个壳子,真正留下来的是这套判断方法——下次换成数据库工具或者内部接口,排查顺序完全一样。
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度




被折叠的 条评论
为什么被折叠?



