LLM 工具调用与 MCP 机制

发布时间:2026/9/12 23:55:37

LLM 工具调用与 MCP 机制 主题LLM 如何被提供可用工具、工具调用协议、MCP 工具发现机制、以及多模型参数差异的抹平方式。一、工具调用整体流程工具调用Function Calling / Tool Use本质是一套「声明 → 决策 → 执行 → 回填」的循环在请求里声明「有哪些工具可用」(tools 定义)LLM 根据用户问题决定「是否调用 / 调用哪个 / 传什么参数」应用程序真正执行工具拿到结果把结果回填给 LLMLLM 生成最终自然语言回答关键认知LLM 本身不执行工具它只输出「我想调用某工具 参数」的结构化意图真正的执行由应用代码负责。二、如何提供可用工具工具声明主流做法在 API 请求中传入一个tools数组每个工具用 JSON Schema 描述。OpenAI 格式{model:gpt-4,messages:[],tools:[{type:function,function:{name:get_weather,description:查询指定城市的实时天气,parameters:{type:object,properties:{city:{type:string,description:城市名如 杭州},unit:{type:string,enum:[celsius,fahrenheit]}},required:[city]}}}],tool_choice:auto}Anthropic (Claude) 格式{model:claude-sonnet-4,messages:[],tools:[{name:get_weather,description:查询指定城市的实时天气,input_schema:{type:object,properties:{city:{type:string}},required:[city]}}]}关键点name工具唯一标识description最重要模型靠它判断何时调用要写清楚用途/触发条件parameters/input_schema用 JSON Schema 约束参数类型、枚举、必填项三、工具调用协议关键要素1. 调用控制字段 tool_choiceauto模型自行决定是否调用none禁止调用required/any强制必须调用某工具指定具体工具名强制调用该工具2. 模型返回工具调用意图OpenAI{role:assistant,tool_calls:[{id:call_abc123,type:function,function:{name:get_weather,arguments:{\city\: \杭州\}}}]}Anthropic{role:assistant,content:[{type:tool_use,id:toolu_abc123,name:get_weather,input:{city:杭州}}],stop_reason:tool_use}3. 回填执行结果协议核心执行完工具后必须用特定角色/类型把结果塞回对话历史并通过 id 关联OpenAI —— 用role: tooltool_call_id{role:tool,tool_call_id:call_abc123,content:{\temp\: 28, \desc\: \晴\}}Anthropic —— 用role: user里的tool_resulttool_use_id{role:user,content:[{type:tool_result,tool_use_id:toolu_abc123,content:{\temp\: 28, \desc\: \晴\}}]}4. 多轮循环回填后再次请求模型模型可能继续调用下一个工具多步/链式调用或生成最终回答stop_reason: end_turn/finish_reason: stop。5. 并行工具调用现代模型支持一次返回多个 tool_call。协议要求每个 tool_call 有独立 id回填时每个结果按 id 一一对应返回缺一不可应用可并行执行这些工具以提速6. 常见协议注意事项事项说明arguments 是字符串OpenAI 的 arguments 是 JSON 字符串需二次解析Anthropic 的 input 已是对象id 必须匹配回填结果 id 与调用 id 不匹配会报错完整对话历史每轮请求需带上包含 tool_call tool_result 的完整 messagesschema 越清晰越准description 和 enum 约束能显著降低幻觉/传错参错误也要回填工具执行失败时把错误信息作为 tool_result 返回让模型决定重试或换方案四、MCP支持哪些工具是怎么告诉 LLM 的核心结论LLM 本身并不直接知道有哪些 MCP它只认标准的 tools 定义。中间的 MCP Client宿主程序负责去各 MCP Server 发现工具再翻译成 LLM 的工具协议喂给它。整体链路MCP Server提供工具 ↑ MCP 协议 (tools/list, tools/call) MCP Client / Host如 Claude Desktop、IDE、Agent 框架 ↑ 把 MCP 工具翻译成 LLM 的 tools 定义 LLM API 请求 (tools: [...])第一步宿主如何知道支持哪些 MCP—— 靠配置{mcpServers:{filesystem:{command:npx,args:[-y,modelcontextprotocol/server-filesystem,/path]},github:{command:npx,args:[-y,modelcontextprotocol/server-github],env:{GITHUB_TOKEN:xxx}},my-remote:{url:https://example.com/mcp,transport:sse}}}宿主启动时按配置逐个连接本地用 stdio 启子进程远程用 SSE / HTTP。第二步MCP 协议的工具发现底层 JSON-RPC 2.0握手初始化{jsonrpc:2.0,id:1,method:initialize,params:{protocolVersion:2024-11-05,capabilities:{}}}列出工具 tools/list// Client → Server{jsonrpc:2.0,id:2,method:tools/list}// Server → Client{jsonrpc:2.0,id:2,result:{tools:[{name:read_file,description:读取指定路径的文件内容,inputSchema:{type:object,properties:{path:{type:string}},required:[path]}}]}}MCP Server 除了 tools还能暴露 resourcesresources/list和 promptsprompts/list发现机制类似。第三步翻译成 LLM 的 tools 定义宿主把所有 MCP Server 返回的工具聚合转换成 LLM 工具格式注入 API 请求。MCP 的 inputSchema 与 LLM 的 input_schema/parameters 几乎同构都是 JSON Schema。命名冲突处理多 Server 可能有同名工具宿主通常加前缀区分例如filesystem__read_file、github__create_issue。第四步调用回路1. LLM 返回 tool_use: { name: filesystem__read_file, input: {...} } 2. 宿主识别前缀路由到对应 MCP Server 3. 宿主向该 Server 发 tools/call 4. Server 执行返回 result 5. 宿主把 result 作为 tool_result 回填给 LLMtools/call 示例// Client → Server{jsonrpc:2.0,id:3,method:tools/call,params:{name:read_file,arguments:{path:/a.txt}}}// Server → Client{jsonrpc:2.0,id:3,result:{content:[{type:text,text:文件内容...}]}}动态更新工具列表变化通知{jsonrpc:2.0,method:notifications/tools/list_changed}宿主收到后重新 tools/list并在下一轮请求里更新给 LLM 的 tools 定义。完整图景配置文件 → 宿主知道「连哪些 MCP Server」 tools/list → 宿主知道「每个 Server 有哪些工具」 Schema 翻译聚合 → 拼成 LLM 的 tools 定义 API 请求 → 这一刻 LLM 才「知道」有哪些工具可用 tool_use → LLM 决定调用 tools/call → 宿主路由回对应 Server 执行 tool_result 回填 → LLM 生成最终回答一句话总结支持哪些 MCP 由宿主的配置决定宿主通过 MCP 的 tools/list 发现工具再翻译聚合成标准 tools 定义在每次 API 请求里告诉 LLM。LLM 全程只跟标准工具协议打交道对 MCP 本身无感知。五、不同模型参数格式差异的抹平核心结论差异主要在「客户端 / Agent 框架层」通过适配器Adapter / Provider 抽象抹平。抹平的是「协议格式」抹不平的是「模型能力和行为」。抹平发生在哪一层业务代码 ↓ 统一接口抹平层 ┌─────────────────────────────┐ │ Provider / Adapter 抽象层 │ │ OpenAIAdapter / ClaudeAdapter / GeminiAdapter │ └─────────────────────────────┘ ↓ 各自原生 API 格式 OpenAI API Claude API Gemini API两种常见实现方式Agent / SDK 框架内置适配LangChain、LlamaIndex、Vercel AI SDK、Spring AI 等定义统一的 Tool / Message 抽象内部为每个厂商写 adapter。网关 / 代理服务如 LiteLLM、OneAPI对外统一暴露 OpenAI 格式内部转译成各厂商格式。具体抹平了哪些差异以工具调用为例差异点OpenAIAnthropicGemini抹平方式工具定义键名function.parametersinput_schemafunctionDeclarations.parametersadapter 改字段名schema 本体同构调用意图tool_calls[]content[].tool_usefunctionCall统一解析成内部 ToolCall参数载荷argumentsJSON 字符串input对象args对象adapter 统一 parse 成对象结果回填role:“tool” tool_call_idrole:“user” 里 tool_result tool_use_idfunctionResponse统一封装成 ToolResult 按厂商拼回system 提示messages 里 role:“system”顶层独立 system 字段systemInstructionadapter 搬运到对应位置强制调用tool_choicetool_choicetoolConfig.mode统一枚举映射本质一套内部中间表示IR业务定义统一 Tool │ ▼ 内部 IR中立表示Message / Tool / ToolCall / ToolResult │ serialize按 provider 出站翻译 ▼ 各厂商原生请求格式 │ 调用 API ▼ 各厂商原生响应 │ parse入站翻译回 IR ▼ 内部 IR → 业务统一处理伪代码classToolCall:# 中立表示id:strname:strargs:dict# 统一是对象不管厂商用字符串还是对象classOpenAIAdapter:defto_request(self,tools,messages):...defparse_response(self,resp)-list[ToolCall]:# OpenAI 的 arguments 是字符串这里 json.loads 抹平成 dict...classClaudeAdapter:defto_request(self,tools,messages):...defparse_response(self,resp)-list[ToolCall]:...能抹平 vs 抹不平能抹平格式/协议层字段名、消息结构、system 位置参数是字符串还是对象工具定义、调用、回填的封装形式流式事件格式抹不平能力/行为层是否支持并行工具调用是否支持工具调用本身老模型/小模型可能不支持只能降级为提示词模拟 ReActJSON Schema 支持程度enum、嵌套对象、$ref 遵守度不同指令遵循度 / 幻觉率上下文窗口、token 计费、stop_reason 语义差异多模态、思维链thinking等特有能力对能力差异框架只能做「能力探测 降级策略」而非真正抹平。结论格式差异在 Agent / 框架 / 网关的适配层根据 provider 自动抹平业务代码通常无感。能力差异抹不平只能靠能力标记 降级 / 兼容策略处理。这也是很多框架有「provider」或「model capability」概念的原因——既做格式翻译也记录每个模型支持什么运行时决定走原生工具协议还是模拟方案。
延伸阅读

更多相关文章

2026/8/31 14:44:54

手把手教你用PDFTranslator处理多语言技术文档

做技术文档翻译的同学应该都遇到过这个问题:一份英文技术白皮书或API文档,翻译后表格错位、代码块丢失、图片和文字混成一团,最后还不如直接看原文。 今天分享一个实测好用的在线PDF翻译工具 PDFTranslator,它能比较好地保留原始排…

2026/9/3 12:05:47

嵌入式事件驱动架构:硬件事件管理器原理与实战应用

1. 事件驱动架构:嵌入式系统高效协同的基石在嵌入式开发领域,尤其是资源受限的微控制器应用中,如何高效、实时地处理来自传感器、通信接口和定时器的各种信号,一直是开发者面临的核心挑战。传统轮询方式不仅浪费宝贵的CPU周期&…

2026/9/4 3:33:52

MSPM0 ADC FIFO模式与DMA触发机制深度解析与实战配置

1. MSPM0 ADC FIFO模式与DMA触发机制深度解析在嵌入式系统开发中,尤其是涉及模拟信号采集的应用,ADC的性能和效率往往是决定系统实时性与可靠性的关键。传统的CPU轮询读取ADC结果的方式,不仅会占用大量处理器时间,在高采样率下还极…

2026/9/12 23:51:16

YOLO烟盒检测实战:小目标标注校验与训练调优全链路

简介:本资源是面向计算机视觉初学者与算法工程师的烟盒目标检测专用数据集,专为YOLO系列模型训练与验证设计,适用于工业质检、包装识别等实际场景。数据集共1934张高质量图像,已按标准划分训练集、验证集与测试集,并提…

2026/9/12 23:51:16

lucide-solid 使用指南:在 SolidJS 应用中集成 Lucide 图标库

lucide-solid 使用指南:在 SolidJS 应用中集成 Lucide 图标库 【免费下载链接】lucide Beautiful & consistent icon toolkit made by the community. Open-source project and a fork of Feather Icons. 项目地址: https://gitcode.com/GitHub_Trending/lu/l…

2026/9/12 2:05:33

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/12 3:55:12

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/12 10:09:03

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/12 0:04:17

MATLAB仿生优化框架:长鼻浣熊算法多策略融合实现

简介:本资源是一份面向智能优化算法研究者与MATLAB初学者的仿生智能算法实践代码包,聚焦于长鼻浣熊优化算法(COA)的多策略改进与性能验证。针对传统COA易陷局部最优、收敛精度不足等问题,作者融合Circle映射初始化提升…

2026/9/12 0:04:17

【JAVA毕设源码分享】基于 JavaWeb 的校园一卡通管理系统的设计与实现 基于 JavaWeb 的校园卡业务管理系统(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/12 0:04:17

【JAVA毕设源码分享】基于 Java 的图书馆借阅管理平台的搭建与实现 基于 Java 的图书馆综合管理系统(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/12 6:37:43

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码