AI协作工程(二):从最小执行循环到 MCP 工具设计
本文承接上一篇关于 Prompt → Agent 的讨论,关注点从“prompt 为什么有效”转向一个更贴近工程的问题:当模型开始具备读取文件、遍历目录、修改内容乃至连接外部服务的能力时,一个 coding agent 本质上是由哪些部分构成的。
本文将从最小可用结构入手,逐步拆解 agent 的组成;再结合两个案例,说明工具接入如何从“本地函数注册”演进为“协议化服务”;最后补充认证机制、registry 与 tool design 等关键要素——这些才是真正决定系统能否走向工程化的核心因素。
如果用一句话概括本文的中心思想,可以这样表达:Coding Agent 不是“会写代码的 LLM”,而是一个能够感知环境、调用工具、维护状态,并在循环中持续执行任务的系统。
引言
在上一篇文章中,我们主要建立了一条基础理解路径:如果不理解模型如何处理上下文,以及 prompt 为什么会影响输出,就很容易把 AI协作 开发误解为一套零散的技巧。本文会对问题做一步推进——即便已经掌握了 few-shot、chain-of-thought 或 tool calling等,这些能力依然不足以回答一个更核心的工程问题:为什么有些系统只是“按要求生成内容”,而另一些却已经开始像 agent 一样执行任务?
关键差异并不在于模型是否会写代码,而在于执行结构是否成立。单轮问答只涉及输入与输出,而 agent 则必须引入一套循环机制:模型需要判断何时调用工具,系统负责执行工具,结果再回流到上下文中,模型基于新信息继续决策,而不是在第一次响应后结束。换句话说,agent 的本质不在于生成更长的答案,而在于形成一个完整的执行闭环。
如果进一步明确边界,可以将三种形态区分为:
- single call = input → output
一次性调用,模型只基于当前输入生成结果,没有状态延续,也不会进行后续决策或动作。 - workflow = 预定义步骤
多步执行,但流程是事先写死的(if/else 或 pipeline),模型只在固定节点被调用,不参与整体路径的决策。 - agent = 模型在 loop 中自主决定下一步(是否调用工具)
存在执行循环,模型根据当前上下文动态判断下一步行动(调用工具 / 继续推理 / 结束),系统围绕这个决策不断推进任务。
这个区分之所以重要,是因为它揭示了一个常见误区:许多系统看似在“多步执行”,但如果每一步都是预先定义好的流程,而非模型在上下文中动态决策,那么它本质上仍然只是一个更复杂的脚本,而不是真正的 agent。
下面的两个案例正好提供了一个清晰的对照:第一个案例是手工构建了一个最小化的 coding agent,第二个案例则是将类似能力封装为 MCP tool。将两者放在一起,可以看到一条明确的演进路径——如何从 prompt 驱动的本地工具调用,逐步走向具备可发现、可组合、可治理能力的工具服务体系。
---
title: 最小 Coding Agent 执行闭环
---
flowchart LR
A["用户任务
User Task"] --> B["系统提示词
System Prompt"]
B --> C["模型决策
Model Response"]
C --> D{"需要工具
Need Tool?"}
D -->|否| G["最终回答
Final Answer"]
D -->|是| E["工具调用
Tool Call"]
E --> F["执行器
Executor"]
F --> H["工具结果回注
Tool Result"]
H --> C
1. 一个最小 Coding Agent 由哪些部分组成
如果把一个 coding agent 拆开来看,最小可运行版本通常至少包含六个部分:
- system prompt:定义模型的角色、可用工具以及调用规则
- tools 定义:描述工具的名称、用途、参数与返回边界
- 工具调用解析层:判断模型输出中是否包含可执行的工具请求
- 执行层:真正运行工具并返回结果
- conversation 状态:保存用户输入、模型响应与工具结果
- 循环与停止条件:控制系统是继续执行还是输出最终答案
把这些压缩成一个公式:Agent = LLM + Tools + Loop,这条公式明确了 agent 与单次模型调用的区别:LLM 负责理解与决策,tools 提供外部能力,loop 则把“判断 → 执行 → 回注 → 再判断”串成一个闭环。缺少任意一环,都还不能称为真正的 agent。
但如果进一步靠近真实工程,这个结构还需要继续扩充。通常会补上三类关键能力:
- 更持久的状态(memory):不仅是对话历史,还包括任务阶段、中间产物与上下文信息
- 错误处理与重试机制:出错或失败是常态,需要明确的恢复策略
- 终止策略(stop condition):区分“继续尝试”与“返回结果”的边界
因此,从工程视角看,更完整的表达:Agent ≈ LLM + Tools + Memory + Execution
这里的 memory 不一定是复杂的长期记忆,也可以是当前仓库上下文和任务中间状态;execution 则是实际执行动作的一层,例如读写文件、运行命令或调用外部服务。补上这两层之后,agent 才真正具备持续处理任务的能力。
在这几个组成部分中,最容易被忽略的是执行。很多人在初次接触 agent 时,会把注意力集中在 prompt 或工具描述上,仿佛只要告诉模型“可以使用这些工具”,系统就可以自动升级。但实际上:
- 没有解析层 → 模型输出无法转化为可执行动作
- 没有结果回注 → 模型无法获取执行反馈
- 没有循环结构 → 系统只能做一次决策
因此,判断一个系统是否是 agent,关键不在“能不能调用工具”,而在是否具备完整的:判断 → 执行 → 回注 → 再判断。tool calling 只是入口,真正的差别在于闭环是否成立。这个最小结构可以用一段伪代码表达:
1 | conversation = [system_prompt, user_task] |
这段逻辑虽然简单,但已经区分了两类系统:前者只生成一轮文本,后者则在“生成 ↔ 执行”之间形成循环。
不过,“能跑”并不等于“能用”。一个可用的最小 agent,至少还需要补上两个关键点:
- stop condition:什么时候应该结束,而不是无限循环
- failure handling:当工具失败时,是重试、降级还是直接返回
很多 demo 到这里就结束了,但在真实工程中,难点才从这里开始。
2. 从零实现一个 Coding Agent:关键不是模型调用,而是闭环成立
先看完整代码。这段代码实现了一个最小可运行的 coding agent:它可以读取文件、查看目录、修改代码,并在模型的决策下自动调用这些工具完成任务。
1 | import inspect |
这段代码表面上是在用 OpenAI SDK 写一个命令行助手,但核心并不是 chat.completions.create(...) ,而是围绕它搭建起来的执行结构。也正是这层结构,让系统从“单次模型调用”转变为“可持续运转的 agent”。
我们首先看系统提示词。这里不仅包含了工具清单和工具描述,还明确规定了工具调用的输出格式。模型在需要使用工具时,必须严格输出一行固定结构:
1 | tool: TOOL_NAME({"arg":"value"}) |
这一步揭示了一个关键点:在最小实现阶段,工具调用本质上仍然是一种语言协议。模型并不会直接调用本地 Python 函数,它只是根据提示词生成符合约定格式的文本;真正的执行,是由系统解析这段文本后完成的。换句话说,模型之所以“会用工具”,并不是因为它理解了工具的实现,而是因为提示词把可用能力编码成了一种它可以续写的结构。
接着,代码通过 TOOL_REGISTRY 将本地函数组织成一个稳定映射:
1 | TOOL_REGISTRY = { |
这一层在结构上非常关键。它把“模型看到的工具名”与“系统实际可执行的函数”绑定在一起。没有这层映射,提示词中的工具只是一段描述;有了 TOOL_REGISTRY,模型输出的工具调用才有机会转化为真实执行。可以说,这一层完成了从“语言层能力声明”到“执行层具体动作”的连接。
再往下看,extract_tool_invocations 这样的解析函数承担了另一个核心职责:从模型输出中提取工具调用请求,并解析其中的 JSON 参数。这一步同样暴露了最小 agent 的一个重要特征——脆弱性。只要模型输出的格式稍有偏差,例如多出额外文本或 JSON 不合法,整个执行链路就会中断。因此,这种实现方式非常适合理解 agent 的第一性原理,但并不适合直接用于复杂、长期运行的系统。
真正让系统具备 agent 属性的,是最后的循环机制。代码在获取模型输出后,并不会立即结束,而是先判断是否存在工具调用请求。如果存在,就执行对应工具,并将结果重新写入对话上下文:
1 | conversation.append({ |
这一操作可以视为整个实现的关键节点。它意味着外部世界的执行结果被重新注入模型的上下文中,使模型能够基于最新状态继续决策。此时,模型的行为不再局限于对初始问题的回答,而是可以结合刚刚获得的文件内容、目录结构或修改结果,推进下一步行动。也正是在这一刻,系统形成了“决策—执行—反馈—再决策”的闭环。
从工程视角来看,这段代码至少传达了四个核心要点。
- agent 并不会随着 prompt 的增加自然出现,它依赖一套明确的执行骨架。
- 工具调用在初始阶段并不复杂,本质上只是可解析的字符串协议。
- conversation 不仅需要保存人类对话,还必须纳入外部执行反馈,成为完整的状态载体。
- 模型在 agent 中承担的是决策角色,而非独立完成所有工作的黑盒。
进一步来看,这个案例还有一个更重要的结论:在 AI coding 场景中,关键能力往往不在“生成代码”,而在“获取上下文并基于上下文修改代码”。系统需要先了解仓库结构、相关文件以及当前实现状态,后续的生成与修改才具备依据。因此,repo context acquisition 并不是附属能力,而是 coding agent 的核心执行能力之一。
3. 为什么只靠本地函数注册还不够
到这里,一个最小的 coding agent 已经可以运行:模型能够根据输入做出判断,选择是否调用工具,执行操作,并在结果回注之后继续推进任务。从结构上看,这套 LLM + tools + loop 的闭环已经成立,系统也从单次调用转变为可以持续运转的执行体。
在最小案例中,agent 运行在命令行环境里,可用的工具也只有几个本地函数,例如读取文件、列出目录或修改内容。这样的环境足够简单,问题也相对收敛。但当 agent 被放入编辑器环境,例如 AI IDE 时,系统所面对的上下文会迅速扩展。文件树、当前打开的文件、选中的代码片段、编译错误、运行结果,这些都会成为模型可以消费的信息。agent 不再只处理一段输入文本,而是开始面对一个持续变化的环境。
然而,这种变化并没有改变底层结构。无论是在命令行还是在 IDE 中,系统仍然围绕同一套机制运行:模型基于上下文做决策,决定是否调用工具,执行操作,再将结果回注到上下文中继续判断。界面可以变化,交互可以变化,但底层始终是 LLM + tools + context + loop。理解这一点,比记住具体产品形态更重要。
在这样的系统中,一个容易被忽略但极其关键的问题开始浮现出来:在动手修改之前,系统读了什么。coding agent 的表现,很大程度上并不取决于生成能力本身,而取决于它在生成之前是否获得了足够且正确的上下文。如果没有先列出目录、没有定位相关文件、没有理解现有实现,那么后续生成的代码再流畅,也往往只是脱离真实仓库状态的猜测。
“先读什么,再改什么”本身是一个系统设计问题,而不是工具细节问题。工具只是提供了读取能力,但是否读取、读取哪些内容、以什么顺序读取,这些决策都属于 agent 的核心逻辑。在复杂工程中,这一问题会被进一步放大,因为相关信息往往分布在多个文件和多个模块之中,错误的上下文选择会直接导致后续决策偏离。
当系统规模继续扩大,本地函数注册的方式也开始显露出明显的局限。最小实现中,通过 TOOL_REGISTRY 将工具统一管理是完全可行的,但这种方式默认了一件事:工具属于 agent 的内部实现细节。只要工具数量有限,并且都在同一个进程内,这个假设是成立的。但一旦工具开始变多,或者需要跨进程、跨机器调用,这种方式就会迅速变得难以维护。
- 首先,工具定义与执行是强耦合的。函数既是接口也是实现,难以独立演进,也难以被多个系统复用。
- 其次,工具来源被限制在本地进程中,无法自然接入远程服务或已有系统能力。
- 再进一步,系统缺乏工具发现机制,所有能力都需要手动注册,客户端无法动态感知当前可用工具。
- 同时,调用边界与权限控制缺失,所有工具默认可用,缺乏清晰的访问约束。
在多客户端场景下,这些问题会更加明显,因为不同系统之间没有统一的接口约定,也无法进行集中治理。
这些问题本质上指向同一个事实:本地函数注册把工具当作“代码中的函数”,而不是“系统中的能力”。在最小场景中,这种视角足够,但在工程系统中,它会逐渐成为限制。
因此,工具需要发生一次角色转变。它不再只是写在某个脚本里的函数,而是需要变成可以被描述、被发现、被调用的独立能力。也就是说,工具需要具备统一的接口形式,使不同客户端能够以一致的方式访问它们,同时也为权限控制、调用约束和系统治理提供基础。
从这个角度看,MCP 的出现并不是为了重新定义 agent,而是针对工具层的工程化问题给出了一种解决路径。它关注的不是模型是否能够调用函数,而是在工具体系开始走向复用和共享时,如何用统一协议来描述和接入这些能力。换句话说,MCP 解决的是工具层的标准化问题,而不是模型能力问题。
因此,将 MCP 理解为一个孤立的概念并不准确。更合理的理解方式是,它是 agent 系统在复杂度上升之后的自然演进结果。在最小实现中,工具可以是本地函数;在工程系统中,工具更需要成为可发现、可描述、可调用、可治理的能力接口。这种从“函数”到“能力”的转变,正是 coding agent 从原型走向工程化的关键一步。
4. 自定义 MCP Server:工具如何从函数变成能力接口
先看完整代码,包括 server 和 client。
1 | # ===== server: chapter_4_1.py ===== |
1 | # ===== client: chapter_4_1_client.py ===== |
这个案例用 FastMCP 把工具层的变化非常直接地表达了出来。相比第二章中基于 TOOL_REGISTRY 的本地注册方式,这里最大的变化并不在于“换了一个框架”,而在于系统边界发生了变化。
在本地实现中,工具函数属于 agent 脚本的一部分,它们的生命周期、调用方式和可见范围都被限制在当前进程内。而在这里,随着 FastMCP 的引入,工具开始从“脚本内部函数”转变为 “服务对外能力”。这一变化,从 server 初始化那一刻就已经发生。
创建 FastMCP 实例,意味着系统不再只是组织函数,而是在构建一个可以被外部访问的能力提供方。工具不再附属于某个 agent,而是成为一个可以被连接、被发现、被调用的对象。这一点,决定了后续整个系统的扩展方式。
这种变化在 @mcp.tool() 上体现得更加明显。这个装饰器的意义,并不是简单的注册函数,而是为函数赋予协议语义。函数的名称、参数结构、返回格式都会被提取出来,形成结构化描述,供客户端通过 list_tools 查询。这意味着工具的描述不再写在 prompt 里,而是进入了协议层。
与此同时,client 的存在,让这种变化变得具体可见。在本地模式下,调用路径是直接执行函数;而在 MCP 中,调用路径变成通过协议发起请求。也就是说,调用方不再依赖函数本身,而是依赖工具接口。这一点,是“函数”与“能力接口”之间的本质区别。
从结构上看,这里至少拆出了几个清晰的角色。client 负责连接与调用,server 负责能力暴露,tool 是具体执行单元,tool result 承载执行结果。原本混在一个脚本里的逻辑,被拆成了清晰的系统边界。正是这种拆分,使得 agent、工具提供方和调用方之间可以相互独立。
这种独立性带来了几个直接结果。首先,工具可以被多个客户端复用,不再绑定于某一个 agent。其次,工具可以被动态发现,而不需要写死在代码中。再次,调用方式统一之后,权限控制、远程访问、调用约束才有落地空间。这些能力在本地函数注册模式中很难自然出现,但在协议化之后成为系统的一部分。
mcp.run() 进一步强化了这一点。它意味着工具不再随着脚本执行结束而消失,而是以服务形式持续存在。只有在这种模式下,客户端才能在任意时间连接、列出工具并发起调用。这看起来像运行方式的变化,但本质上是系统从“一次性执行”转向“长期存在能力”。
把这一章节与前面章节放在一起,可以看到一个清晰的演进路径。最初,工具只是本地函数,通过字典注册供 agent 使用;随后,工具获得结构化描述,并通过协议对外暴露;再进一步,工具成为独立能力,由不同客户端调用。这个过程不是从抽象理论出发设计的,而是随着执行链路不断拉长、系统复杂度不断提升,自然发生的结构变化。
因此,本章的重点并不在于如何使用 MCP,而在于理解一个关键转变:工具从“函数”变成“能力接口”。当这一转变发生之后,agent 系统的组织方式也随之改变,系统开始具备复用、扩展与治理的基础。这一步,标志着 coding agent 从原型阶段真正进入工程化阶段。
---
title: 本地工具注册与 MCP server 的对比图
---
flowchart LR
A1["本地 Agent Script
TOOL_REGISTRY 注册工具"]
--> B1["执行机制
直接函数调用
tool(...)"]
--> C1["结果路径 A
工具 = 本地函数
强耦合
仅进程内可用
难复用"]
A2["Agent Client
通过 MCP 连接"]
--> B2["执行机制
协议调用
session.call_tool(...)"]
--> C2["结果路径 B
工具 = 能力接口
发现
调用
解耦
治理"]
5. 好的 MCP Tool 该如何设计
理解 MCP 之后,一个很容易出现的误区,是把注意力过多放在协议本身,仿佛只要把工具挂到 MCP server 上,agent 就自然会变强。实际上,协议解决的是“如何接入”的问题,而真正决定 agent 使用体验的,往往不是有没有 MCP,而是 tool 本身是否设计得足够清晰、稳定、可调用。
这也是为什么在讨论 MCP 时,有一个判断需要被单独强调:API 不等于好 tool。
API 往往面向底层资源和完整操作集,追求的是功能覆盖与能力开放;但模型真正适合调用的 tool,通常不是底层能力的原样暴露,而是围绕具体任务抽象出来的动作单元。换句话说,tool 更像是为模型设计的任务接口,而不是给人类工程师看的系统说明书。
对于模型来说,最友好的工具通常具备一种“任务导向”的形态。它不要求模型理解过多隐藏前提,也不要求模型在大量参数和分支之间做复杂判断,而是尽量把一个高频动作压缩成边界清楚、输入有限、返回稳定的调用单元。像第二章中的 read_file_tool、list_files_tool 和 edit_file_tool,就属于这一类典型例子。它们的名字直接表达用途,参数数量相对有限,返回结构也比较稳定,因此很容易被放进 agent loop 中持续使用。对于模型来说,这类工具更容易“做对”,因为它不需要在决策时同时处理太多分支判断。
如果把这个判断再往前推进一步,就会更容易看清 tool design 在 agent 系统中的位置。假设当前任务是“根据数据库表结构生成登录相关代码”,系统真正需要的,通常不是让模型凭空猜测数据库长什么样,而是先通过工具读取真实 schema,再基于返回结果生成代码框架。也就是说,agent 更合理的执行方式不是直接开始写代码,而是先调用类似 get_user_table_schema 这样的工具,获取 users 表的字段、类型和约束,再继续生成 API、数据模型和校验逻辑。
这个例子清楚地说明了一件事:tool use 的作用,不是给模型补一点“额外信息”,而是把原本不该靠猜测完成的任务,改造成“先读取外部事实,再继续执行”的受控链路。一旦这个链路建立起来,模型的输出就不再只是语言补全,而开始建立在真实上下文之上。
反过来看,如果只是把一个庞大 API 的全部细节原样暴露给模型,结果往往并不会更好。参数过多时,模型更容易拼错、漏传或误解字段含义;工具粒度过细时,模型需要在一堆相似选项里做不稳定决策;返回结果如果缺乏稳定结构,后续 prompt 也很难继续消费这些信息。也就是说,工具越“完整”,并不一定越容易被模型正确使用,很多时候恰恰相反。
因此,一个好的 MCP tool,通常至少要满足几个基本要求:
- 名字要足够清楚,让模型一眼知道它是干什么的。
- 参数边界要足够明确,不要让模型去猜哪些参数是必须的,哪些前提是隐含的。
- 返回结构要足够稳定,这样模型才能把结果继续接进后续推理和执行中。
- 失败模式也要清楚,因为对 agent 来说,失败并不是结束,关键是失败之后还能不能知道下一步该怎么调整。
从这个角度看,一个好 tool 的本质,并不是“把系统能力公开出来”,而是在为模型设计一个更容易调用正确的接口。它做的事情,不是单纯暴露能力,而是整理复杂性:把底层系统中那些原本只有工程师才能稳定处理的细节,压缩成模型也更容易理解和执行的任务单元。
如果把这件事换成一个更直观的例子,可以看一个常见的需求:
1 | User: add login API |
一个不成熟的系统,可能会让模型直接开始生成代码;但一个更像 agent 的系统,执行过程通常会更接近下面这样:
1 | Agent: |
这个链路虽然很短,却刚好揭示了 agent 与普通代码生成的差异。真正发生的,不再是“模型一次性吐出答案”,而是系统先读取外部事实,再组织动作,再修改结果。也正因为如此,tool design 才会成为 agent 质量的关键变量。工具不是越多越好,关键在于它们是否能被稳定组合成连续动作。
这也是本章更想强调的地方。对于 agent 来说,真正决定效果上限的,往往不是工具数量,而是工具抽象是否足够合理。模型并不是一个真正理解系统全貌的工程师,它更像是在上下文中做近似决策的执行器。好的 tool design,本质上就是把外部世界整理成一种更适合它正确调用的形状。
6. MCP 的工程化外延:认证、Registry 与生态
当工具从本地脚本走向通过 MCP server 提供能力之后,问题的性质会发生变化。在本地环境中,tool 更像是 agent 的“内部函数”,调用关系清晰、边界隐含;但一旦跨进程、跨机器甚至跨组织调用,tool 就不再只是能力封装,而开始变成一种系统边界上的服务接口。也正是在这一刻,一组典型的工程问题会自然浮现出来。
首先出现的是认证问题。只要工具不再运行在完全信任的本地环境中,就必须回答一些基础但关键的问题:谁可以调用这个工具,哪些操作需要额外授权,不同用户是否拥有不同能力范围,调用失败时如何处理。这些问题本质上并不是“登录流程怎么实现”,而是能力边界的定义问题。也就是说,认证关心的不是身份本身,而是哪些能力可以被谁在什么条件下调用。从这个角度看,认证并不是 MCP 的附加模块,而是它走向真实生产环境时必须面对的核心组成部分。因为一旦 tool 可以访问数据库、修改代码或执行命令,它就已经成为系统行为的一部分,而不再只是一个被动工具。
随着工具数量增加,第二个问题很快出现:如何发现这些工具。如果系统中只有少量 MCP server,通过手工配置连接关系尚且可行;但当工具来自不同团队、不同服务甚至不同组织时,这种方式很快会变得不可维护。此时系统需要的不只是“能调用工具”,而是“能够在需要时找到合适的工具”。这正是 registry 层存在的意义。它并不只是一个工具目录,而是让工具的发布、发现和复用开始具备标准化的组织方式。如果说 MCP server 解决的是“工具如何被标准化暴露”,那么 registry 进一步解决的是“工具如何被标准化找到”。这两者分别对应接口问题和发现问题,当它们同时存在时,工具系统就不再是若干孤立 server 的集合,而开始具备网络化扩展的能力。
再往前一步,是实现成熟度的问题。MCP 不只是一个抽象协议,还逐渐配套了 SDK、示例 server、调用流程以及认证与扩展说明。这意味着 MCP 正在从“如何设计接口”的讨论,走向“如何在真实系统中落地”的阶段。只有当协议、实现和运行环境连在一起时,它才真正具备作为工具层标准的意义。
不过,放回本文主线,这些外延并不需要逐一展开细节。更重要的是建立一个更稳定的认识:当一个 agent 系统开始认真处理 tool use,它迟早会遇到同一组问题——如何描述工具、如何调用工具、如何控制权限、如何发现工具,以及如何进行治理。MCP 的价值,并不在于引入了多少新概念,而在于它为这些问题提供了一套统一的接口语言。
这也顺带带出一个重要的问题。很多人会把 agent 的能力理解为“能不能改文件、写代码、跑命令”,但一旦进入真实仓库,系统立刻会碰到权限边界、修改范围、失败回滚和安全控制这些问题。换句话说,执行能力和治理能力往往是一起增长的。一个只会“做事”的 agent,在真实环境中很难稳定工作;只有同时具备边界控制和结果约束的系统,才真正具备工程意义。
因此,当我们把 MCP 放回工程语境中,它的意义就不再只是一个 tool calling 协议,而更像是一套用于组织工具调用、权限边界与生态扩展的基础设施。它所连接的,并不是单个工具,而是 agent 从“能调用工具”走向“能在真实系统中运行”这一过程的关键。
7. 总结
coding agent 的关键不在于“更会生成代码”,而在于“更完整地组织执行”。
系统提示词、工具描述、调用解析、结果回调以及循环结构,这些部分组合在一起,才构成一个最小可运行的 agent。本文第二章的案例说明了这套执行骨架如何成立,而第四章的案例则进一步揭示:一旦工具开始参与执行,这套结构就不可避免地走向更稳定的接口与更清晰的边界。
从这个角度看,MCP 并不是一个突然出现的新中心,而是 agent 工程化过程中的自然延伸。它把“函数能不能被调用”的问题,推进成“外部能力如何被描述、接入并长期维护”的问题。也正是在这一层上,工具不再只是本地实现细节,而开始成为系统的一部分。
继续往前,认证会演变为权限边界的问题,registry 会演变为发现与分发机制,SDK 和 sample servers 会进入工程复用。但在这些变化之中,最值得抓住的并不是这些名词本身,而是更底层的一点:API 面向系统,而 tool 面向模型。
真正决定 agent 可用性的,往往不是能力是否齐全,而是这些能力是否被抽象成模型可以稳定调用的形状。也就是说,tool design 才是贯穿始终的核心变量。
本文先把几个基础的问题理清:agent 的执行结构是什么,工具层发生了什么变化,MCP 在这条链路中处于什么位置。只有在这一层结构被看清之后,后面无论进入 AI IDE、terminal agent、权限控制、安全机制还是复杂工作流,看到的就不再只是工具形态的差异,而是它们背后共享的那套执行逻辑。
8.备注
本文部分观点基于公开资料整理与个人实践总结,如有引用不准确之处欢迎指正。
参考材料: