8. 为什么有些特定的推理模型不支持 MCP 协议?
我理解根本原因是两者的生成范式有冲突。
推理模型在给出答案之前,会先跑一段完整的「思维链」,这个 thinking 过程是一次性连续生成的,不能中途打断。但工具调用天然是多轮交互:模型输出调用请求、暂停等工具执行、拿到结果再继续生成,这两种模式没法兼容。你没法在思考链跑到一半的时候暂停去等工具结果,否则之前的推理上下文全断了。
而 MCP 底层就是靠 Function Calling 驱动的,推理模型连 Function Calling 都支持不好,MCP 自然也用不了。
当然这个问题不是无解的,后来 o3 和 Claude Extended Thinking 都找到了折中方案,比如让工具调用发生在思考阶段结束之后,保证思考过程还是一次性完整生成的。
先弄清楚推理模型是什么
普通模型的工作方式很直接:问题进来,答案出去,收到输入就开始生成 token,一路生成到结束。
推理模型(Reasoning Model)不一样。它在给出最终答案之前,会先生成一大段「内部思考」(thinking tokens),在思考里自言自语地推演、验证、反驳,甚至推翻自己前面的结论重来,直到把问题想清楚了,再输出面向用户的最终答案。代表模型有 OpenAI o1/o3 系列、DeepSeek-R1、Claude 的扩展思考(Extended Thinking)模式。
这套「先思考再回答」的机制,正是推理模型在复杂推理、数学、代码问题上比普通模型强的根本原因。但也正是这个机制,和工具调用产生了根本冲突。
工具调用的本质是「中途暂停」
要理解冲突,先要搞清楚工具调用的完整流程。
工具调用不是一次性生成完成的,它天然是多轮交互:第一步,模型生成调用请求,表达「我要查北京天气,调get_weather工具,参数是 city=北京」;第二步,停下来等宿主程序去执行这个工具;第三步,拿到工具返回的结果;第四步,继续生成,把工具结果纳入后续推理,最终给出答案。
整个流程的核心是第二步,模型生成到一半,强制暂停,等外部执行完毕,再恢复生成。对普通模型来说,这没有问题,因为它的状态很轻量,随时可以截断再重新启动。
直觉类比,写推理过程中途被打断
推理模型遇到这个「中途暂停」会是什么感觉?
想象你正在心无旁骛地写一篇复杂的推理论文,脑子里已经建立了一整套逻辑框架,各个论点之间的关系都串起来了,正处于思维最活跃的时刻。
突然电话来了,你放下笔去接了 20 分钟电话,再回来坐下,很多细节想不起来了,之前好不容易建立的推理脉络断了,只能重新梳理。
推理模型的思考链就是这种东西。它是一个依赖完整上下文的连续生成过程,每一步推理都建立在前面所有推理内容的基础上,整条链是一个有机整体。
中途强行打断,之前建立的推理状态会断掉,模型没办法从中间接着想,只能整个重来。
「那保存状态再恢复不就行了?」
有人可能会问:那暂停时把状态保存起来,工具执行完再恢复,不就解决了?
听起来好像可行,但实际代价很大。你可以把模型推理时的中间状态想象成一本「思考草稿本」,上面记满了到目前为止每一步推理积累下来的脉络(技术上叫 KV Cache,是模型缓存注意力计算结果的结构,体积非常庞大)。一旦暂停,这本草稿本就得原封不动占着一块 GPU 显存,工具执行要几秒、几十秒,这块显存就一直被占着不能给别的请求用。工具执行完再接着想,显存占用翻倍、吞吐量直接腰斩,整体延迟也大幅上升。对一个需要同时服务成千上万请求的在线推理系统来说,这个代价是完全承受不了的。
更难解决的是一致性问题。思考过程中途接入工具结果,等于在模型「想到一半」时改变了输入。模型之前的思路是基于「我还不知道工具结果」建立的,突然工具结果来了,模型需要重新校准,之前的推理链和新来的工具结果可能是矛盾的,怎么融合?这个「思考状态一致性」的问题没有简单的解法。
训练目标上的冲突
除了生成范式,训练层面也有根本性的冲突。
推理模型的训练核心是:用强化学习(RL,通过奖励反馈让模型学会更好的行为)大量奖励「思考链完整且结论正确」的输出。模型接受了大量这类训练之后,会越来越倾向于「一直想、想到底」,把推理过程跑完整,这是它推理能力强的根本来源。
而 Function Calling 的训练恰好相反,需要模型学会在合适时机打断自己,从推理状态切换出来,输出一段结构化的 JSON 调用请求。这个行为和「持续深入推理」是相反的,要同时学好这两件事,训练数据的分布就要两边都兼顾。
如果强行把两种训练数据混在一起喂,实际会看到什么现象?常见的失败模式有三种:一是模型在思考到一半突然跳出来输出一段奇怪的 JSON,结果 JSON 格式还错了,两边都没干好;二是模型彻底偏向一边,要么思考链缩水变浅(变成普通模型),要么干脆不会输出工具调用;三是融合处的推理断裂,工具结果回来之后模型的后续推理和之前的思考链对不上,答非所问。所以早期推理模型宁可先放弃工具调用,也要先把推理能力做扎实。
早期推理模型的真实情况
OpenAI o1-preview 是最典型的案例,2024 年 9 月发布时明确不支持 Function Calling,官方文档直接标注了这个限制。不过要注意区分版本:o1-preview 是早期预览版,确实不支持工具调用;但 2024 年 12 月发布的正式版 o1 已经加上了 Function Calling 支持,说明 OpenAI 在后续版本中找到了兼容方案。DeepSeek-R1 早期版本也是类似情况,推理能力很强,但工具调用支持极弱甚至没有。
这些早期限制不是懒得做,而是上面这些结构性冲突导致的工程取舍:先把推理能力做扎实,再想办法处理工具调用兼容的问题。
后来是怎么解决的,折中方案
后续版本找到的工程解法是:让工具调用发生在思考阶段结束之后。
具体做法是:模型先把整个推理链完整跑完,进入「输出最终答案」阶段时,才触发 Function Calling 流程。这样思考过程仍然是一次性完整生成的,完全不被打断,推理质量得以保住。
代价是:思考阶段完全感知不到工具结果,模型只能基于自己的已有知识来推理,工具数据只有在「答案生成阶段」才能引入。
对于那种「需要先查到某个数据,再基于这个数据做复杂推理」的任务,这个方案是有局限的,模型没办法带着工具结果去深度推理。但对大多数场景来说,先想清楚再调工具已经够用。
o3 和 Claude Extended Thinking 走的都是这条路,所以它们现在已经支持工具调用了。而且 Claude 还进一步推出了 interleaved thinking(交错思考)模式,允许模型在多次工具调用之间穿插思考,而不是只能在所有思考结束后才调用工具,这在一定程度上缓解了「思考阶段感知不到工具结果」的局限。
但你要知道这个内在限制的本质仍然存在,各家的解法都是在「保证推理质量」和「支持工具调用」之间做权衡。
为什么不支持 Function Calling 就不支持 MCP?
这个传导关系很直接。
MCP 协议在底层完全依赖 Function Calling。整个调用链是这样的:MCP Client 先连上 Server,拉取工具定义,然后把这些定义转换成模型原生的 Function Calling 格式传给模型。接下来等模型输出tool_calls,Client 再把调用请求路由到对应的 Server 执行,最后把执行结果喂回对话。
这个「工具定义 -> Function Calling 格式转换」就是 MCP 的翻译层,是整个链路的关键环节。
那如果推理模型不支持 Function Calling 呢?这个翻译层就完全失效了。工具信息没办法让模型理解,调用请求也无法被模型生成,整条链路从中间直接断掉了。
所以「推理模型不支持 Function Calling -> 不支持 MCP」是一个很自然的传导关系,不是 MCP 本身有什么问题,是底层能力缺失导致的连锁反应。
面试回答这道题,必须讲清楚三个层次:第一,推理模型的思考链是一次性连续生成的,不能中途打断;第二,工具调用天然需要在生成过程中暂停等待外部执行,这和连续生成的范式冲突;第三,MCP 底层依赖 Function Calling,推理模型连 Function Calling 都支持不好,MCP 自然也用不了,这是一个传导关系。
如果能再补充后续的解决方案就更加分了:o3 和 Claude Extended Thinking 采用的折中方案是让工具调用发生在思考阶段结束之后,保证思考过程仍然完整连续。Claude 还进一步推出了 interleaved thinking 模式,允许在多次工具调用之间穿插思考,部分缓解了这个局限。
同时也要点出折中方案的本质权衡:各家的解法都是在「保证推理质量」和「支持工具调用」之间找平衡点。
9. Skill 是什么?
Agent Skill 是把「指令、脚本、模板」一体化打包成可复用能力包的机制,关键在于三件事:Agent 能自动发现它、按需加载它、在需要时调用里面的脚本和资源。它不只是「存 prompt」,而是一份 Agent 能自己翻阅的「操作手册 + 工具箱」。每个 Skill 是一个文件夹,里面有一份 SKILL.md 指令文件,还可以带上脚本、模板、参考文档这些资源。
它和普通 prompt 最大的区别是:Skill 能被 Agent 自动发现和按需加载,不用你每次手动输入;和 MCP 工具的区别是:MCP 给 Agent 提供外部工具和数据的访问能力,而 Skill 教 Agent 拿到这些工具和数据之后该怎么用。
Anthropic 在 2025 年 10 月推出了 Agent Skills,同年 12 月把规范作为开放标准发布出来,允许其他 Agent 平台按照这套格式来兼容 Skills 生态。
为什么需要 Skill?从「重复贴 prompt」的痛点说起
你一定遇到过这种情况:每次让 AI 帮你做代码审查,你都要贴一大段指令,告诉它「检查这几类问题、用这种格式输出、重点关注安全漏洞」。第一次贴的时候还好,第二次、第三次你就开始烦了,每次新对话都要从头贴一遍,漏掉某个细节就会导致输出质量不稳定。
这还只是一个人的情况。如果是团队协作呢?十个人做代码审查,每个人贴的 prompt 都不一样,有的人关注安全,有的人关注性能,审查标准完全没法统一。
你可能想到把 prompt 写到一个共享文档里让大家复制,但这本质上还是靠人工去维护和执行,版本一多就容易乱,更新了文档但有人还在用旧版的 prompt,质量把控根本做不到。
Skill 要解决的就是这个问题:把那些你反复在用的指令、流程、模板,打包成一个标准化的模块,Agent 自己知道什么时候该用它、怎么用它,不再依赖你手动复制粘贴。
Skill 的结构长什么样
一个 Skill 说白了就是一个文件夹,里面最核心的是一份叫 SKILL.md 的文件,再加上一些可选的辅助资源。结构很直观:
code-review/ # Skill 文件夹,名字就是这个 Skill 的标识 ├── SKILL.md # 核心指令文件(必须有) ├── scripts/ # 可选:可执行的脚本 │ └── check_security.py # 比如一个安全检查脚本 ├── references/ # 可选:参考文档 │ └── review_standards.md # 比如团队的审查标准文档 └── assets/ # 可选:模板、资源文件 └── report_template.md # 比如审查报告的输出模板SKILL.md 的内容分两部分。顶部是一段 YAML 格式的元数据,叫 frontmatter,声明这个 Skill 的名字和一句话描述;下面是正文,用 Markdown 写具体的指令和步骤。来看一个实际的例子:
--- name: code-review description: "对代码进行全面审查,检查 bug、安全漏洞和性能问题,输出结构化审查报告" --- # 代码审查 Skill ## 指令 ### 第一步:理解代码上下文 阅读提交的代码,理解它的功能和所属模块,确认修改范围。 ### 第二步:逐项检查 按以下维度逐一检查: 1. 功能正确性:逻辑是否有 bug,边界条件是否处理了 2. 安全性:是否有注入、XSS、权限绕过等漏洞 3. 性能:是否有 N+1 查询、不必要的循环、内存泄漏风险 4. 可读性:命名是否清晰,关键逻辑是否有注释 ### 第三步:输出报告 使用 assets/report_template.md 的模板格式,输出结构化的审查报告。你会发现,这和普通 prompt 的区别就很明显了。普通 prompt 只是一段文字,用完就没了;而 Skill 是一个完整的文件夹,里面的指令、脚本、模板可以持续维护、版本管理,团队里所有人用的都是同一份。
渐进式加载:Skill 最聪明的设计
Skill 最让人眼前一亮的设计,不是「能打包」这件事本身,而是它的加载方式。
你可能会想,既然 Skill 可以打包那么多东西,Agent 启动的时候是不是要把所有 Skill 的内容全部读进来?想象一下这个账:假设你有 20 个 Skill,每个 Skill 的指令加上参考文档平均 2000 token,全部加载就是 4 万 token 打底。现在市面上常见的模型上下文窗口是 20 万 token,光 Skill 就吃掉了五分之一,剩下的要分给系统提示、对话历史、用户文件,留给模型真正思考的空间就很紧张了。更糟的是,这 20 个 Skill 里大部分在当前这一次任务里根本用不上,加载了也是白加载。
所以 Skill 用了一套叫「渐进式加载」(Progressive Disclosure)的三层机制来解决这个问题。
第一层是「只看简历」。Agent 启动的时候,只加载每个 Skill 的 name 和 description 这两个字段,大概每个 Skill 只占 30 到 50 个 token。这就像你面前摆了 20 份简历,每份只看名字和一句话介绍,几秒钟就能扫完,心里有数「我手上有哪些能力可以用」。
第二层是「翻开详细资料」。当用户提了一个任务,Agent 判断「这个任务跟 code-review 这个 Skill 相关」,这时候才会把 code-review 的 SKILL.md 正文完整加载进来,读取里面的详细指令。不相关的 Skill 始终不会被加载,不浪费一个 token。
第三层是「需要时再取」。执行过程中,如果指令里提到了「使用 assets/report_template.md 的模板」,Agent 才会在那个时刻去读取这个模板文件。参考文档、脚本这些辅助资源也是一样,用到的时候才加载。
这个设计用一个类比就很好理解:Skill 就像公司给新员工准备的入职手册。你入职第一天不会把整本手册从头到尾看完,而是先扫一眼目录,知道里面有「报销流程」「请假制度」「代码规范」这些章节就行了。等你真的要报销了,再翻开「报销流程」那一章仔细看。这样既不会信息过载,又确保你需要的时候能找到。
为什么这个设计这么重要?因为 context window 是 Agent 最宝贵的资源。如果把所有 Skill 的全部内容一股脑塞进去,真正有用的用户任务信息反而会被淹没,Agent 的注意力被分散,输出质量反而下降。渐进式加载的本质就是「让 Agent 只在需要的时候获取需要的知识」,这和人类的工作方式其实是一样的。
Skill 和 Tool、Prompt 分别是什么关系
这三个概念经常被混淆,但它们处于完全不同的层次,用一个类比就能讲清楚。
你可以把 Tool(包括 MCP 工具)想象成公司给员工配的电脑、软件和数据库访问权限。有了 Tool,Agent 就能「做事」,比如查数据库、调 API、读写文件。但光有工具不够,你给一个新人配了一台电脑和所有系统权限,他也不知道该按什么流程做代码审查,不知道先查什么、后查什么、用什么格式输出报告。
Skill 就是那份「操作手册」和「SOP 流程」。它教 Agent 拿到这些工具之后,该按什么步骤、什么标准、什么格式来完成一个具体的工作流。所以 Tool 和 Skill 的关系是互补的:Tool 提供能力,Skill 提供知识和流程。
那 Prompt 呢?Prompt 就像你口头跟员工说的一句话指令,比如「帮我看看这段代码有没有问题」。这句话说完就没了,下次你还得再说一遍。Prompt 是一次性的、临时的,而 Skill 是持久化的、可复用的。
还有一个容易搞混的是 Slash Command(斜杠命令)。Slash Command 也是把指令保存下来复用,但它必须由你手动触发,比如你得输入/code-review才能调用。而 Skill 可以被 Agent 自动发现和调用,Agent 看到你的任务后,自己判断「这个任务需要用 code-review Skill」,然后主动去加载和执行,不需要你告诉它该用哪个 Skill。这个自动发现的能力,就是 Skill 比 Slash Command 更进一步的地方。
Skill 从 Anthropic 走向开放标准
Agent Skills 最早是 Anthropic 在 2025 年 10 月推出的,一开始只在 Claude 自家的生态里用,覆盖了 Claude Code、Claude API 和 claude.ai 这三个入口。推出两个月后,Anthropic 做了一个很聪明的决定:在 2025 年 12 月把 Agent Skills 的规范作为开放标准发布出来,任何想做 Agent 平台的团队都可以按这个规范来实现自己的 Skills 支持。
为什么要把规范开放?核心原因是 Skills 的设计足够简单。一个 Skill 就是一个文件夹加一份 Markdown 文件,不需要安装特殊的运行时,不需要学新的编程语言,任何支持文件系统的 Agent 平台理论上都能实现这套格式。这种「零门槛」的设计让它有希望成为跨平台的通用约定。
你可能会问,开放成标准有什么好处?好处是你写一份 Skill,未来有机会在不同的 Agent 平台之间复用,而不是被某一家产品绑死。这就像 USB 接口一样,你买一根 USB-C 数据线,手机能用、电脑也能用,不用每个设备买一根专用线。Anthropic 想做的就是让 Agent Skills 朝着这个方向发展,虽然现在主要还是 Claude 生态在用,社区里也有项目开始探索在其他 Agent 平台上兼容这个格式,后续能走到哪一步还要看行业的采纳情况。