尧图精选

大模型的执行者 Function Calling与MCP协议:从工具调用到TaoToken统一通道的落地实践

🕒 发布时间:2026/10/2 11:43:00 📁 来源:尧图网络
1. 从“只会聊天”到“动手做事”Function Calling 与 MCP 到底解决了什么很多人第一次用大模型 API 时都会有个疑问模型明明能写代码、能分析问题为什么让它“查一下今天北京天气”就只会回复“我无法获取实时信息”原因很简单纯文本模型本质上是个“语言接龙机器”它的输出空间被限制在 token 序列里没法主动去碰外部世界。Function Calling 就是给模型开的一扇门开发者提前把可用工具用 JSON Schema 描述清楚模型在对话中判断“这一步该调工具了”就吐出结构化的函数名和参数由你的后端去真正执行再把结果塞回对话让模型整合成自然语言。MCPModel Context Protocol则更进一步它想解决的是“工具多了以后怎么统一管理”的问题——把工具、资源、提示模板抽象成标准协议让不同客户端IDE、聊天应用、Agent 框架都能用同一套方式接入同一批服务端能力。我试过在同一个项目里既写 Function Calling 又接 MCP Server最直观的感受是Function Calling 像“临时叫个外卖”你每次都得自己定义菜单MCP 像“公司食堂”菜单是标准化的谁来都能点。两者不是替代关系而是层次不同——Function Calling 是模型侧的能力开关MCP 是工程侧的集成规范。对于想快速验证“模型能不能调工具”的开发者Function Calling 是最短路径对于要做多模型、多工具、长期维护的 Agent 系统MCP 的上下文标准化和会话状态管理会省掉大量胶水代码。这篇文章会从零跑通一条完整链路先写一个最小可用的 Function Calling 请求再把它包装成 MCP Server 能识别的工具定义最后用 TaoToken 的统一 Key 和 API 通道完成一次真实的工具调用验证。全程只依赖一个 API Key不需要在多个厂商控制台之间来回切换。适合已经会写 Python 或 Node.js、想搞明白“模型决策到外部执行”闭环到底怎么落地的人。2. 前置准备用 TaoToken 统一 Key 打通多模型调用通道在写任何工具调用代码之前得先解决“模型从哪来”的问题。Function Calling 和 MCP 都依赖一个能返回结构化 tool_calls 的模型接口而不同厂商的请求格式、鉴权方式、模型 ID 命名规则都不一样。如果每个模型都单独申请 Key、单独改 base_url光是环境变量就能把人搞晕。TaoToken 在这里的角色是统一通道你拿一个 Key通过同一个 API 入口就能调用多家模型请求格式保持 OpenAI 兼容Function Calling 的 tools 参数、tool_choice 参数都能正常透传。先注册并拿到 Key。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 完成账号注册后进入控制台。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在里面找到“API Keys”菜单新建一个 Key 并复制保存。注意 Key 只在创建时完整显示一次关掉页面就看不到了建议先贴到本地密码管理器里。接下来确认 API 入口。TaoToken 的 API 基础地址是 https://taotoken.net/api 所有 OpenAI 兼容的请求都往这个地址发。比如聊天补全的完整路径是 https://taotoken.net/api/v1/chat/completions。如果你用的是 openai Python SDK只需要把 base_url 改成 https://taotoken.net/api/v1api_key 填刚才拿到的 Key其余代码不用动。Node.js 的 openai 包同理baseURL 设为 https://taotoken.net/api/v1 即可。模型 ID 方面TaoToken 支持多家主流模型具体可用列表可以在控制台的模型页面查看或者直接调 https://taotoken.net/api/v1/models 拉取。常见的有 qwen-plus、qwen-max、claude 系列、gpt 系列等。Function Calling 对模型能力有要求建议选支持 tools 参数的模型qwen-plus 和 claude 系列实测都能稳定返回 tool_calls。如果你不确定某个模型是否支持可以先发一个带 tools 的请求看返回里有没有 tool_calls 字段。环境变量建议这样设置避免把 Key 硬编码进代码export TAOTOKEN_API_KEYsk-你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/api/v1Python 里读取import os from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], )到这里前置就完成了。你不需要单独去申请 qwen 的 DashScope Key、也不需要 claude 的 Anthropic Key一个 TaoToken Key 就能覆盖后面的所有调用。如果你后面要长期跑编码类 Agent可以关注 Coding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 里面有适合持续调用的套餐说明。验证模型是否通可以先用模型对话页面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 发一条简单消息确认 Key 有效。3. 可复制配置Function Calling 请求示例与 MCP Server 工具定义这一节直接给可运行的代码。先写一个最小的 Function Calling 示例定义一个查天气的工具让模型判断是否需要调用然后执行并回传结果。工具定义用 JSON Schema这是 Function Calling 的核心——模型靠 description 和 parameters 来决定“这个工具是干什么的、需要哪些参数”。import json import os from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], ) # 1. 定义工具查天气 tools [ { type: function, function: { name: get_weather, description: 查询指定城市的当前天气返回温度和天气状况, parameters: { type: object, properties: { city: { type: string, description: 城市名称例如 北京、上海, }, unit: { type: string, enum: [celsius, fahrenheit], description: 温度单位默认摄氏度, }, }, required: [city], }, }, } ] # 2. 模拟工具执行函数 def get_weather(city: str, unit: str celsius) - dict: # 真实场景这里调天气 API这里返回模拟数据 return {city: city, temperature: 26, unit: unit, condition: 晴} # 3. 第一轮请求让模型决定是否调工具 messages [{role: user, content: 北京现在天气怎么样}] response client.chat.completions.create( modelqwen-plus, messagesmessages, toolstools, tool_choiceauto, ) msg response.choices[0].message print(模型返回:, msg) # 4. 如果模型要求调工具执行并回传 if msg.tool_calls: messages.append(msg) for tool_call in msg.tool_calls: args json.loads(tool_call.function.arguments) result get_weather(**args) messages.append({ role: tool, tool_call_id: tool_call.id, content: json.dumps(result, ensure_asciiFalse), }) # 5. 第二轮请求模型整合工具结果生成自然语言 final client.chat.completions.create( modelqwen-plus, messagesmessages, toolstools, ) print(最终回复:, final.choices[0].message.content)这段代码跑通后你会看到模型先返回一个 tool_calls里面包含 get_weather 和 {city: 北京}然后第二轮返回“北京当前26度晴天”。这就是 Function Calling 的完整闭环模型决策 → 参数生成 → 外部执行 → 结果整合。接下来把同一个工具包装成 MCP Server 能识别的格式。MCP 的工具定义和 Function Calling 的 JSON Schema 高度相似但 MCP 要求服务端通过 stdio 或 SSE 暴露能力客户端通过协议握手发现工具。下面是一个最小 MCP Server 的配置片段用 Python 的 mcp 包实现工具定义和上面的 get_weather 保持一致{ mcpServers: { weather-server: { command: python, args: [/path/to/weather_mcp_server.py], env: { TAOTOKEN_API_KEY: sk-你的Key, TAOTOKEN_BASE_URL: https://taotoken.net/api/v1 } } } }对应的 weather_mcp_server.py 核心部分from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent import json app Server(weather-server) app.list_tools() async def list_tools(): return [ Tool( nameget_weather, description查询指定城市的当前天气, inputSchema{ type: object, properties: { city: {type: string, description: 城市名称}, unit: {type: string, enum: [celsius, fahrenheit]}, }, required: [city], }, ) ] app.call_tool() async def call_tool(name: str, arguments: dict): if name get_weather: city arguments[city] unit arguments.get(unit, celsius) result {city: city, temperature: 26, unit: unit, condition: 晴} return [TextContent(typetext, textjson.dumps(result, ensure_asciiFalse))] async def main(): async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options()) if __name__ __main__: import asyncio asyncio.run(main())这个 Server 启动后任何支持 MCP 的客户端比如 Claude Code、Cline、Cursor 的 MCP 插件都能通过上面的 JSON 配置发现 get_weather 工具。注意 env 里同样用的是 TaoToken 的 Key 和 Base URL这样 MCP Server 内部如果要调模型做二次决策也走统一通道。如果你用的是 Claude Code 这类工具配置路径通常在 ~/.claude/settings.json 或项目级的 .mcp.json。Claude Code 的接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有完整的 Base URL、Key、Model ID 三件套说明。Cline 的 MCP 配置类似在 Cline 设置里找到 MCP Servers粘贴上面的 JSON 即可。Codex 的 auth.json 则需要把 api_key 和 base_url 指向 TaoToken具体格式参考文档页。4. 验证请求用 TaoToken 通道跑通一次真实工具调用配置写完后必须验证否则你不知道是模型不支持 tools、还是 Key 没生效、还是 MCP Server 没启动。验证分两步先确认 TaoToken 通道能返回 tool_calls再确认 MCP Server 能被客户端发现并调用。第一步用 curl 直接打 TaoToken 的 chat completions 接口带 tools 参数。这样能排除 SDK 封装的干扰curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: qwen-plus, messages: [{role: user, content: 上海天气如何}], tools: [{ type: function, function: { name: get_weather, description: 查询城市天气, parameters: { type: object, properties: {city: {type: string}}, required: [city] } } }], tool_choice: auto }正常返回里应该能看到 choices[0].message.tool_calls结构类似{ id: call_xxx, type: function, function: { name: get_weather, arguments: {\city\: \上海\} } }如果返回的是普通 content 而没有 tool_calls说明模型没匹配到工具检查 description 是否够明确、tool_choice 是否为 auto。如果返回 401说明 Key 不对或没带 Authorization 头。如果返回 model not found说明模型 ID 写错了去控制台确认可用模型列表。第二步验证 MCP Server。以 Claude Code 为例把前面的 mcpServers JSON 写进配置后重启客户端然后在对话里输入“用 get_weather 查一下深圳天气”。如果配置正确Claude Code 会显示正在调用 MCP 工具并返回天气结果。如果客户端提示 “MCP server failed to start”检查 command 路径是否正确、python 是否在 PATH 里、依赖包 mcp 是否安装。如果提示 “no tools found”检查 list_tools 是否返回了工具、inputSchema 是否符合 JSON Schema 规范。第三步把 Function Calling 和 MCP 串起来验证。在 MCP Server 内部当 call_tool 被触发时可以再调一次 TaoToken 的模型接口做参数补全或结果润色。比如用户说“帮我查下天气然后决定穿什么”MCP Server 先调 get_weather再把天气结果和用户问题一起发给 qwen-plus让模型生成穿衣建议。这样一次请求里既有 MCP 的工具发现又有 Function Calling 的模型决策完整闭环就跑通了。实测下来qwen-plus 在 TaoToken 通道上返回 tool_calls 的稳定性不错参数 JSON 也基本合法。偶尔会出现 arguments 里多包一层转义的情况用 json.loads 之前先 strip 一下即可。Claude 系列对工具描述的理解更细适合参数复杂的场景。如果你要验证模型对话本身是否正常可以先去 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 发几条消息确认通道畅通。5. 常见报错排查401、local proxy failed、reading choices、OAuth这一节按真实遇到的报错来排。第一个高频错误是 401 Unauthorized。返回体通常是 {error: {message: Invalid API key}}。原因有三种Key 复制时带了空格、Key 被删除或过期、请求头没带 Bearer 前缀。排查方法用 echo $TAOTOKEN_API_KEY 确认环境变量非空用 curl -H Authorization: Bearer $TAOTOKEN_API_KEY https://taotoken.net/api/v1/models 测试 Key 是否有效。如果 models 接口能返回列表说明 Key 没问题问题在 chat 请求的 body 或模型 ID。第二个错误是 local proxy failed 或 connection refused。这通常出现在 MCP Server 启动时客户端尝试连接本地 stdio 或 SSE 端口失败。检查 MCP 配置里的 command 是否是可执行文件、args 路径是否存在、Python 环境是否装了 mcp 包。如果是 SSE 模式确认端口没被占用。Windows 下路径要用双反斜杠或正斜杠避免转义问题。第三个错误是 reading choices 相关比如 KeyError: choices 或 reading choices failed。这说明返回体里没有 choices 字段通常是接口返回了错误但代码没检查。打印完整 response 看 error 字段。常见原因是模型 ID 不支持 tools或者 tool_choice 设成了具体函数名但模型没匹配到。把 tool_choice 改成 auto 再试。第四个是 OAuth 相关报错比如 invalid_grant 或 token expired。如果你用的是 Claude Code 或 Codex 这类带 OAuth 流程的客户端注意它们可能默认走官方登录需要手动改成 API Key 模式。Claude Code 的配置里要把 apiKey 和 baseURL 显式指向 TaoToken参考 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里的 ClaudeCodeAnthropic 接入说明。Codex 的 auth.json 里要填 OPENAI_API_KEY 和 OPENAI_BASE_URLbase_url 设为 https://taotoken.net/api/v1。还有一个容易忽略的点MCP 工具定义里的 inputSchema 如果 required 字段写错客户端可能能发现工具但调用时报参数校验失败。确保 required 数组里的字段名和 properties 里的 key 完全一致。另外Function Calling 的 tools 数组里每个 function 的 name 不能有空格或特殊字符用下划线连接。如果遇到 429 rate limit说明短时间内请求过多TaoToken 通道一般有并发限制降低频率或换模型即可。如果遇到 500 或 502先重试一次持续失败就去控制台看服务状态。排障时建议把请求体和响应体都打到日志里尤其是 tool_calls 的 arguments 字段很多时候是 JSON 解析失败而不是模型没返回。6. 从验证到长期使用把统一通道接进你的编码工作流跑通一次工具调用只是起点。真正要长期用得把 TaoToken 的统一 Key 和 Base URL 固化到你的开发环境里。如果你主要用 Claude Code 做编码配置路径在 ~/.claude/settings.json把 env 里的 ANTHROPIC_BASE_URL 指向 https://taotoken.net/api ANTHROPIC_API_KEY 填 TaoToken Key模型 ID 按文档填。这样 Claude Code 的所有请求都走统一通道不用再单独维护 Anthropic 的 Key。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有 ClaudeCodeAnthropic 的完整字段说明。如果你用 Cline 或 Continue 这类 VS Code 插件在设置里找 OpenAI Compatible 或 Anthropic CompatibleBase URL 填 https://taotoken.net/api/v1API Key 填 TaoToken KeyModel ID 填 qwen-plus 或 claude 系列。Cline 的 MCP 配置直接粘贴第 3 节的 JSON把 env 里的 Key 换成你的。这样 Cline 既能调模型又能通过 MCP 调本地工具两条链路共用一个 Key。对于要跑批量任务或 Agent 的场景建议把 Function Calling 的 tools 定义抽成独立的 JSON 文件MCP Server 的 list_tools 直接读同一份定义避免两处维护不一致。工具执行函数也抽成独立模块Function Calling 的本地执行和 MCP 的 call_tool 都调同一个函数。这样你新增一个工具时只改一处两条链路同时生效。长期使用还要关注 Key 的额度。TaoToken 控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 里能看到用量和余额。如果要做持续编码或 Agent 任务Coding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 有适合高频调用的方案。API Keys 管理页 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 可以创建多个 Key 做环境隔离比如开发用一个、生产用一个方便排查和轮换。最后提醒一个实操细节MCP Server 的 stdio 模式在客户端重启后会重新拉起进程如果你在 Server 里维护了内存状态比如缓存重启会丢。需要持久化的数据写到本地文件或数据库。另外Function Calling 的 tool_calls 可能一次返回多个代码里要用 for 循环处理不要只取第一个。工具执行失败时把错误信息作为 tool 角色的 content 回传模型能根据错误调整参数重试这比直接抛异常给用户友好得多。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →