“最后不还是 Agent 在调工具吗?那 MCP 多做了什么?”
这个问题比背定义有用。因为第一次看 MCP,很容易把模型、Agent、Harness、Client、Server 都画成一团,然后得出一个模糊的结论:MCP 就是 Function Calling 的另一种写法。
先说结论:模型负责提出要做什么,应用负责把它做成一次真实调用;MCP 约定的是应用与外部服务之间怎么对接。
先从一次工具调用看起
假设我对一个代码助手说:“帮我看看 PR 123,有没有明显问题。”模型发现自己还没看到改动,于是提出:调用 get_pr_diff,参数是 123。
到这里,模型只给出了调用意图。真正去取 PR、处理权限、拿回结果的,是运行这个助手的应用。Function Calling 主要解决前半段:让模型以结构化方式表达工具名和参数,再由执行方把结果交回来。OpenAI Function Calling 文档
如果 get_pr_diff 来自一个独立的服务,应用还得知道:服务在哪儿?它有哪些工具?参数长什么样?调用后会返回什么?MCP 给这段对接提供了共同的协议。MCP 架构规范
所以两者可以连起来用,但不在同一层:
模型提出调用 → 应用接收并检查 → MCP Client 请求 MCP Server → 返回结果给模型
有的平台也原生支持 MCP 接入,并不要求应用先把每个 MCP 工具都转换成普通的 function tool。上面这条链路是帮助理解职责的简化图,不是所有平台内部唯一的实现方式。OpenAI MCP 接入文档
MCP Client 到底放在哪里?
MCP 文档把参与者分为 Host、Client 和 Server。Host 是使用这些能力的应用;它创建和管理 MCP Client。一个 Client 与一个 Server 通信,Server 则提供工具、资料等能力。MCP 架构规范
在 Codex 这类 Agent 应用里,Client 通常由 Harness 管理。但它不属于模型,也不只能放在 Harness 里。IDE、桌面应用、自己写的后端,只要实现 MCP Client,都能连接 MCP Server。普通程序甚至可以不接模型,直接读取 Resource 或调用 Tool。
也不必先建一个统一注册中心。本地 Server 可以由应用启动,远程 Server 可以按地址连接;应用需要知道要连接谁,并在执行时落实自己的权限规则。MCP Server 本身不需要再“提供一个 Client 端”。MCP TypeScript Client 入门
Tools、Resources、Prompts:别把三者都当成函数
继续用 PR 审查的例子:
| Server 提供的能力 | 可以是什么 | 谁通常决定何时用 |
|---|---|---|
| Tool | get_pr_diff(123),获取这次改动 | 模型选择,应用执行 |
| Resource | repo://CONTRIBUTING.md,项目开发规范 | 应用决定怎样展示或加入上下文 |
| Prompt | review_pr(123),一套审查提问模板 | 用户选择,应用取回模板消息 |
Resource 像“可寻址的资料”。它不一定是静态文件,也可以是由 Server 在读取时生成的内容;关键是 Client 能通过 URI 找到并读取它。Tool 也能查询数据,两者的区别主要是调用接口和使用方式,不是“读操作只能用 Resource、写操作只能用 Tool”。Resources 规范、Tools 规范
Prompt 则像应用里可选的提问方式:用户点“审查 PR”,填入编号,Server 返回适合放进对话的消息。它不会因为 Server 连上了,就自动变成模型的系统指令。Prompts 规范
一个 Server 可以同时提供三种能力,也可以只提供 Tool。MCP 没要求“凑齐三件套”才能工作。MCP Server 能力概览
放到同一张图里
下面画的是一种常见用法。虚线表示按需读取 Prompt 或 Resource;三类能力没有固定调用顺序,也不要求每轮都用到。
这张图只画了一轮。实际任务里,模型可能连续调用多个 Tool;应用也可能在工具返回后再读取 Resource。协议规定了这些能力怎么请求,没有规定必须按 Prompt → Resource → Tool 的顺序走。
什么场景下值得用 MCP?
我更愿意把判断标准放在“这项能力要被谁使用”上。假如同一个代码仓库服务,既要接 IDE,又要接桌面 Agent,后面可能还要接内部审查平台,那么每个宿主各写一套工具适配,很快就会变成重复劳动。把能力放进独立的 MCP Server,几个应用就能用同一套方式发现和调用它。
下面几种情况,MCP 往往比较合适:
- 一项外部能力要被多个 Host 复用,例如代码平台、知识库、工单系统同时服务于 IDE 和 Agent 应用。
- Client 需要按协议发现 Server 当前提供的 Tools、Resources 或 Prompts,而不是在应用里长期写死一份能力清单。
- 能力本来就有独立的服务边界,希望把参数、返回结构和接入方式稳定下来,方便服务与应用各自演进。
反过来,如果只有一个应用、两三个稳定的本地函数,而且没有跨宿主复用和动态发现的需求,直接使用 Function Calling 配合普通函数通常更省事。少一层服务,也少一套连接、部署和故障排查成本。
一个很实用的做法是:先用简单工具把需求跑通;当第二个宿主出现,或者同一套接入开始被重复实现时,再认真考虑 MCP。它解决的是连接规模变大后的协作问题,不是每个工具调用都必须经过的仪式。
FAQ:前面几个问题,一次答完
MCP 是不是 Function Calling 的另一种写法?
不是。Function Calling 让模型结构化表达“调用哪个工具、传什么参数”;MCP 约定应用怎样发现并连接外部能力。它们可以出现在同一条调用链上,但解决的是不同层的问题。
MCP Server 一定要注册到统一中心吗?
不需要。应用可以按配置连接远程 Server,也可以直接启动本地 Server。统一目录或服务市场可以作为额外设施,但不是使用 MCP 的前置条件。
MCP Client 一定在 Agent Harness 里吗?
不一定。Host 负责创建和管理 Client;在 Agent 应用里,这部分常由 Harness 承担。IDE、桌面应用或后端服务也可以自己实现 Client,甚至不接模型也能使用 Server 提供的能力。
Resource、Prompt、Tool 有固定使用顺序吗?
没有。用户可以先选 Prompt,应用可以在任意合适的时机读取 Resource,模型也可以按任务需要调用一次或多次 Tool。具体顺序由产品交互和任务流程决定。
最后怎么记?
下次再看到 MCP,可以先问三个问题:
- 谁做决定? 模型通常决定要不要调用 Tool;Prompt 通常由用户选择;Resource 怎样进入上下文由应用安排。
- 谁真正发请求? 是应用里的 MCP Client,不是模型自己连到 Server。
- Server 提供什么? 它可以提供 Tool、Resource、Prompt 中的一种或多种。
把“模型决策”和“协议通信”分开,MCP 就没那么玄了。它没有替 Agent 思考,也没有替应用处理所有权限和流程;它让不同应用与外部能力之间有了一套共同的接法。