系统篇

11|工具设计与MCP:从连接到可控执行

系统篇约 6 千字1 组分步图解
本章目录

本章预备知识

连接服务器、发现工具、获准使用、真正执行是四个关口。知道工具存在不代表当前模型看见它,更不代表当前身份获得它的全部权限。

本章各题列出所需基础。可先完成相应基础课,也可通过自检确认掌握程度。

进入深读前的小检查:用“可以连接日历,但只能读取不能写入”解释transport、tool schema、authorization和execution的不同责任。

术语带虚线时可点击速查。公式中的字母先看定义;不要用猜缩写替代推导。

本章MCP消息采用明确固定的2025-11-25规范说明基础生命周期,不宣称它是当前唯一版本。2026年的文档与扩展可能增加能力;学习时把稳定原理与版本字段分开。[MCP-LIFE]

沿着对象与状态理解本章

MCP解决连接与能力描述,不替业务决定授权。先把“工具存在”“本次对模型可见”“当前用户可执行”画成三个检查点,再看Schema与协议细节,就不会误认为发现成功等于有权限。

下方图解的固定输入在“输入与适用条件”中声明。它用于解释本章机制,不与本章其他独立例子的数值暗中接续。

动态图解 · F25

MCP连起接口,不自动交出权限

连接、发现、模型可见和实际授权分别发生在哪里?

把MCP想成工具之间的共同接口语言,而不是新大脑。Host负责应用级选择与控制,Client负责协议连接,Server提供能力。接线完成以后仍要决定哪些工具暴露给模型、哪些资源允许访问、哪些动作需要确认。

Host承载模型、任务与权限策略的应用。
ClientHost中的协议客户端。
Server提供工具、资源等能力的服务。
授权允许某个身份在某个范围执行某个动作。

输入与适用条件:按公开架构画逻辑流程,省略具体传输和认证字段。不同协议版本的能力细节以项目声明为准。

1 / 7 · 1. Host建立连接,Client与Server协商能力

第1步,共7步

窄屏可左右滑动图形,或点击“放大图形”。文字解释紧随图后。

MCP连起接口,不自动交出权限:1. Host建立连接,Client与Server协商能力Host宿主Client客户端Server服务端Host建立连接,Client与Server协商能力Client请求可用工具列表Server返回工具描述和输入结构Host选定要向模型暴露的工具通过权限检查后发送调用返回工具结果与错误信息Host将结果放入模型下一轮上下文

Host是承载AI应用的宿主;Client是其连接特定Server的协议客户端。建立连接不是自动批准所有操作。

本步状态由图形与说明共同给出。

默认静止。用“下一步”看完解释再继续;播放到最后一步自动停止。键盘聚焦播放器后,可用左右键逐步查看、空格播放/暂停。图中颜色辅助区分,含义同时用文字注明。

为什么需要

减少每个工具都单独设计集成方式的成本。

怎样实现

先发现能力,再由宿主形成模型可见集合,最后在执行边界检查权限。

可能的代价与误解

外部Server的权限不会因为本地Shell受沙箱保护而自动受同样限制。

如何判断是否做对

分别测试“未暴露”“未授权”“参数不合法”“业务拒绝”,观察是否被准确区分。

Q041|给Agent设计工具时,应该拆成很多小工具还是一个万能工具?

核心回答

工具粒度应匹配模型真实决策与系统可验证边界。太细会增加轮次和组装负担,太粗会隐藏副作用与错误原因。好的工具提供明确输入、可控输出、可区分失败和适当的幂等/版本条件,而不只是好听的名称。

比较三种仓库接口

run_shell(command)非常灵活,但参数空间巨大,输出容易冗长,安全边界依赖执行环境。read_line(file,n)过细,读取一段上下文需要几十次调用。read_file_range(path,start,end)通常更容易让模型精确获取一个证据块,并能返回下一段位置、文件版本和截断标记。

写工具同样有取舍。replace_entire_file简单但容易覆盖他人修改;apply_patch可表达局部改动,但旧片段不唯一时可能匹配错误;带expected_version和明确定位的编辑接口更容易检测冲突,却需要管理版本。没有必要对一次性临时文件都施加复杂协议,但共享仓库的写入值得更强条件。

输出应按后续任务设计。搜索工具返回文件、行号、片段和稳定引用,而不是整个仓库文本;测试工具返回命令、工作目录、版本、退出码、通过/失败/跳过统计与日志位置,而不是只有“success”。有些流程可把常见且确定的多步操作组合为工具,但不应隐藏需要用户授权的写动作。

运行示例 · Q041

把“执行任意SQL”改成“查询工单”,少了什么多了什么

输入与条件。需求只是查看用户u7名下最近10条工单。比较run_sql(sql)与list_tickets(user_id,limit)。

步骤与对象内部动作中间结果 / 新状态
1通用接口模型自己拼查询和权限条件表达能力大,也更容易忘user_id过滤或产生写操作。
2任务接口宿主固定只读查询、权限过滤和limit上限模型只填u7与10。
3返回设计给工单ID、状态、更新时间与截断提示不用把整张表的所有字段塞入上下文。
4边界失败模型填limit=100000确定性上限拦截,不靠提醒“请节约”。
5选择取舍研究人员需要复杂探索查询时受控只读SQL可能更合适,而不是把每一种查询都造一个新工具。

把过程连起来。工具粒度应贴合常见工作单位,把稳定约束放在程序里,同时避免接口碎片化。

边界与反例。这是接口设计示例,不声称专用工具在所有任务都更优;需要代表性任务评测。

依据与适用范围:[TOOLS]。示例输入和场景由本书明确设定。

追问:工具说明越详细,模型使用越好吗?

适量例子和边界有帮助;大量重复说明增加上下文且可能制造冲突。优先解释容易弄错的单位、路径、包含/排除边界、分页与副作用。通过失败样例改进描述,比写百科式说明更有效。

追问:工具名称变更为什么会影响质量?

名称参与模型理解和选择,也可能被历史状态、skill或自动化依赖。变更不只是API编译问题,还可能改变选择概率。应做功能兼容、描述更新与路由回归,而不是只检查函数是否存在。

追问:让模型执行代码批量调用工具为何能省Token?

模型可以生成一段程序,在执行环境内部筛选、循环和聚合,只把必要结果返回上下文,减少大量中间数据往返。但执行环境获得了更强能力,必须有资源和权限边界;代码执行也引入程序错误。它适合可程序化的数据处理,不代表所有工具调用都应改写成脚本。

Q042|MCP从连接到调用工具经历哪些消息?Host、Client、Server分别是谁?

核心回答

Host是承载Agent和用户交互的应用;MCP Client是Host内与特定Server通信的组件;Server暴露工具、资源等能力。连接后先协商协议版本和能力,再进入正常操作;发现工具不等于自动把它们全部送入模型。[MCP][MCP-LIFE]

按协议顺序走一次只读查询

以下为缩减的教学消息,名称和版本是示例配置。

{"jsonrpc":"2.0","id":1,"method":"initialize",
 "params":{"protocolVersion":"2025-11-25","capabilities":{},
 "clientInfo":{"name":"study-host","version":"1.0"}}}

Server回应相同id,返回它支持的协议版本、serverInfo和例如tools能力。Client检查是否兼容,然后发送无id的notifications/initialized,表示初始化完成。request有id便于关联响应,notification不期待对应响应。

接着Client发tools/list,Server返回工具名、description、inputSchema和可能的nextCursor。若有分页要继续请求,直到完成所需发现。Host把选中的工具定义转换成模型接口支持的形式;这一步属于Host策略,不是Server直接控制模型Prompt。

模型提出search_docs(query)后,Host做授权与参数检查,Client发送:

{"jsonrpc":"2.0","id":2,"method":"tools/call",
 "params":{"name":"search_docs","arguments":{"query":"部署步骤"}}}

Server返回result或协议error。Host再把内容转换为模型工具结果,关联模型侧call_id。MCP的JSON-RPC id与模型侧call_id属于不同协议层,应用可以映射,但不能假设二者天然相同。

运行示例 · Q042

一次MCP连接的消息按顺序发生什么

输入与条件。按MCP 2025-06-18规范做示意。宿主的MCP客户端连接一个只读文件服务,使用JSON-RPC消息。

步骤与对象内部动作中间结果 / 新状态
1初始化客户端发送initialize并声明协议与能力服务器返回协商结果;这不是模型工具调用。
2就绪通知客户端发送notifications/initialized建立后续正常交互阶段。
3发现工具发送tools/list服务器返回工具名称、描述与输入schema。
4构造模型请求宿主决定哪些工具说明对模型可见发现到的工具并不必然全部授权给模型。
5执行调用模型提议后,客户端发tools/callJSON-RPC请求id关联协议响应;模型call_id的映射由宿主管理。

把过程连起来。MCP解决连接与消息互操作的一部分问题,宿主仍负责模型输入、授权和任务执行组织。

边界与反例。固定规范版本的示意流程;不表示所有MCP工具都直接暴露,也不表示协议id与模型call_id可以混用。

依据与适用范围:[MCP-LIFE] [MCP-TOOLS]。示例输入和场景由本书明确设定。

追问:stdio模式为什么日志不能随便写stdout?

stdout被用来承载协议消息,普通日志混入会破坏解析。日志应走约定的日志机制或stderr。HTTP传输则有另一套连接、身份和会话要求。传输不同不改变工具schema语义,但会改变部署与故障模式。

追问:协议版本不兼容时能否继续尝试调用?

不能假设兼容。初始化就是为建立共同解释。客户端需要检查服务端返回版本是否支持;否则应退出或走明确兼容策略。把所有差异当成普通参数错误让模型猜,会把协议问题变成无意义的Token消耗。

追问:为什么能力声明不等于安全授权?

capabilities表示双方支持哪些协议功能,不证明当前用户能读取所有资源或执行所有工具。Server仍需认证授权,Host也需控制哪些能力给模型、何时批准副作用。工具注解来自不可信Server时不能作为安全事实。[MCP-TOOLS]

Q043|MCP Tools、Resources、Prompts与Skills分别是什么?

核心回答

Tools提供可调用动作;Resources提供可读取的数据对象;Prompts提供可参数化的提示模板;Skills组织可复用的任务知识、说明和资源。MCP解决接口互联,Skills解决专业工作方法的发现与加载,二者可以配合但不相互替代。[MCP][SKILLS]

对照一次“调查线上错误”

错误日志可以是resource,也可以由查询工具返回;运行日志检索是tool;“事故复盘模板”可以是prompt;“如何定位并发重复写、需要检查哪些证据”可以是skill。Skill可要求使用某个MCP工具,但这并不自动安装Server、授予凭据或保证子Agent继承它。

渐进式加载一般先让模型看到紧凑元数据,确认相关后读取具体说明,执行到某个步骤才读取附属资料。这样能减少默认上下文,但必须保留发现路径。若名字太泛、描述没有触发条件,模型可能永远不读真正有用的内容。

资源链接只是一条引用。链接是否可读取、以谁的身份读取、是否需要独立能力,都要由实际工具解决。把URI放进模型输入不能让模型自动拥有文件字节。资源版本变化时,已保存摘要也可能过期。

运行示例 · Q043

同一个仓库资料,作为Resource、Tool和Skill时有什么不同

输入与条件。仓库有 build.md,内容是构建步骤;另外有可以实际运行测试的test工具。

步骤与对象内部动作中间结果 / 新状态
1Resource通过约定资源接口提供build.md内容提供可读取数据,不代表自动执行。
2Prompt服务器提供可参数化的提示模板宿主采用后进入模型输入,不等于最高权限指令。
3Tooltest执行后返回退出码和日志发生真实计算或外部操作。
4Skill组织什么时候读取build.md、如何解释结果与后续检查属于专业流程组织,不是MCP的一条通用执行魔法。
5配合Skill选择读资料并调用工具每层职责仍保持分离。

把过程连起来。名称相似的扩展机制可以协作,但资料、模板、动作和流程不是同一个抽象层。

边界与反例。Skill描述采用开放规范概念,不声称MCP规范本身定义了所有产品的Skill生命周期。

依据与适用范围:[MCP-TOOLS] [SKILLS]。示例输入和场景由本书明确设定。

追问:为什么“安装MCP后模型应该都知道”是错误期待?

连接、发现、暴露、选择是不同阶段。Host可能只加载部分工具、发生分页遗漏或名称冲突;模型也可能没有相关调用意图。要逐阶段查日志,而不是把未调用直接归为模型不够聪明。

追问:MCP能让不同Agent共享完整记忆吗?

它可以暴露记忆读写接口,但不自动定义记忆语义、冲突处理、可见范围或压缩策略。两个Agent即使用同一个Server,也可能访问不同命名空间;共享存储还会引入竞争和污染。协议连通不等于认知一致。

追问:什么时候用普通REST就够了?

工具少、应用单一且已有稳定SDK时,直接封装REST可能最简单。需要跨多Host复用发现、标准化资源与工具接口时,MCP更有价值。技术选择看集成收益,不必为一个本地函数部署完整协议服务。

Q044|MCP报错应怎样分层?身份与网络边界在哪里?

核心回答

区分传输、协议、工具执行、业务和授权问题。它们的重试、向模型暴露内容和恢复方式不同。远程Server通常有自己的权限与环境,不能认为本地Shell沙箱自动约束远端MCP操作。[MCP-TOOLS][CODEX]

从一个超时反推可能发生的位置

连接建立失败,可能请求未发送;Server收到请求但下游超时,副作用可能已发生;Server执行完成但响应丢失,客户端只看到等待超时。这三种都可能显示“timeout”,但是否可安全重试不同。

JSON-RPC层的未知方法或格式错误与工具结果isError:true不同。后者可以表示查询语法错误、业务条件不满足等,让模型有针对性修正。HTTP401/403、证书问题、进程退出应由连接/权限层处理,不应让模型通过修改业务参数掩盖。

身份链也要追踪:用户是谁,Host用谁的凭据,Server代表谁访问下游,工具结果是否包含其他租户数据。一个共享服务账号若权限过大,模型只要构造不同resource_id就可能跨边界;schema验证不会阻止这种访问。

运行示例 · Q044

都叫“工具失败”,四层错误却对应四种修复

输入与条件。读取工具没有成功。逐次只改变一种故障条件,其余保持不变。

步骤与对象内部动作中间结果 / 新状态
1网络层连接超时检查地址、网络与服务是否可达,改Prompt通常无效。
2协议层调用不存在的JSON-RPC方法检查客户端与服务端协议支持,不应误报文件不存在。
3授权层服务器返回无权读取该目录更换正当授权或缩小目标,不能靠重试绕过。
4工具业务层已授权且协议正常,但文件不存在改路径或回到目录定位。
5结果层工具成功返回,但输出被截断补读指定范围,不要认定后半文件没有目标符号。

把过程连起来。先按失败发生的层分流,才能把错误反馈成模型或工程师可以采取的下一步。

边界与反例。错误名称为说明性分类,实际错误码取决于实现;重试仅适用于确有暂态性的故障。

依据与适用范围:[MCP-LIFE] [MCP-TOOLS]。示例输入和场景由本书明确设定。

追问:服务端说工具是read-only,能直接信任吗?

只有可信服务及审查过的实现才能支持这种安全判断。注解和描述是元数据,不是沙箱。查询也可能通过恶意输入触发副作用,或把敏感数据传到网络。需要对实现、目标地址与资源权限做实际控制。

追问:所有工具失败都要返回给模型吗?

可操作的业务反馈应返回;敏感堆栈、凭据、攻击载荷不应原样暴露。基础设施不可恢复失败可直接结束或降级,不必让模型重复猜。返回简洁错误类别与已知执行状态,保存原始日志供有权限者诊断。

追问:为什么不能自动降级到权限更大的工具?

因为失败可能正是授权边界。例如受限查询被拒绝后改用全权限Shell访问数据库,会绕过用户授权。降级应在同等或更小权限内进行;扩大权限是新的决策,不是普通容错。

记录保存在本机浏览器。

输入关键词即可检索。

↑ ↓ 选择 Enter 打开Esc 关闭 · 仅本地搜索

阅读设置

阅读设置仅保存在本机浏览器,不上传任何数据。