news 2026/10/15 22:13:54

第2篇:Tools 与 MCP —— 让 LLM 从“只会说“变成“能做事“:TaoToken 统一 Key 打通 Function Calling 与 JSON-RPC 实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第2篇:Tools 与 MCP —— 让 LLM 从“只会说“变成“能做事“:TaoToken 统一 Key 打通 Function Calling 与 JSON-RPC 实战

1. 从“只会说”到“能做事”:LLM 工具调用的真实卡点

LLM 本身只能做一件事:文字进、文字出。你问它“北京到上海今天有哪些航班”,它要么编一个看起来很像的答案,要么告诉你“我无法获取实时信息”。这不是模型笨,是它天生没有手和脚——它不能查数据库、不能读文件、不能发 HTTP 请求。

Tools(工具)就是给 LLM 装上的手脚。但装手脚这件事,在 MCP 出现之前和之后,是两套完全不同的思路。我见过太多人卡在同一个地方:本地写好了 Function Calling 的 schema,换一个客户端(比如从 Cline 换到 Claude Code)就得把适配代码重写一遍;工具从 5 个加到 20 个,模型开始选错工具,调用链直接断掉。

这篇要解决的就是这条落地路径:用 Tools 定义能力,用 Function Calling 触发调用,用 MCP 的 JSON-RPC 通信把工具从“模型私有字段”变成“系统协议”,最后用 TaoToken 的统一 Key 和 API 通道把多模型调用集中管起来。适合谁?正在把 LLM 从聊天框往 Agent 方向推、但被工具集成复杂度卡住的开发者。

核心检索词先摆出来:LLM Function Calling 与 MCP JSON-RPC 工具调用实战。下面每一步都给可复制的 schema、配置片段和验证命令,你跟着做就能确认模型是否真的发起了工具调用。

先说清楚 Tools 的本质。Tools 是给 LLM 用的外接能力单元,常见的有 Search、Browser、File、Code Run、Database。关键点是:LLM 不直接执行工具。它读完工具描述(JSON Schema)后,输出一个标准 JSON,告诉程序“该调用哪个函数、传什么参数”。真正干活的是你的程序。

一个典型调用过程长这样:

{"function": "search", "args": {"query": "北京到上海航班"}}

程序收到这个 JSON,执行 search 函数,把结果返回给 LLM,LLM 看到结果后再推理下一步,输出下一个 JSON。整个循环里,模型只负责“决策”,不负责“执行”。

写 Tool Schema 的关键是description。LLM 通过阅读描述来推理该用哪个工具,所以 description 要写场景而不是功能。不要写“搜索互联网”,而要写“当用户需要查找最新信息、实时数据时使用”。这个细节直接决定模型选工具的准确率。

纯 Function Calling 的局限也很明显:它是各家大模型厂商 API 里的私有字段——OpenAI 叫tools,Anthropic 叫tool_use,Gemini 叫function_declarations。它跟模型强绑定。如果你有 N 个客户端和 M 个工具,需要写 N×M 份适配代码。3 个客户端 × 5 个工具 = 15 份适配;10 个客户端 × 50 个工具 = 500 份适配。乘法增长,规模一大就失控。

MCP(Model Context Protocol)的核心贡献不是“更好的 Function Calling”,而是把工具调用从模型能力升维成系统协议。它基于 JSON-RPC 2.0,定义了标准握手、能力协商、Client/Server 分离。写一份 Server,任意 Client 都能复用,复杂度从 N×M 降到 N+M。还是 10 客户端 × 50 工具,500 份变成 60 份。

MCP 的工作结构是这样的:

MCP Host(AI 应用) └─ MCP Client(协议转换) └─ MCP Server 1(搜索) └─ MCP Server 2(文件操作) └─ MCP Server 3(数据库)

一次典型的 MCP 调用:initialize(握手,确认双方能力)→tools/list(Client 问:你能提供什么工具?)→tools/call(Client 说:调用 search,参数是...)→ 结果返回(JSON-RPC 格式)。这跟 HTTP 的工作方式如出一辙——握手建立连接、列出资源、请求资源、返回响应。

这里有个反直觉的结论:MCP 不是 Function Calling 的升级版,它做了相反的事——把工具调用从模型 API 特有的魔法行为,降级为普通的网络协议请求。任何语言、任何框架、任何模型,只要实现了 JSON-RPC 2.0,就能接入 MCP。这是它最核心的价值。

2. TaoToken 前置:统一 Key 与 API 通道怎么准备

在写 Tools schema 和 MCP 配置之前,先把调用通道准备好。为什么需要这一步?因为 Function Calling 和 MCP 的调用链里,模型请求是高频且多模型的——你可能用 Claude 做工具决策,用另一个模型做结果总结。如果每个模型都单独配 Key、单独记 Base URL,排障时会疯掉。

TaoToken 在这里的角色是统一 Key 和 API 通道:一个 Key 管多模型调用,Base URL 统一,省去在多个客户端里反复填不同厂商地址的麻烦。官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api (这个不加 UTM)。

你需要准备三件套,这三件套在后面每个客户端配置里都会出现:

配置项值说明
Base URLhttps://taotoken.net/api所有请求的统一入口
API Key在控制台生成形如sk-...,只显示一次
Model ID按需选择如claude-sonnet-4-5、gpt-4o等

生成 Key 的路径:进入控制台 → API Keys → 新建。这里有个坑:Key 只在创建时完整显示一次,关掉页面就看不到了,所以生成后立刻复制到安全的地方。如果你要长期跑编码类 Agent,建议直接看 Coding Plan,它比按量计费更适合高频工具调用场景。

模型对话入口可以用来快速验证 Key 是否可用,不用写代码就能发一条测试消息。接入文档里有各客户端的详细配置说明,遇到不确定的字段名先去那里对一遍。

为什么强调“统一通道”?因为 MCP 的调用链里,模型请求和工具执行是分开的。模型请求走 TaoToken 的 API,工具执行走你本地的 MCP Server。如果模型请求这一层用了多个厂商的 Key,一旦工具调用失败,你很难判断是模型没返回正确的 tool_use,还是 Key 权限问题,还是 Base URL 写错了。统一通道把变量减少到一个,排障效率完全不一样。

还有一点:Function Calling 对模型的指令遵循能力有要求。不是所有模型都能稳定输出符合 schema 的 JSON。选模型时优先选工具调用能力强的,别为了省钱选一个连 JSON 格式都守不住的模型,后面调工具选择准确率会让你怀疑人生。

准备好这三件套后,先别急着写 MCP Server。先用一个最小的 Function Calling 例子验证通道是通的——这是下一节的内容。

3. 可复制配置:Tools Schema 与 MCP Server 片段

这一节给可直接复制的配置。先给 Function Calling 的 Tools schema,再给 MCP Server 的配置片段,最后给客户端接入的三件套写法。

3.1 Tools Schema:一个搜索工具的完整定义

下面是一个符合 OpenAItools字段格式的 schema,你可以直接放进请求体:

{ "tools": [ { "type": "function", "function": { "name": "search_flights", "description": "当用户需要查询两个城市之间的实时航班信息、起飞时间、价格时使用。不适用于历史航班或航班政策咨询。", "parameters": { "type": "object", "properties": { "from_city": { "type": "string", "description": "出发城市,例如:北京" }, "to_city": { "type": "string", "description": "到达城市,例如:上海" }, "date": { "type": "string", "description": "出发日期,格式 YYYY-MM-DD" } }, "required": ["from_city", "to_city", "date"] } } } ] }

注意description的写法:写的是“当用户需要查询……时使用”,而不是“搜索航班”。这个差别在模型选工具时非常关键。required字段也要写全,否则模型可能漏传参数。

3.2 MCP Server 配置片段

MCP Server 的配置通常放在客户端的配置文件里。以常见的mcp.json或客户端 settings 为例,一个 stdio 类型的 MCP Server 配置长这样:

{ "mcpServers": { "flight-search": { "command": "node", "args": ["/path/to/your/mcp-server/index.js"], "env": { "API_BASE": "https://taotoken.net/api", "API_KEY": "sk-你的Key" } } } }

如果你用的是支持 TOML 的客户端,等价写法是:

[mcp_servers.flight-search] command = "node" args = ["/path/to/your/mcp-server/index.js"] [mcp_servers.flight-search.env] API_BASE = "https://taotoken.net/api" API_KEY = "sk-你的Key"

这里command和args指向你的 MCP Server 启动脚本。env里放的是 Server 内部调用模型时用的通道信息。注意:MCP Server 本身不一定要调模型,但如果你的 Server 内部有二次推理逻辑,就需要这三件套。

3.3 客户端接入三件套

无论你用 Claude Code、Cline 还是其他支持 MCP 的客户端,接入时都要填全三件套。以 Claude Code 的配置为例(settings 文件):

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的Key", "ANTHROPIC_MODEL": "claude-sonnet-4-5" } }

Cline 的 MCP 配置里,Base URL、Key、Model ID 三个字段一个都不能少。Codex 的auth.json同理:

{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的Key", "model": "gpt-4o" }

三件套缺一不可:Base URL 决定请求发到哪,Key 决定有没有权限,Model ID 决定用哪个模型做工具决策。少任何一个,调用链都会在第一步就断掉。

配置写完后,先别急着跑完整调用链。下一节用一条最小请求验证通道和工具调用是否正常。

4. 验证请求:一次完整调用链的成功结果

这一节用 curl 发一条带 tools 的请求,确认模型能正确返回 tool_use。这是整条链路里最关键的验证点——如果模型不返回工具调用,后面 MCP 配得再好也没用。

4.1 发一条带 Tools 的请求

curl https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-你的Key" \ -d '{ "model": "claude-sonnet-4-5", "messages": [ {"role": "user", "content": "帮我查一下明天北京到上海的航班"} ], "tools": [ { "type": "function", "function": { "name": "search_flights", "description": "当用户需要查询两个城市之间的实时航班信息时使用", "parameters": { "type": "object", "properties": { "from_city": {"type": "string"}, "to_city": {"type": "string"}, "date": {"type": "string"} }, "required": ["from_city", "to_city", "date"] } } } ] }'

4.2 期望的成功结果

如果通道和 schema 都正确,返回体里会出现tool_calls字段,类似:

{ "choices": [ { "message": { "role": "assistant", "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "search_flights", "arguments": "{\"from_city\":\"北京\",\"to_city\":\"上海\",\"date\":\"2025-01-16\"}" } } ] } } ] }

看到tool_calls就说明模型正确发起了工具调用。注意arguments是一个 JSON 字符串,需要二次解析。日期是模型根据“明天”推算的,实际使用时建议在 prompt 里给明确的日期,减少模型推算错误。

4.3 把工具结果回传给模型

拿到 tool_calls 后,你的程序执行 search_flights,然后把结果作为tool角色消息回传:

{ "role": "tool", "tool_call_id": "call_abc123", "content": "{\"flights\":[{\"flight\":\"MU5101\",\"depart\":\"08:00\",\"price\":1200}]}" }

再发一次请求,模型会基于工具结果生成自然语言回复。到这里,一次完整的 Function Calling 调用链就跑通了。

4.4 MCP 侧的验证

MCP 的验证方式不同,它走 JSON-RPC。你可以手动发一条tools/list请求确认 Server 正常:

{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}

正常返回会列出 Server 暴露的所有工具。再发tools/call:

{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_flights","arguments":{"from_city":"北京","to_city":"上海","date":"2025-01-16"}}}

返回结果里会有content数组。如果这两步都通,说明 MCP Server 的 JSON-RPC 通信正常,客户端可以正常发现和调用工具。

实测下来,最容易出问题的不是 schema 本身,而是通道配置和模型选择。下一节把常见报错逐个拆开。

5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth

这一节对照真实报错给排查路径。每个报错都对应调用链上的一个具体环节。

5.1 401 Unauthorized

最常见。原因通常是 Key 没填、填错、或者 Base URL 和 Key 不匹配。检查顺序:先确认Authorization: Bearer sk-...里的 Key 完整;再确认 Base URL 是https://taotoken.net/api,没有多余斜杠或路径;最后去控制台确认这个 Key 还有效、没被删除。

如果是在客户端里报 401,检查配置文件里的字段名是否正确。比如 Claude Code 用的是ANTHROPIC_API_KEY,Cline 可能用apiKey,字段名写错等于没填。

5.2 local proxy failed

这个报错通常出现在客户端尝试连接本地 MCP Server 时。原因可能是:MCP Server 的command路径写错、args指向的文件不存在、或者 Server 启动就崩了。排查方法:先在终端手动执行command + args那串命令,看 Server 能不能正常启动。如果手动启动报错,先修 Server;如果手动能启动但客户端报错,检查客户端的 MCP 配置路径是不是绝对路径。

还有一种情况是端口冲突。如果 MCP Server 用的是 HTTP/SSE 模式而不是 stdio,端口被占用也会报这个错。换一个端口再试。

5.3 reading choices 相关报错

这个报错说明请求发出去了,但返回体里没有choices字段。常见原因:模型名写错(比如写了一个不存在的 Model ID),或者请求体格式不对(比如messages字段缺失)。检查 Model ID 是否在 TaoToken 支持的模型列表里,检查请求体 JSON 是否合法。

如果返回体里有error字段,先看 error message。很多“reading choices”的根因其实是上游返回了错误,客户端没处理好就直接去读 choices 了。

5.4 OAuth 相关报错

如果你用的是 Claude Code 这类带 OAuth 流程的客户端,可能会遇到 OAuth 报错。这类报错通常和 Base URL 配置有关——客户端可能默认走官方 OAuth 流程,而不是走你配置的 API 通道。检查配置里是否同时设置了ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY,并且确认客户端版本支持自定义 Base URL。

如果客户端强制走 OAuth,考虑换用支持 API Key 直连的客户端,或者查接入文档里对应客户端的配置方式。

5.5 工具调用返回空

模型返回了tool_calls但arguments是空对象,或者模型直接返回文本而没有调用工具。原因通常是description写得太模糊,模型判断“不需要调用工具”。把 description 改成明确的场景描述,比如“当用户询问实时航班时使用”,再试一次。

另一个原因是模型本身工具调用能力弱。换一个工具调用能力强的 Model ID,对比结果。

排障时记住一个原则:先验证通道,再验证 schema,最后验证模型。通道不通,后面都是白搭。

6. 把统一 Key 用起来:从验证到长期编码

走到这里,你已经有了可复制的 Tools schema、MCP Server 配置片段、三件套写法,也知道了常见报错怎么排查。接下来是怎么把这套东西用起来。

如果你只是偶尔验证工具调用,用模型对话入口发几条测试消息就够了,不用配客户端。如果你要长期跑编码类 Agent,或者工具数量会持续增加,建议看 Coding Plan——高频工具调用场景下,按量计费的波动会很大,包月方案更可控。

接入文档里有各客户端的完整配置示例,遇到字段名不确定的时候先去那里对一遍,比在报错里猜要快得多。API Keys 页面用来管理你的 Key,建议给不同客户端生成不同的 Key,这样某个客户端出问题时能快速定位是哪个 Key 的配置有问题。

最后给一个实用技巧:MCP Server 的tools/list返回的工具数量不要超过 15 个。前面提过,工具从 10 个扩展到 200 个时,模型选择准确率会从 95% 跌到 41%。如果你的 Server 暴露了太多工具,考虑用 Skill 把多个工具的调用顺序打包成一个命名概念,让模型选 Skill 而不是从几十个工具里挑。

工具调用这件事,配通一次之后就是复制粘贴。真正花时间的是排障——而排障效率取决于你的通道是否统一。统一 Key 和 Base URL 之后,变量少了,问题定位就快了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 22:10:05

MySQL慢查询优化实战:从执行计划到索引设计

1. 为什么慢查询迟迟不改善:先看清执行计划接手这套订单系统的时候,线上已经积累了几十条慢查询记录,每天早上九点高峰期一到,数据库CPU直接飙到80%以上,首页订单列表接口的响应时间从原来的300毫秒一路涨到了4秒多。几…

作者头像 李华
网站建设 2026/10/15 22:09:01

车载以太网实战指南:从100Base-T1选型到gPTP时间同步的避坑手册

简介:《Automotive Ethernet: The Definitive Guide》是面向汽车电子工程师、车载网络研发人员及高校相关专业学生的专业电子书,系统讲解车载以太网这一现代汽车通信核心技术。全书共42章、1628页,从工作原理、标准规范、网络架构、物理层设计…

作者头像 李华
网站建设 2026/10/15 22:08:20

STM32N6 FSBL启动流程详解:从BootROM到应用跳转的避坑指南

简介:这份PDF文档面向从事ARM架构MCU开发的程序员与嵌入式技术爱好者,聚焦STM32N6这颗ST首款带NPU的MCU,系统讲解其启动机制与FSBL(First Stage Boot Loader)的基本流程,帮助开发者理解片内BootROM、外部Fl…

作者头像 李华
网站建设 2026/10/15 22:08:18

容器化部署性能优化实战:从镜像瘦身到资源配额与网络调优

做容器化部署的同学,八成都会遇到这个尴尬时刻:明明代码没改,部署方式从虚拟机换成了容器,性能反而变差了。接口响应时间翻倍,CPU时不时飙满,内存动不动就被杀,重启后没一会儿又被打回原形。我们…

作者头像 李华
网站建设 2026/10/15 22:07:57

POJ基础题刷题指南:从A+B到高精度与DP的避坑实战

简介:这份资源面向正在刷北大POJ、准备ACM/ICPC入门或巩固算法基础的编程学习者,收录了从1000到3673区间内大量经典题目的可运行答案,覆盖模拟、枚举、数论、动态规划、图论、贪心、搜索等常见考点,适合作为日常练习对照与思路参考…

作者头像 李华