27-工具发现与调用流程——路由注册表与四阶段调用编排
第 1 章 文档定位与阅读指引
1.1 本篇在 55 篇中的位置
本系列围绕《AI Agent 智能体分层架构全景图深度拆解》展开。前 26 篇已完成认知层(17–24)与连接协议层定位/协议规范(25–26)。本篇承接源文档 6.4 工具发现与调用流程,回答一个承上启下的工程问题:协议规范(26 篇)已经定义了 tools/list、tools/call 这些方法,但 Agent 在实际运行时,到底是怎么从"不知道有哪些工具"走到"精确调用某个工具并拿到结果"的?
- 25 篇:连接协议层为什么存在(N×M → N+M 降维)。
- 26 篇:MCP 协议本身怎么定义(JSON-RPC、三原语、会话)。
- 本篇:工具发现与调用的完整流程编排(路由注册表 + 四阶段)。
- 28 篇:典型 MCP Server 详解(GitHub/数据库/浏览器)。
- 29 篇:代码审查 Agent 案例 + MCP vs 传统 API + 第 6 章小结。
1.2 本篇要回答的核心问题
1.3 读者对象与前置
- 读者:AI 应用架构师、Agent 平台开发者、MCP 集成工程师、对"AI 如何调用工具"好奇的产品经理。
- 前置:建议先读 25(连接协议层定位)与 26(MCP 协议规范);本篇会在用到方法名时直接引用其定义。
1.4 阅读方法建议
- 想快速理解骨架:读第 2、3 章(概念 + 四阶段全景)。
- 想落地实现:重点读第 4、5、6、7 章(注册表/发现/调用/多 Server)。
- 想避坑:读第 8 章(技术挑战)。
- 想直观感受:读第 9 章(通俗案例)。
- 想验收成果:读第 10 章(小结、自测、清单)。
1.6 本篇与行动层的衔接
工具发现与调用是"认知层决定做什么、连接协议层负责怎么执行"的接缝处:
- 认知层(17–24 篇):Agent 规划、决策,决定"要调用哪个工具"。
- 连接协议层(25–29 篇):提供工具清单与调用通道。
- 行动层(30 篇起,源第 7 章):工具背后的真实执行器(API、代码沙箱、数据库)。
本篇是"决策与执行之间的路由层":它不替 Agent 做决策,也不替 Server 干活,只保证"决策了就能精准、可靠地到达正确的执行者"。
1.7 本篇的知识地图
#mermaid-svg-My0EAzqQXw4Ynhtn{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-My0EAzqQXw4Ynhtn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-My0EAzqQXw4Ynhtn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-My0EAzqQXw4Ynhtn .error-icon{fill:#552222;}#mermaid-svg-My0EAzqQXw4Ynhtn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-My0EAzqQXw4Ynhtn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-My0EAzqQXw4Ynhtn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-My0EAzqQXw4Ynhtn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-My0EAzqQXw4Ynhtn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-My0EAzqQXw4Ynhtn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-My0EAzqQXw4Ynhtn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-My0EAzqQXw4Ynhtn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-My0EAzqQXw4Ynhtn .marker.cross{stroke:#333333;}#mermaid-svg-My0EAzqQXw4Ynhtn svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-My0EAzqQXw4Ynhtn p{margin:0;}#mermaid-svg-My0EAzqQXw4Ynhtn .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-My0EAzqQXw4Ynhtn .cluster-label text{fill:#333;}#mermaid-svg-My0EAzqQXw4Ynhtn .cluster-label span{color:#333;}#mermaid-svg-My0EAzqQXw4Ynhtn .cluster-label span p{background-color:transparent;}#mermaid-svg-My0EAzqQXw4Ynhtn .label text,#mermaid-svg-My0EAzqQXw4Ynhtn span{fill:#333;color:#333;}#mermaid-svg-My0EAzqQXw4Ynhtn .node rect,#mermaid-svg-My0EAzqQXw4Ynhtn .node circle,#mermaid-svg-My0EAzqQXw4Ynhtn .node ellipse,#mermaid-svg-My0EAzqQXw4Ynhtn .node polygon,#mermaid-svg-My0EAzqQXw4Ynhtn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-My0EAzqQXw4Ynhtn .rough-node .label text,#mermaid-svg-My0EAzqQXw4Ynhtn .node .label text,#mermaid-svg-My0EAzqQXw4Ynhtn .image-shape .label,#mermaid-svg-My0EAzqQXw4Ynhtn .icon-shape .label{text-anchor:middle;}#mermaid-svg-My0EAzqQXw4Ynhtn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-My0EAzqQXw4Ynhtn .rough-node .label,#mermaid-svg-My0EAzqQXw4Ynhtn .node .label,#mermaid-svg-My0EAzqQXw4Ynhtn .image-shape .label,#mermaid-svg-My0EAzqQXw4Ynhtn .icon-shape .label{text-align:center;}#mermaid-svg-My0EAzqQXw4Ynhtn .node.clickable{cursor:pointer;}#mermaid-svg-My0EAzqQXw4Ynhtn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-My0EAzqQXw4Ynhtn .arrowheadPath{fill:#333333;}#mermaid-svg-My0EAzqQXw4Ynhtn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-My0EAzqQXw4Ynhtn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-My0EAzqQXw4Ynhtn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-My0EAzqQXw4Ynhtn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-My0EAzqQXw4Ynhtn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-My0EAzqQXw4Ynhtn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-My0EAzqQXw4Ynhtn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-My0EAzqQXw4Ynhtn .cluster text{fill:#333;}#mermaid-svg-My0EAzqQXw4Ynhtn .cluster span{color:#333;}#mermaid-svg-My0EAzqQXw4Ynhtn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-My0EAzqQXw4Ynhtn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-My0EAzqQXw4Ynhtn rect.text{fill:none;stroke-width:0;}#mermaid-svg-My0EAzqQXw4Ynhtn .icon-shape,#mermaid-svg-My0EAzqQXw4Ynhtn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-My0EAzqQXw4Ynhtn .icon-shape p,#mermaid-svg-My0EAzqQXw4Ynhtn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-My0EAzqQXw4Ynhtn .icon-shape .label rect,#mermaid-svg-My0EAzqQXw4Ynhtn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-My0EAzqQXw4Ynhtn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-My0EAzqQXw4Ynhtn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-My0EAzqQXw4Ynhtn :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
第2章 核心概念
第3章 四阶段全景
第4章 注册表
第5章 发现机制
第6章 调用机制
第7章 多Server
第8章 挑战
第9章 案例
第10章 小结
1.8 与源文档的承接关系
源文档 6.4 共 44 行(2517–2560),核心是一张四阶段 sequenceDiagram。本篇将其拆为:
| 阶段1 初始化 | 第 3 章 3.11–3.14 |
| 阶段2 工具发现 | 第 3 章 3.15–3.17 + 第 5 章 |
| 阶段3 注册路由 | 第 3 章 3.18–3.19 + 第 4 章 |
| 阶段4 工具调用 | 第 3 章 3.20–3.22 + 第 6 章 |
| 多 Server(GitHub+Slack) | 第 7 章 |
1.9 阅读时长与篇幅
- 全篇约 2500 行、30+ 图,按 10 章组织。
- 每章内部用大量 ### 子节承载深度,不增加章数(符合系列规范)。
1.10 本章小结(扩展版)
本篇是"连接协议层"由静态规范走向动态运行的转折点:协议定义方法,流程编排方法。四阶段(初始化→发现→注册→调用)与路由注册表,是 Agent 工具能力的"运行时神经系统"。本篇衔接认知层决策与行动层执行,是"决策与执行之间的路由层"。
第 2 章 核心概念:发现与调用的本质
2.1 从"硬编码"到"动态发现"
传统集成里,Agent 要用 GitHub 的搜索功能,开发者得先写死一段适配代码:
def search_code(query, repo):
token = get_token("github")
return github_api.search_code(query=query, repo=repo, token=token)
每个工具、每个 API 都要写一套这样的胶水代码。工具一多,代码里全是 N×M 的适配组合。MCP 的出现把"写死"变成"运行时发现":
#mermaid-svg-BZ5xOGzRfBc9yvEw{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BZ5xOGzRfBc9yvEw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BZ5xOGzRfBc9yvEw .error-icon{fill:#552222;}#mermaid-svg-BZ5xOGzRfBc9yvEw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BZ5xOGzRfBc9yvEw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BZ5xOGzRfBc9yvEw .marker.cross{stroke:#333333;}#mermaid-svg-BZ5xOGzRfBc9yvEw svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BZ5xOGzRfBc9yvEw p{margin:0;}#mermaid-svg-BZ5xOGzRfBc9yvEw .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-BZ5xOGzRfBc9yvEw .cluster-label text{fill:#333;}#mermaid-svg-BZ5xOGzRfBc9yvEw .cluster-label span{color:#333;}#mermaid-svg-BZ5xOGzRfBc9yvEw .cluster-label span p{background-color:transparent;}#mermaid-svg-BZ5xOGzRfBc9yvEw .label text,#mermaid-svg-BZ5xOGzRfBc9yvEw span{fill:#333;color:#333;}#mermaid-svg-BZ5xOGzRfBc9yvEw .node rect,#mermaid-svg-BZ5xOGzRfBc9yvEw .node circle,#mermaid-svg-BZ5xOGzRfBc9yvEw .node ellipse,#mermaid-svg-BZ5xOGzRfBc9yvEw .node polygon,#mermaid-svg-BZ5xOGzRfBc9yvEw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BZ5xOGzRfBc9yvEw .rough-node .label text,#mermaid-svg-BZ5xOGzRfBc9yvEw .node .label text,#mermaid-svg-BZ5xOGzRfBc9yvEw .image-shape .label,#mermaid-svg-BZ5xOGzRfBc9yvEw .icon-shape .label{text-anchor:middle;}#mermaid-svg-BZ5xOGzRfBc9yvEw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BZ5xOGzRfBc9yvEw .rough-node .label,#mermaid-svg-BZ5xOGzRfBc9yvEw .node .label,#mermaid-svg-BZ5xOGzRfBc9yvEw .image-shape .label,#mermaid-svg-BZ5xOGzRfBc9yvEw .icon-shape .label{text-align:center;}#mermaid-svg-BZ5xOGzRfBc9yvEw .node.clickable{cursor:pointer;}#mermaid-svg-BZ5xOGzRfBc9yvEw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BZ5xOGzRfBc9yvEw .arrowheadPath{fill:#333333;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BZ5xOGzRfBc9yvEw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BZ5xOGzRfBc9yvEw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BZ5xOGzRfBc9yvEw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BZ5xOGzRfBc9yvEw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BZ5xOGzRfBc9yvEw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BZ5xOGzRfBc9yvEw .cluster text{fill:#333;}#mermaid-svg-BZ5xOGzRfBc9yvEw .cluster span{color:#333;}#mermaid-svg-BZ5xOGzRfBc9yvEw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BZ5xOGzRfBc9yvEw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BZ5xOGzRfBc9yvEw rect.text{fill:none;stroke-width:0;}#mermaid-svg-BZ5xOGzRfBc9yvEw .icon-shape,#mermaid-svg-BZ5xOGzRfBc9yvEw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BZ5xOGzRfBc9yvEw .icon-shape p,#mermaid-svg-BZ5xOGzRfBc9yvEw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BZ5xOGzRfBc9yvEw .icon-shape .label rect,#mermaid-svg-BZ5xOGzRfBc9yvEw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BZ5xOGzRfBc9yvEw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BZ5xOGzRfBc9yvEw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BZ5xOGzRfBc9yvEw :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
传统方式
每个工具写适配代码
工具列表硬编码
API 变更要改代码
MCP 方式
Server 声明工具
Client 运行时发现
Schema 自动生成参数
2.2 两个关键词的定义
- 工具发现(Tool Discovery):Client 在运行时通过 tools/list 获取 Server 当前提供的工具清单(名称、描述、inputSchema)。Agent 不需要在编译期知道有哪些工具。
- 工具调用(Tool Invocation):Agent 依据发现的 schema 构造参数,通过 tools/call 让 Server 执行,并拿到结构化结果。
两者合在一起,构成"先侦察、后行动"的完整闭环——这正是 Agent 区别于传统程序的关键:传统程序调用什么函数是写死的,Agent 调用什么工具是思考后决定的。
2.3 发现与调用的四阶段总览
源文档 6.4 用一张 sequenceDiagram 完整展示了从启动到调用的全过程。我们把它提炼为四阶段:
#mermaid-svg-cBiFnh4gIEe49KJS{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cBiFnh4gIEe49KJS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cBiFnh4gIEe49KJS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cBiFnh4gIEe49KJS .error-icon{fill:#552222;}#mermaid-svg-cBiFnh4gIEe49KJS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cBiFnh4gIEe49KJS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cBiFnh4gIEe49KJS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cBiFnh4gIEe49KJS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cBiFnh4gIEe49KJS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cBiFnh4gIEe49KJS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cBiFnh4gIEe49KJS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cBiFnh4gIEe49KJS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cBiFnh4gIEe49KJS .marker.cross{stroke:#333333;}#mermaid-svg-cBiFnh4gIEe49KJS svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cBiFnh4gIEe49KJS p{margin:0;}#mermaid-svg-cBiFnh4gIEe49KJS .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-cBiFnh4gIEe49KJS .cluster-label text{fill:#333;}#mermaid-svg-cBiFnh4gIEe49KJS .cluster-label span{color:#333;}#mermaid-svg-cBiFnh4gIEe49KJS .cluster-label span p{background-color:transparent;}#mermaid-svg-cBiFnh4gIEe49KJS .label text,#mermaid-svg-cBiFnh4gIEe49KJS span{fill:#333;color:#333;}#mermaid-svg-cBiFnh4gIEe49KJS .node rect,#mermaid-svg-cBiFnh4gIEe49KJS .node circle,#mermaid-svg-cBiFnh4gIEe49KJS .node ellipse,#mermaid-svg-cBiFnh4gIEe49KJS .node polygon,#mermaid-svg-cBiFnh4gIEe49KJS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cBiFnh4gIEe49KJS .rough-node .label text,#mermaid-svg-cBiFnh4gIEe49KJS .node .label text,#mermaid-svg-cBiFnh4gIEe49KJS .image-shape .label,#mermaid-svg-cBiFnh4gIEe49KJS .icon-shape .label{text-anchor:middle;}#mermaid-svg-cBiFnh4gIEe49KJS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cBiFnh4gIEe49KJS .rough-node .label,#mermaid-svg-cBiFnh4gIEe49KJS .node .label,#mermaid-svg-cBiFnh4gIEe49KJS .image-shape .label,#mermaid-svg-cBiFnh4gIEe49KJS .icon-shape .label{text-align:center;}#mermaid-svg-cBiFnh4gIEe49KJS .node.clickable{cursor:pointer;}#mermaid-svg-cBiFnh4gIEe49KJS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cBiFnh4gIEe49KJS .arrowheadPath{fill:#333333;}#mermaid-svg-cBiFnh4gIEe49KJS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cBiFnh4gIEe49KJS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cBiFnh4gIEe49KJS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cBiFnh4gIEe49KJS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cBiFnh4gIEe49KJS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cBiFnh4gIEe49KJS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cBiFnh4gIEe49KJS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cBiFnh4gIEe49KJS .cluster text{fill:#333;}#mermaid-svg-cBiFnh4gIEe49KJS .cluster span{color:#333;}#mermaid-svg-cBiFnh4gIEe49KJS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cBiFnh4gIEe49KJS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cBiFnh4gIEe49KJS rect.text{fill:none;stroke-width:0;}#mermaid-svg-cBiFnh4gIEe49KJS .icon-shape,#mermaid-svg-cBiFnh4gIEe49KJS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cBiFnh4gIEe49KJS .icon-shape p,#mermaid-svg-cBiFnh4gIEe49KJS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cBiFnh4gIEe49KJS .icon-shape .label rect,#mermaid-svg-cBiFnh4gIEe49KJS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cBiFnh4gIEe49KJS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cBiFnh4gIEe49KJS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cBiFnh4gIEe49KJS :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
新工具上线
阶段1 初始化
阶段2 工具发现
阶段3 注册路由
阶段4 工具调用
返回结果
- 阶段 1 初始化:Agent 启动,Client 与每个 Server 建立会话(initialize)。
- 阶段 2 工具发现:Client 向各 Server 发 tools/list,拿回工具清单。
- 阶段 3 注册路由:Client 把"工具名 → Server"的映射写入路由注册表。
- 阶段 4 工具调用:Agent 发起 call_tool,Client 查注册表路由到正确 Server 执行。
2.4 为什么需要路由注册表
一个 Agent 可能同时连 GitHub、Slack、数据库等多个 Server,每个 Server 提供一批工具。如果没有注册表,Client 每次都要遍历所有 Server 找"哪个 Server 有 search_code",代价高且易错。注册表是一张"工具路由表":
#mermaid-svg-AuFmGMIxCzycVPNi{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AuFmGMIxCzycVPNi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AuFmGMIxCzycVPNi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AuFmGMIxCzycVPNi .error-icon{fill:#552222;}#mermaid-svg-AuFmGMIxCzycVPNi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AuFmGMIxCzycVPNi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AuFmGMIxCzycVPNi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AuFmGMIxCzycVPNi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AuFmGMIxCzycVPNi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AuFmGMIxCzycVPNi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AuFmGMIxCzycVPNi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AuFmGMIxCzycVPNi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AuFmGMIxCzycVPNi .marker.cross{stroke:#333333;}#mermaid-svg-AuFmGMIxCzycVPNi svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AuFmGMIxCzycVPNi p{margin:0;}#mermaid-svg-AuFmGMIxCzycVPNi .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-AuFmGMIxCzycVPNi .cluster-label text{fill:#333;}#mermaid-svg-AuFmGMIxCzycVPNi .cluster-label span{color:#333;}#mermaid-svg-AuFmGMIxCzycVPNi .cluster-label span p{background-color:transparent;}#mermaid-svg-AuFmGMIxCzycVPNi .label text,#mermaid-svg-AuFmGMIxCzycVPNi span{fill:#333;color:#333;}#mermaid-svg-AuFmGMIxCzycVPNi .node rect,#mermaid-svg-AuFmGMIxCzycVPNi .node circle,#mermaid-svg-AuFmGMIxCzycVPNi .node ellipse,#mermaid-svg-AuFmGMIxCzycVPNi .node polygon,#mermaid-svg-AuFmGMIxCzycVPNi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AuFmGMIxCzycVPNi .rough-node .label text,#mermaid-svg-AuFmGMIxCzycVPNi .node .label text,#mermaid-svg-AuFmGMIxCzycVPNi .image-shape .label,#mermaid-svg-AuFmGMIxCzycVPNi .icon-shape .label{text-anchor:middle;}#mermaid-svg-AuFmGMIxCzycVPNi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AuFmGMIxCzycVPNi .rough-node .label,#mermaid-svg-AuFmGMIxCzycVPNi .node .label,#mermaid-svg-AuFmGMIxCzycVPNi .image-shape .label,#mermaid-svg-AuFmGMIxCzycVPNi .icon-shape .label{text-align:center;}#mermaid-svg-AuFmGMIxCzycVPNi .node.clickable{cursor:pointer;}#mermaid-svg-AuFmGMIxCzycVPNi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AuFmGMIxCzycVPNi .arrowheadPath{fill:#333333;}#mermaid-svg-AuFmGMIxCzycVPNi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AuFmGMIxCzycVPNi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AuFmGMIxCzycVPNi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AuFmGMIxCzycVPNi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AuFmGMIxCzycVPNi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AuFmGMIxCzycVPNi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AuFmGMIxCzycVPNi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AuFmGMIxCzycVPNi .cluster text{fill:#333;}#mermaid-svg-AuFmGMIxCzycVPNi .cluster span{color:#333;}#mermaid-svg-AuFmGMIxCzycVPNi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AuFmGMIxCzycVPNi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AuFmGMIxCzycVPNi rect.text{fill:none;stroke-width:0;}#mermaid-svg-AuFmGMIxCzycVPNi .icon-shape,#mermaid-svg-AuFmGMIxCzycVPNi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AuFmGMIxCzycVPNi .icon-shape p,#mermaid-svg-AuFmGMIxCzycVPNi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AuFmGMIxCzycVPNi .icon-shape .label rect,#mermaid-svg-AuFmGMIxCzycVPNi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AuFmGMIxCzycVPNi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AuFmGMIxCzycVPNi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AuFmGMIxCzycVPNi :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
路由注册表
search_code → GitHub Server
create_issue → GitHub Server
send_message → Slack Server
list_channels → Slack Server
call_tool search_code
路由到 GitHub Server
2.5 路由表 vs DNS vs 服务发现
可以把路由注册表类比为互联网世界的 DNS:
| 解决什么 | 域名 → IP | 工具名 → Server |
| 查询方式 | 解析请求 | tools/call 前查表 |
| 更新时机 | TTL 过期刷新 | tools/list 重新拉取 |
| 缓存 | 本地 DNS 缓存 | Client 内存缓存 |
2.6 动态发现的三个好处
2.7 一个直觉类比:点菜
把 Agent 想成顾客,MCP Server 想成餐厅:
如果顾客同时点了两家餐厅的外卖,心里得记着"红烧肉来自 A 家、披萨来自 B 家"——这就是路由注册表的作用。
2.8 核心概念速记表
| 会话建立 | 打通与 Server 的通道 | initialize |
| 工具发现 | 获取可用工具清单 | tools/list |
| 路由注册 | 建立工具→Server 映射 | Client 内部 |
| 工具调用 | 让 Server 执行工具 | tools/call |
| 结果返回 | 拿到结构化结果 | tools/call 响应 |
2.10 发现 vs 调用:一次对比
| 方法 | tools/list | tools/call |
| 频率 | 低(缓存+通知) | 高(每次行动) |
| 是否可写 | 只读 | 可读写 |
| 结果 | 工具清单 | 执行结果 |
| 失败影响 | 能力缺失 | 任务失败 |
2.11 硬编码时代的痛苦
假设 Agent 要接 3 个外部系统,每个系统 5 个 API,硬编码时代需要:
- 15 段适配代码。
- 15 份 API 文档的人工研读。
- 每次 API 变更都要改代码 + 回归测试。
- 新增系统 = 重复整套流程。
MCP 时代:一套 Client,Server 声明即插即用。这就是"N×M → N+M"降维在运行时的体现。
2.12 动态发现的"运行时才知道"意味着什么
"运行时才知道有哪些工具"对 Agent 架构有深远影响:
#mermaid-svg-rRs9LNdqwhrBaq2d{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rRs9LNdqwhrBaq2d .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rRs9LNdqwhrBaq2d .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rRs9LNdqwhrBaq2d .error-icon{fill:#552222;}#mermaid-svg-rRs9LNdqwhrBaq2d .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rRs9LNdqwhrBaq2d .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rRs9LNdqwhrBaq2d .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rRs9LNdqwhrBaq2d .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rRs9LNdqwhrBaq2d .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rRs9LNdqwhrBaq2d .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rRs9LNdqwhrBaq2d .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rRs9LNdqwhrBaq2d .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rRs9LNdqwhrBaq2d .marker.cross{stroke:#333333;}#mermaid-svg-rRs9LNdqwhrBaq2d svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rRs9LNdqwhrBaq2d p{margin:0;}#mermaid-svg-rRs9LNdqwhrBaq2d .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-rRs9LNdqwhrBaq2d .cluster-label text{fill:#333;}#mermaid-svg-rRs9LNdqwhrBaq2d .cluster-label span{color:#333;}#mermaid-svg-rRs9LNdqwhrBaq2d .cluster-label span p{background-color:transparent;}#mermaid-svg-rRs9LNdqwhrBaq2d .label text,#mermaid-svg-rRs9LNdqwhrBaq2d span{fill:#333;color:#333;}#mermaid-svg-rRs9LNdqwhrBaq2d .node rect,#mermaid-svg-rRs9LNdqwhrBaq2d .node circle,#mermaid-svg-rRs9LNdqwhrBaq2d .node ellipse,#mermaid-svg-rRs9LNdqwhrBaq2d .node polygon,#mermaid-svg-rRs9LNdqwhrBaq2d .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rRs9LNdqwhrBaq2d .rough-node .label text,#mermaid-svg-rRs9LNdqwhrBaq2d .node .label text,#mermaid-svg-rRs9LNdqwhrBaq2d .image-shape .label,#mermaid-svg-rRs9LNdqwhrBaq2d .icon-shape .label{text-anchor:middle;}#mermaid-svg-rRs9LNdqwhrBaq2d .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rRs9LNdqwhrBaq2d .rough-node .label,#mermaid-svg-rRs9LNdqwhrBaq2d .node .label,#mermaid-svg-rRs9LNdqwhrBaq2d .image-shape .label,#mermaid-svg-rRs9LNdqwhrBaq2d .icon-shape .label{text-align:center;}#mermaid-svg-rRs9LNdqwhrBaq2d .node.clickable{cursor:pointer;}#mermaid-svg-rRs9LNdqwhrBaq2d .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rRs9LNdqwhrBaq2d .arrowheadPath{fill:#333333;}#mermaid-svg-rRs9LNdqwhrBaq2d .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rRs9LNdqwhrBaq2d .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rRs9LNdqwhrBaq2d .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rRs9LNdqwhrBaq2d .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rRs9LNdqwhrBaq2d .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rRs9LNdqwhrBaq2d .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rRs9LNdqwhrBaq2d .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rRs9LNdqwhrBaq2d .cluster text{fill:#333;}#mermaid-svg-rRs9LNdqwhrBaq2d .cluster span{color:#333;}#mermaid-svg-rRs9LNdqwhrBaq2d div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rRs9LNdqwhrBaq2d .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rRs9LNdqwhrBaq2d rect.text{fill:none;stroke-width:0;}#mermaid-svg-rRs9LNdqwhrBaq2d .icon-shape,#mermaid-svg-rRs9LNdqwhrBaq2d .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rRs9LNdqwhrBaq2d .icon-shape p,#mermaid-svg-rRs9LNdqwhrBaq2d .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rRs9LNdqwhrBaq2d .icon-shape .label rect,#mermaid-svg-rRs9LNdqwhrBaq2d .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rRs9LNdqwhrBaq2d .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rRs9LNdqwhrBaq2d .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rRs9LNdqwhrBaq2d :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Server 配置
动态发现
能力地图
Agent 提示词
Agent 行为
2.13 点菜类比的完整版
把"点菜"类比展开成一张映射表:
| 扫码看菜单 | tools/list | 发现 |
| 记住哪家有什么 | 路由注册表 | 注册 |
| 看菜看配料 | inputSchema | 协商 |
| 下单 | tools/call | 调用 |
| 后厨出菜 | Server 执行 | 执行 |
| 上菜 | 返回结果 | 反馈 |
| 菜品下架 | list_changed 通知 | 变更 |
2.14 发现与调用的循环关系
发现不是一次性的,它与调用构成持续循环:
#mermaid-svg-xyXxZr45FeOsD4YS{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xyXxZr45FeOsD4YS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xyXxZr45FeOsD4YS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xyXxZr45FeOsD4YS .error-icon{fill:#552222;}#mermaid-svg-xyXxZr45FeOsD4YS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xyXxZr45FeOsD4YS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xyXxZr45FeOsD4YS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xyXxZr45FeOsD4YS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xyXxZr45FeOsD4YS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xyXxZr45FeOsD4YS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xyXxZr45FeOsD4YS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xyXxZr45FeOsD4YS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xyXxZr45FeOsD4YS .marker.cross{stroke:#333333;}#mermaid-svg-xyXxZr45FeOsD4YS svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xyXxZr45FeOsD4YS p{margin:0;}#mermaid-svg-xyXxZr45FeOsD4YS .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-xyXxZr45FeOsD4YS .cluster-label text{fill:#333;}#mermaid-svg-xyXxZr45FeOsD4YS .cluster-label span{color:#333;}#mermaid-svg-xyXxZr45FeOsD4YS .cluster-label span p{background-color:transparent;}#mermaid-svg-xyXxZr45FeOsD4YS .label text,#mermaid-svg-xyXxZr45FeOsD4YS span{fill:#333;color:#333;}#mermaid-svg-xyXxZr45FeOsD4YS .node rect,#mermaid-svg-xyXxZr45FeOsD4YS .node circle,#mermaid-svg-xyXxZr45FeOsD4YS .node ellipse,#mermaid-svg-xyXxZr45FeOsD4YS .node polygon,#mermaid-svg-xyXxZr45FeOsD4YS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xyXxZr45FeOsD4YS .rough-node .label text,#mermaid-svg-xyXxZr45FeOsD4YS .node .label text,#mermaid-svg-xyXxZr45FeOsD4YS .image-shape .label,#mermaid-svg-xyXxZr45FeOsD4YS .icon-shape .label{text-anchor:middle;}#mermaid-svg-xyXxZr45FeOsD4YS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xyXxZr45FeOsD4YS .rough-node .label,#mermaid-svg-xyXxZr45FeOsD4YS .node .label,#mermaid-svg-xyXxZr45FeOsD4YS .image-shape .label,#mermaid-svg-xyXxZr45FeOsD4YS .icon-shape .label{text-align:center;}#mermaid-svg-xyXxZr45FeOsD4YS .node.clickable{cursor:pointer;}#mermaid-svg-xyXxZr45FeOsD4YS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xyXxZr45FeOsD4YS .arrowheadPath{fill:#333333;}#mermaid-svg-xyXxZr45FeOsD4YS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xyXxZr45FeOsD4YS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xyXxZr45FeOsD4YS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xyXxZr45FeOsD4YS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xyXxZr45FeOsD4YS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xyXxZr45FeOsD4YS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xyXxZr45FeOsD4YS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xyXxZr45FeOsD4YS .cluster text{fill:#333;}#mermaid-svg-xyXxZr45FeOsD4YS .cluster span{color:#333;}#mermaid-svg-xyXxZr45FeOsD4YS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xyXxZr45FeOsD4YS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xyXxZr45FeOsD4YS rect.text{fill:none;stroke-width:0;}#mermaid-svg-xyXxZr45FeOsD4YS .icon-shape,#mermaid-svg-xyXxZr45FeOsD4YS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xyXxZr45FeOsD4YS .icon-shape p,#mermaid-svg-xyXxZr45FeOsD4YS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xyXxZr45FeOsD4YS .icon-shape .label rect,#mermaid-svg-xyXxZr45FeOsD4YS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xyXxZr45FeOsD4YS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xyXxZr45FeOsD4YS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xyXxZr45FeOsD4YS :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
新需求
发现工具
注册
调用
成功
失败-工具不存在
任务完成
2.15 核心概念总结图
#mermaid-svg-Z0cYnlJo7DIilFRn{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Z0cYnlJo7DIilFRn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Z0cYnlJo7DIilFRn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Z0cYnlJo7DIilFRn .error-icon{fill:#552222;}#mermaid-svg-Z0cYnlJo7DIilFRn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Z0cYnlJo7DIilFRn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Z0cYnlJo7DIilFRn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Z0cYnlJo7DIilFRn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Z0cYnlJo7DIilFRn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Z0cYnlJo7DIilFRn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Z0cYnlJo7DIilFRn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Z0cYnlJo7DIilFRn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Z0cYnlJo7DIilFRn .marker.cross{stroke:#333333;}#mermaid-svg-Z0cYnlJo7DIilFRn svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Z0cYnlJo7DIilFRn p{margin:0;}#mermaid-svg-Z0cYnlJo7DIilFRn .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Z0cYnlJo7DIilFRn .cluster-label text{fill:#333;}#mermaid-svg-Z0cYnlJo7DIilFRn .cluster-label span{color:#333;}#mermaid-svg-Z0cYnlJo7DIilFRn .cluster-label span p{background-color:transparent;}#mermaid-svg-Z0cYnlJo7DIilFRn .label text,#mermaid-svg-Z0cYnlJo7DIilFRn span{fill:#333;color:#333;}#mermaid-svg-Z0cYnlJo7DIilFRn .node rect,#mermaid-svg-Z0cYnlJo7DIilFRn .node circle,#mermaid-svg-Z0cYnlJo7DIilFRn .node ellipse,#mermaid-svg-Z0cYnlJo7DIilFRn .node polygon,#mermaid-svg-Z0cYnlJo7DIilFRn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Z0cYnlJo7DIilFRn .rough-node .label text,#mermaid-svg-Z0cYnlJo7DIilFRn .node .label text,#mermaid-svg-Z0cYnlJo7DIilFRn .image-shape .label,#mermaid-svg-Z0cYnlJo7DIilFRn .icon-shape .label{text-anchor:middle;}#mermaid-svg-Z0cYnlJo7DIilFRn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Z0cYnlJo7DIilFRn .rough-node .label,#mermaid-svg-Z0cYnlJo7DIilFRn .node .label,#mermaid-svg-Z0cYnlJo7DIilFRn .image-shape .label,#mermaid-svg-Z0cYnlJo7DIilFRn .icon-shape .label{text-align:center;}#mermaid-svg-Z0cYnlJo7DIilFRn .node.clickable{cursor:pointer;}#mermaid-svg-Z0cYnlJo7DIilFRn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Z0cYnlJo7DIilFRn .arrowheadPath{fill:#333333;}#mermaid-svg-Z0cYnlJo7DIilFRn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Z0cYnlJo7DIilFRn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Z0cYnlJo7DIilFRn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Z0cYnlJo7DIilFRn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Z0cYnlJo7DIilFRn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Z0cYnlJo7DIilFRn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Z0cYnlJo7DIilFRn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Z0cYnlJo7DIilFRn .cluster text{fill:#333;}#mermaid-svg-Z0cYnlJo7DIilFRn .cluster span{color:#333;}#mermaid-svg-Z0cYnlJo7DIilFRn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Z0cYnlJo7DIilFRn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Z0cYnlJo7DIilFRn rect.text{fill:none;stroke-width:0;}#mermaid-svg-Z0cYnlJo7DIilFRn .icon-shape,#mermaid-svg-Z0cYnlJo7DIilFRn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Z0cYnlJo7DIilFRn .icon-shape p,#mermaid-svg-Z0cYnlJo7DIilFRn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Z0cYnlJo7DIilFRn .icon-shape .label rect,#mermaid-svg-Z0cYnlJo7DIilFRn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Z0cYnlJo7DIilFRn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Z0cYnlJo7DIilFRn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Z0cYnlJo7DIilFRn :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
本篇运行时
协议定义 26篇
methods: list/call
原语: Tools
initialize 建会话
tools/list 发现
注册表 路由
tools/call 调用
2.17 工具调用链路的全景图
把本篇所有概念放进一张图:
#mermaid-svg-tMF4hEDJQPT0MvrD{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tMF4hEDJQPT0MvrD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tMF4hEDJQPT0MvrD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tMF4hEDJQPT0MvrD .error-icon{fill:#552222;}#mermaid-svg-tMF4hEDJQPT0MvrD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tMF4hEDJQPT0MvrD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tMF4hEDJQPT0MvrD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tMF4hEDJQPT0MvrD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tMF4hEDJQPT0MvrD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tMF4hEDJQPT0MvrD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tMF4hEDJQPT0MvrD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tMF4hEDJQPT0MvrD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tMF4hEDJQPT0MvrD .marker.cross{stroke:#333333;}#mermaid-svg-tMF4hEDJQPT0MvrD svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tMF4hEDJQPT0MvrD p{margin:0;}#mermaid-svg-tMF4hEDJQPT0MvrD .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-tMF4hEDJQPT0MvrD .cluster-label text{fill:#333;}#mermaid-svg-tMF4hEDJQPT0MvrD .cluster-label span{color:#333;}#mermaid-svg-tMF4hEDJQPT0MvrD .cluster-label span p{background-color:transparent;}#mermaid-svg-tMF4hEDJQPT0MvrD .label text,#mermaid-svg-tMF4hEDJQPT0MvrD span{fill:#333;color:#333;}#mermaid-svg-tMF4hEDJQPT0MvrD .node rect,#mermaid-svg-tMF4hEDJQPT0MvrD .node circle,#mermaid-svg-tMF4hEDJQPT0MvrD .node ellipse,#mermaid-svg-tMF4hEDJQPT0MvrD .node polygon,#mermaid-svg-tMF4hEDJQPT0MvrD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tMF4hEDJQPT0MvrD .rough-node .label text,#mermaid-svg-tMF4hEDJQPT0MvrD .node .label text,#mermaid-svg-tMF4hEDJQPT0MvrD .image-shape .label,#mermaid-svg-tMF4hEDJQPT0MvrD .icon-shape .label{text-anchor:middle;}#mermaid-svg-tMF4hEDJQPT0MvrD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tMF4hEDJQPT0MvrD .rough-node .label,#mermaid-svg-tMF4hEDJQPT0MvrD .node .label,#mermaid-svg-tMF4hEDJQPT0MvrD .image-shape .label,#mermaid-svg-tMF4hEDJQPT0MvrD .icon-shape .label{text-align:center;}#mermaid-svg-tMF4hEDJQPT0MvrD .node.clickable{cursor:pointer;}#mermaid-svg-tMF4hEDJQPT0MvrD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tMF4hEDJQPT0MvrD .arrowheadPath{fill:#333333;}#mermaid-svg-tMF4hEDJQPT0MvrD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tMF4hEDJQPT0MvrD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tMF4hEDJQPT0MvrD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tMF4hEDJQPT0MvrD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tMF4hEDJQPT0MvrD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tMF4hEDJQPT0MvrD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tMF4hEDJQPT0MvrD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tMF4hEDJQPT0MvrD .cluster text{fill:#333;}#mermaid-svg-tMF4hEDJQPT0MvrD .cluster span{color:#333;}#mermaid-svg-tMF4hEDJQPT0MvrD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tMF4hEDJQPT0MvrD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tMF4hEDJQPT0MvrD rect.text{fill:none;stroke-width:0;}#mermaid-svg-tMF4hEDJQPT0MvrD .icon-shape,#mermaid-svg-tMF4hEDJQPT0MvrD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tMF4hEDJQPT0MvrD .icon-shape p,#mermaid-svg-tMF4hEDJQPT0MvrD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tMF4hEDJQPT0MvrD .icon-shape .label rect,#mermaid-svg-tMF4hEDJQPT0MvrD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tMF4hEDJQPT0MvrD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tMF4hEDJQPT0MvrD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tMF4hEDJQPT0MvrD :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Agent
Client
注册表
校验器
限流器
审计
Server A
Server B
结果处理
2.18 本章小结(终版)
发现与调用是 Agent 工具能力的"两条腿":发现解决"有什么可用",调用解决"怎么用起来"。路由注册表把多 Server 的复杂拓扑收敛为一张可查询的表,让 Agent 的调用从"遍历猜"变成"查表直达"。配套校验、限流、审计、结果处理,构成完整的调用链路。
第 3 章 四阶段流程全景
3.1 源文档时序图
源文档 6.4 给出完整时序图,本篇第 3 章先原样承接并逐段解读,第 4–7 章再分别深拆。
Slack MCP ServerGitHub MCP Server路由注册表MCP ClientAgent认知层Slack MCP ServerGitHub MCP Server路由注册表MCP ClientAgent认知层#mermaid-svg-x554nxnwWeqOZo8t{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-x554nxnwWeqOZo8t .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-x554nxnwWeqOZo8t .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-x554nxnwWeqOZo8t .error-icon{fill:#552222;}#mermaid-svg-x554nxnwWeqOZo8t .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-x554nxnwWeqOZo8t .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-x554nxnwWeqOZo8t .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-x554nxnwWeqOZo8t .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-x554nxnwWeqOZo8t .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-x554nxnwWeqOZo8t .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-x554nxnwWeqOZo8t .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-x554nxnwWeqOZo8t .marker{fill:#333333;stroke:#333333;}#mermaid-svg-x554nxnwWeqOZo8t .marker.cross{stroke:#333333;}#mermaid-svg-x554nxnwWeqOZo8t svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-x554nxnwWeqOZo8t p{margin:0;}#mermaid-svg-x554nxnwWeqOZo8t .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-x554nxnwWeqOZo8t text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-x554nxnwWeqOZo8t .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-x554nxnwWeqOZo8t .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-x554nxnwWeqOZo8t .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-x554nxnwWeqOZo8t .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-x554nxnwWeqOZo8t #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-x554nxnwWeqOZo8t .sequenceNumber{fill:white;}#mermaid-svg-x554nxnwWeqOZo8t #sequencenumber{fill:#333;}#mermaid-svg-x554nxnwWeqOZo8t #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-x554nxnwWeqOZo8t .messageText{fill:#333;stroke:none;}#mermaid-svg-x554nxnwWeqOZo8t .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-x554nxnwWeqOZo8t .labelText,#mermaid-svg-x554nxnwWeqOZo8t .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-x554nxnwWeqOZo8t .loopText,#mermaid-svg-x554nxnwWeqOZo8t .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-x554nxnwWeqOZo8t .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-x554nxnwWeqOZo8t .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-x554nxnwWeqOZo8t .noteText,#mermaid-svg-x554nxnwWeqOZo8t .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-x554nxnwWeqOZo8t .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-x554nxnwWeqOZo8t .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-x554nxnwWeqOZo8t .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-x554nxnwWeqOZo8t .actorPopupMenu{position:absolute;}#mermaid-svg-x554nxnwWeqOZo8t .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-x554nxnwWeqOZo8t .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-x554nxnwWeqOZo8t .actor-man circle,#mermaid-svg-x554nxnwWeqOZo8t line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-x554nxnwWeqOZo8t :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}阶段1:初始化阶段2:工具发现search_code → ServerAcreate_issue → ServerAsend_message → ServerB阶段3:工具调用执行GitHub API搜索阶段4:工具调用(另一个工具)启动,需要连接工具initialize()支持tools, resources, promptsinitialize()支持tools, resourcestools/list()[search_code, create_issue, list_prs, …]tools/list()[send_message, list_channels, …]注册工具路由表call_tool("search_code", {query:"auth", repo:"myrepo"})查找search_code → ServerAServerAtools/call("search_code", {query:"auth", repo:"myrepo"})结果:找到5个匹配文件返回搜索结果call_tool("send_message", {channel:"查找send_message → ServerBtools/call("send_message", {…})消息已发送返回发送结果
3.2 阶段 1:初始化——建会话
Agent 启动后,第一件事是向每个要连接的 Server 发起 initialize:
- Client → ServerA:initialize()。
- ServerA 回:支持 tools, resources, prompts(能力声明)。
- Client → ServerB:initialize()。
- ServerB 回:支持 tools, resources(注意:ServerB 没有声明 prompts)。
关键点:每个 Server 的能力集可能不同。Client 在初始化阶段就知道"哪个 Server 能干什么",为后续路由提供依据。
3.3 阶段 2:工具发现——拉清单
初始化完成后,Client 逐个向 Server 发 tools/list:
- ServerA 返回:[search_code, create_issue, list_prs, …]。
- ServerB 返回:[send_message, list_channels, …]。
发现结果不只是名字,还包括每个工具的 description 与 inputSchema——这是 Agent 后续"会正确调用"的前提。
3.4 阶段 3:注册路由——建表
Client 把发现结果写入路由注册表:
- search_code → ServerA
- create_issue → ServerA
- send_message → ServerB
从此以后,Client 看到 call_tool("search_code", …) 就知道该找 ServerA,无需再遍历。
3.5 阶段 4:工具调用——执行
Agent 发起调用:
再调 send_message 时走同一路径,但路由到 ServerB。
3.6 四阶段的时序特征
#mermaid-svg-FSNIzXDAFbsjiQMh{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FSNIzXDAFbsjiQMh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FSNIzXDAFbsjiQMh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FSNIzXDAFbsjiQMh .error-icon{fill:#552222;}#mermaid-svg-FSNIzXDAFbsjiQMh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FSNIzXDAFbsjiQMh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FSNIzXDAFbsjiQMh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FSNIzXDAFbsjiQMh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FSNIzXDAFbsjiQMh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FSNIzXDAFbsjiQMh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FSNIzXDAFbsjiQMh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FSNIzXDAFbsjiQMh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FSNIzXDAFbsjiQMh .marker.cross{stroke:#333333;}#mermaid-svg-FSNIzXDAFbsjiQMh svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FSNIzXDAFbsjiQMh p{margin:0;}#mermaid-svg-FSNIzXDAFbsjiQMh defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-FSNIzXDAFbsjiQMh g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-FSNIzXDAFbsjiQMh g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-FSNIzXDAFbsjiQMh g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-FSNIzXDAFbsjiQMh g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-FSNIzXDAFbsjiQMh g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-FSNIzXDAFbsjiQMh .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-FSNIzXDAFbsjiQMh .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-FSNIzXDAFbsjiQMh .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-FSNIzXDAFbsjiQMh .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-FSNIzXDAFbsjiQMh .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-FSNIzXDAFbsjiQMh .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-FSNIzXDAFbsjiQMh .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-FSNIzXDAFbsjiQMh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FSNIzXDAFbsjiQMh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FSNIzXDAFbsjiQMh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FSNIzXDAFbsjiQMh .edgeLabel .label text{fill:#333;}#mermaid-svg-FSNIzXDAFbsjiQMh .label div .edgeLabel{color:#333;}#mermaid-svg-FSNIzXDAFbsjiQMh .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-FSNIzXDAFbsjiQMh .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-FSNIzXDAFbsjiQMh .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-FSNIzXDAFbsjiQMh .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-FSNIzXDAFbsjiQMh .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-FSNIzXDAFbsjiQMh .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FSNIzXDAFbsjiQMh .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FSNIzXDAFbsjiQMh #statediagram-barbEnd{fill:#333333;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FSNIzXDAFbsjiQMh .cluster-label,#mermaid-svg-FSNIzXDAFbsjiQMh .nodeLabel{color:#131300;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-FSNIzXDAFbsjiQMh .note-edge{stroke-dasharray:5;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-note text{fill:black;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram-note .nodeLabel{color:black;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagram .edgeLabel{color:red;}#mermaid-svg-FSNIzXDAFbsjiQMh #dependencyStart,#mermaid-svg-FSNIzXDAFbsjiQMh #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-FSNIzXDAFbsjiQMh .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FSNIzXDAFbsjiQMh :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
initialize 成功
tools/list 返回
注册表就绪
新工具上线需重新发现
会话关闭
初始化
发现
注册
调用
3.7 四阶段各自的失败点
| 初始化 | Server 不支持协议版本 | 无法建会话 |
| 发现 | tools/list 超时 | 工具清单不全 |
| 注册 | 工具名冲突 | 路由错乱 |
| 调用 | 参数不符合 schema | 调用失败 |
3.8 阶段耗时参考
| 初始化 | 50–200ms/Server | 并行 initialize |
| 发现 | 10–50ms/Server | 缓存清单 |
| 注册 | <1ms | 哈希表 |
| 调用 | 取决于 Server | 异步/批处理 |
3.9 四阶段全景速记
初始化建通道、发现拉清单、注册建路由、调用做执行——发现一次、调用多次是常态:Agent 启动时完成 1–3 阶段,运行中反复执行第 4 阶段。
3.11 阶段 1 深挖:初始化做了什么
initialize 不只是"打个招呼",它在交换三样东西:
ServerClientServerClient#mermaid-svg-NyAqQVUMHr9tTc0b{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NyAqQVUMHr9tTc0b .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NyAqQVUMHr9tTc0b .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NyAqQVUMHr9tTc0b .error-icon{fill:#552222;}#mermaid-svg-NyAqQVUMHr9tTc0b .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NyAqQVUMHr9tTc0b .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NyAqQVUMHr9tTc0b .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NyAqQVUMHr9tTc0b .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NyAqQVUMHr9tTc0b .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NyAqQVUMHr9tTc0b .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NyAqQVUMHr9tTc0b .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NyAqQVUMHr9tTc0b .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NyAqQVUMHr9tTc0b .marker.cross{stroke:#333333;}#mermaid-svg-NyAqQVUMHr9tTc0b svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NyAqQVUMHr9tTc0b p{margin:0;}#mermaid-svg-NyAqQVUMHr9tTc0b .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-NyAqQVUMHr9tTc0b text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-NyAqQVUMHr9tTc0b .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-NyAqQVUMHr9tTc0b .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-NyAqQVUMHr9tTc0b .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-NyAqQVUMHr9tTc0b .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-NyAqQVUMHr9tTc0b #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-NyAqQVUMHr9tTc0b .sequenceNumber{fill:white;}#mermaid-svg-NyAqQVUMHr9tTc0b #sequencenumber{fill:#333;}#mermaid-svg-NyAqQVUMHr9tTc0b #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-NyAqQVUMHr9tTc0b .messageText{fill:#333;stroke:none;}#mermaid-svg-NyAqQVUMHr9tTc0b .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-NyAqQVUMHr9tTc0b .labelText,#mermaid-svg-NyAqQVUMHr9tTc0b .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-NyAqQVUMHr9tTc0b .loopText,#mermaid-svg-NyAqQVUMHr9tTc0b .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-NyAqQVUMHr9tTc0b .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-NyAqQVUMHr9tTc0b .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-NyAqQVUMHr9tTc0b .noteText,#mermaid-svg-NyAqQVUMHr9tTc0b .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-NyAqQVUMHr9tTc0b .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-NyAqQVUMHr9tTc0b .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-NyAqQVUMHr9tTc0b .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-NyAqQVUMHr9tTc0b .actorPopupMenu{position:absolute;}#mermaid-svg-NyAqQVUMHr9tTc0b .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-NyAqQVUMHr9tTc0b .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-NyAqQVUMHr9tTc0b .actor-man circle,#mermaid-svg-NyAqQVUMHr9tTc0b line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-NyAqQVUMHr9tTc0b :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}会话进入就绪态initialize(protocolVersion, capabilities, clientInfo)InitializeResult(protocolVersion, capabilities, serverInfo)notifications/initialized
3.12 阶段 1 深挖:能力差异的意义
源时序图中 ServerA 声明了 prompts、ServerB 没有——这个细节很重要:
- Client 会为 ServerA 开放 prompts 相关能力(prompts/list、prompts/get)。
- 对 ServerB,Client 不会展示"模板调用"这类功能,避免 Agent 误用。
能力协商的本质是避免协议双方互相假设:一切以声明为准。
3.13 阶段 1 深挖:多个 Server 并行初始化
多 Server 场景下,初始化应并行而非串行:
#mermaid-svg-mXjNPB1QoVVxVxjX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mXjNPB1QoVVxVxjX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mXjNPB1QoVVxVxjX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mXjNPB1QoVVxVxjX .error-icon{fill:#552222;}#mermaid-svg-mXjNPB1QoVVxVxjX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mXjNPB1QoVVxVxjX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mXjNPB1QoVVxVxjX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mXjNPB1QoVVxVxjX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mXjNPB1QoVVxVxjX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mXjNPB1QoVVxVxjX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mXjNPB1QoVVxVxjX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mXjNPB1QoVVxVxjX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mXjNPB1QoVVxVxjX .marker.cross{stroke:#333333;}#mermaid-svg-mXjNPB1QoVVxVxjX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mXjNPB1QoVVxVxjX p{margin:0;}#mermaid-svg-mXjNPB1QoVVxVxjX .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-mXjNPB1QoVVxVxjX .cluster-label text{fill:#333;}#mermaid-svg-mXjNPB1QoVVxVxjX .cluster-label span{color:#333;}#mermaid-svg-mXjNPB1QoVVxVxjX .cluster-label span p{background-color:transparent;}#mermaid-svg-mXjNPB1QoVVxVxjX .label text,#mermaid-svg-mXjNPB1QoVVxVxjX span{fill:#333;color:#333;}#mermaid-svg-mXjNPB1QoVVxVxjX .node rect,#mermaid-svg-mXjNPB1QoVVxVxjX .node circle,#mermaid-svg-mXjNPB1QoVVxVxjX .node ellipse,#mermaid-svg-mXjNPB1QoVVxVxjX .node polygon,#mermaid-svg-mXjNPB1QoVVxVxjX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mXjNPB1QoVVxVxjX .rough-node .label text,#mermaid-svg-mXjNPB1QoVVxVxjX .node .label text,#mermaid-svg-mXjNPB1QoVVxVxjX .image-shape .label,#mermaid-svg-mXjNPB1QoVVxVxjX .icon-shape .label{text-anchor:middle;}#mermaid-svg-mXjNPB1QoVVxVxjX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mXjNPB1QoVVxVxjX .rough-node .label,#mermaid-svg-mXjNPB1QoVVxVxjX .node .label,#mermaid-svg-mXjNPB1QoVVxVxjX .image-shape .label,#mermaid-svg-mXjNPB1QoVVxVxjX .icon-shape .label{text-align:center;}#mermaid-svg-mXjNPB1QoVVxVxjX .node.clickable{cursor:pointer;}#mermaid-svg-mXjNPB1QoVVxVxjX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mXjNPB1QoVVxVxjX .arrowheadPath{fill:#333333;}#mermaid-svg-mXjNPB1QoVVxVxjX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mXjNPB1QoVVxVxjX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mXjNPB1QoVVxVxjX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mXjNPB1QoVVxVxjX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mXjNPB1QoVVxVxjX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mXjNPB1QoVVxVxjX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mXjNPB1QoVVxVxjX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mXjNPB1QoVVxVxjX .cluster text{fill:#333;}#mermaid-svg-mXjNPB1QoVVxVxjX .cluster span{color:#333;}#mermaid-svg-mXjNPB1QoVVxVxjX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mXjNPB1QoVVxVxjX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mXjNPB1QoVVxVxjX rect.text{fill:none;stroke-width:0;}#mermaid-svg-mXjNPB1QoVVxVxjX .icon-shape,#mermaid-svg-mXjNPB1QoVVxVxjX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mXjNPB1QoVVxVxjX .icon-shape p,#mermaid-svg-mXjNPB1QoVVxVxjX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mXjNPB1QoVVxVxjX .icon-shape .label rect,#mermaid-svg-mXjNPB1QoVVxVxjX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mXjNPB1QoVVxVxjX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mXjNPB1QoVVxVxjX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mXjNPB1QoVVxVxjX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Agent 启动
并行 initialize
GitHub 就绪
Slack 就绪
数据库就绪
全部就绪
并行可把"3 × 100ms"压到"约 100ms"。但注意:部分 Server 初始化失败不应阻断整体启动,失败者标记降级即可。
3.14 阶段 1 深挖:初始化失败的处理
| 版本不兼容 | 提示升级 Client 或 Server |
| 认证失败 | 引导重新授权 |
| Server 不存在 | 从连接清单移除并告警 |
| 网络不可达 | 标记离线,定时重试 |
3.15 阶段 2 深挖:发现的内容不止名字
tools/list 返回的每个工具都带完整元信息,Agent 的"认知"依赖这些元信息:
- name:调用标识。
- description:用途说明,是 Agent 选型依据。
- inputSchema:参数结构,是 Agent 填参依据。
- outputSchema(可选):返回结构,帮助 Agent 预判结果。
- annotations(可选):危险程度、只读性等标注。
3.16 阶段 2 深挖:发现结果如何变成 Agent 的"能力地图"
Agent 看到发现结果后,会把它折叠进自己的提示词/上下文:“当前可用工具:GitHub 提供 search_code、create_issue……;Slack 提供 send_message……”。这就是 Agent"知道自己会什么"的来源——没有发现,Agent 就是"无手之人"。
3.17 阶段 2 深挖:发现的频率控制
| 启动一次 | 工具基本不变 | 可能错过变更 |
| 定时刷新 | 工具会变化 | 额外请求 |
| 通知驱动 | 支持变更通知的 Server | 最省 |
| 失败触发 | 调用报不存在 | 被动兜底 |
3.18 阶段 3 深挖:注册表与"会话"的绑定
路由注册表的值里为什么必须带会话句柄?因为同一 Server 可能被同一个 Client 以多个身份/权限建了多个会话:
search_code → {server: GitHub, session: admin-s1}
search_code → {server: GitHub, session: guest-s2}
Agent 用什么身份说话,就路由到哪个会话——注册表是"工具 + 身份"的复合路由。
3.19 阶段 3 深挖:注册时机与原子性
注册应保证原子性:要么全部工具注册成功,要么回滚。避免出现"注册了一半,Agent 查表发现工具不完整"的中间态。实践上:先构建完整映射,再一次性替换旧表。
3.20 阶段 4 深挖:Agent 如何决定"调哪个工具"
Agent 不是随机选工具,而是依据任务与工具描述做匹配:
这就是"能力协商"的完整闭环——描述写得越好,匹配越准。
3.21 阶段 4 深挖:一次调用的完整生命周期
#mermaid-svg-3FsNswZOiHI6wkv8{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3FsNswZOiHI6wkv8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3FsNswZOiHI6wkv8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3FsNswZOiHI6wkv8 .error-icon{fill:#552222;}#mermaid-svg-3FsNswZOiHI6wkv8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3FsNswZOiHI6wkv8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3FsNswZOiHI6wkv8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3FsNswZOiHI6wkv8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3FsNswZOiHI6wkv8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3FsNswZOiHI6wkv8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3FsNswZOiHI6wkv8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3FsNswZOiHI6wkv8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3FsNswZOiHI6wkv8 .marker.cross{stroke:#333333;}#mermaid-svg-3FsNswZOiHI6wkv8 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3FsNswZOiHI6wkv8 p{margin:0;}#mermaid-svg-3FsNswZOiHI6wkv8 defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-3FsNswZOiHI6wkv8 g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-3FsNswZOiHI6wkv8 g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-3FsNswZOiHI6wkv8 g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-3FsNswZOiHI6wkv8 g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-3FsNswZOiHI6wkv8 g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-3FsNswZOiHI6wkv8 .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-3FsNswZOiHI6wkv8 .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-3FsNswZOiHI6wkv8 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-3FsNswZOiHI6wkv8 .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-3FsNswZOiHI6wkv8 .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-3FsNswZOiHI6wkv8 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-3FsNswZOiHI6wkv8 .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-3FsNswZOiHI6wkv8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3FsNswZOiHI6wkv8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3FsNswZOiHI6wkv8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3FsNswZOiHI6wkv8 .edgeLabel .label text{fill:#333;}#mermaid-svg-3FsNswZOiHI6wkv8 .label div .edgeLabel{color:#333;}#mermaid-svg-3FsNswZOiHI6wkv8 .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-3FsNswZOiHI6wkv8 .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-3FsNswZOiHI6wkv8 .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-3FsNswZOiHI6wkv8 .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-3FsNswZOiHI6wkv8 .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-3FsNswZOiHI6wkv8 .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3FsNswZOiHI6wkv8 .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3FsNswZOiHI6wkv8 #statediagram-barbEnd{fill:#333333;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3FsNswZOiHI6wkv8 .cluster-label,#mermaid-svg-3FsNswZOiHI6wkv8 .nodeLabel{color:#131300;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-3FsNswZOiHI6wkv8 .note-edge{stroke-dasharray:5;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-note text{fill:black;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram-note .nodeLabel{color:black;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagram .edgeLabel{color:red;}#mermaid-svg-3FsNswZOiHI6wkv8 #dependencyStart,#mermaid-svg-3FsNswZOiHI6wkv8 #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-3FsNswZOiHI6wkv8 .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3FsNswZOiHI6wkv8 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
合法
不合法
返回
超时
构造参数
本地校验
查注册表
修正参数
转发Server
等待结果
处理结果
超时处理
重试或放弃
3.22 阶段 4 深挖:结果回传的两种形态
Agent 依据结果类型决定下一步:文本 → 融入推理;结构化 → 可计算;资源引用 → 二次读取。
3.23 四阶段与"思考-行动"闭环的映射
把四阶段映射到 Agent 的宏观闭环(感知-思考-行动-反馈):
| 思考 | 工具选择 | Agent 决定用什么工具 |
| 行动 | 调用 | tools/call 执行 |
| 反馈 | 结果处理 | 结果回流推理 |
| 感知 | 发现 | 工具清单即"环境感知" |
3.24 四阶段的性能预算
一次典型调用(本地 stdio Server)的总延迟构成:
- 初始化(仅首次):50–200ms。
- 查注册表:<1ms。
- 参数校验:<1ms。
- 网络/进程通信:1–5ms。
- Server 执行:取决于业务(1ms 到分钟级)。
- 结果序列化:<1ms。
优化杠杆在 Server 执行本身,协议层的开销已经很小。
3.25 四阶段的常见误区
| 每次调用都重新发现 | 发现一次,缓存 + 通知驱动刷新 |
| 注册表是永久不变的 | 工具会变,需失效机制 |
| initialize 只是握手 | 它还在交换能力与版本 |
| 参数不校验直接转发 | 校验前置,失败本地拦截 |
3.27 阶段 1 进阶:初始化与认证
远程 Server 的 initialize 往往伴随认证:
ServerClientServerClient#mermaid-svg-PWINVUFGUehv90oL{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PWINVUFGUehv90oL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PWINVUFGUehv90oL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PWINVUFGUehv90oL .error-icon{fill:#552222;}#mermaid-svg-PWINVUFGUehv90oL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PWINVUFGUehv90oL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PWINVUFGUehv90oL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PWINVUFGUehv90oL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PWINVUFGUehv90oL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PWINVUFGUehv90oL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PWINVUFGUehv90oL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PWINVUFGUehv90oL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PWINVUFGUehv90oL .marker.cross{stroke:#333333;}#mermaid-svg-PWINVUFGUehv90oL svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PWINVUFGUehv90oL p{margin:0;}#mermaid-svg-PWINVUFGUehv90oL .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PWINVUFGUehv90oL text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-PWINVUFGUehv90oL .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PWINVUFGUehv90oL .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-PWINVUFGUehv90oL .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-PWINVUFGUehv90oL .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-PWINVUFGUehv90oL #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-PWINVUFGUehv90oL .sequenceNumber{fill:white;}#mermaid-svg-PWINVUFGUehv90oL #sequencenumber{fill:#333;}#mermaid-svg-PWINVUFGUehv90oL #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-PWINVUFGUehv90oL .messageText{fill:#333;stroke:none;}#mermaid-svg-PWINVUFGUehv90oL .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PWINVUFGUehv90oL .labelText,#mermaid-svg-PWINVUFGUehv90oL .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-PWINVUFGUehv90oL .loopText,#mermaid-svg-PWINVUFGUehv90oL .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-PWINVUFGUehv90oL .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PWINVUFGUehv90oL .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-PWINVUFGUehv90oL .noteText,#mermaid-svg-PWINVUFGUehv90oL .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-PWINVUFGUehv90oL .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PWINVUFGUehv90oL .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PWINVUFGUehv90oL .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PWINVUFGUehv90oL .actorPopupMenu{position:absolute;}#mermaid-svg-PWINVUFGUehv90oL .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-PWINVUFGUehv90oL .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PWINVUFGUehv90oL .actor-man circle,#mermaid-svg-PWINVUFGUehv90oL line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-PWINVUFGUehv90oL :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}initialize(无凭证)401/要求认证弹授权流程/OAuthinitialize(带token)就绪
认证失败要有清晰引导,而不是神秘报错。
3.28 阶段 2 进阶:发现与能力地图的生成
发现结果生成"能力地图"的完整过程:
3.29 阶段 3 进阶:注册表与"默认 Server"
无冲突时,同名工具可设默认 Server + 优先级。注册表支持:
- 精确匹配(工具名唯一)。
- 前缀匹配(namespace.tool)。
- 默认路由(未指定时)。
3.30 阶段 4 进阶:调用结果的四种走向
| 成功(文本) | 融入推理继续 |
| 成功(结构化) | 程序化处理 |
| 业务错误(isError) | 修正重试/换工具 |
| 系统错误 | 上报/降级 |
3.31 四阶段的工程实现分工
| Agent | 工具选择与参数意图 |
| Client | 发现、注册、路由、校验 |
| 注册表 | 工具→Server 映射 |
| Server | 执行与返回 |
3.32 四阶段的 SLA 参考
| 初始化 | 99.9% 成功 |
| 发现 | 99.9%(缓存兜底) |
| 注册 | 100%(内存操作) |
| 调用 | 99.5%(按工具) |
3.33 本章小结(终版)
四阶段是工具能力的完整生命周期:初始化建通道、发现拉清单、注册建路由、调用做执行。深挖覆盖初始化交换内容、能力差异、并行初始化、认证、能力地图生成、默认路由、结果走向、分工、SLA——源时序图的每一步都能落到工程实践。
第 4 章 路由注册表深拆
4.1 路由注册表的职责
路由注册表是 Client 内部的组件,核心职责只有一个:给定工具名,返回该工具所属的 Server。它是四阶段中"注册"阶段的产物、"调用"阶段的前置。
#mermaid-svg-Sn4EDZNtUjNEAVN0{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .error-icon{fill:#552222;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .marker.cross{stroke:#333333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Sn4EDZNtUjNEAVN0 p{margin:0;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .cluster-label text{fill:#333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .cluster-label span{color:#333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .cluster-label span p{background-color:transparent;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .label text,#mermaid-svg-Sn4EDZNtUjNEAVN0 span{fill:#333;color:#333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .node rect,#mermaid-svg-Sn4EDZNtUjNEAVN0 .node circle,#mermaid-svg-Sn4EDZNtUjNEAVN0 .node ellipse,#mermaid-svg-Sn4EDZNtUjNEAVN0 .node polygon,#mermaid-svg-Sn4EDZNtUjNEAVN0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .rough-node .label text,#mermaid-svg-Sn4EDZNtUjNEAVN0 .node .label text,#mermaid-svg-Sn4EDZNtUjNEAVN0 .image-shape .label,#mermaid-svg-Sn4EDZNtUjNEAVN0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .rough-node .label,#mermaid-svg-Sn4EDZNtUjNEAVN0 .node .label,#mermaid-svg-Sn4EDZNtUjNEAVN0 .image-shape .label,#mermaid-svg-Sn4EDZNtUjNEAVN0 .icon-shape .label{text-align:center;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .node.clickable{cursor:pointer;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .arrowheadPath{fill:#333333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Sn4EDZNtUjNEAVN0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Sn4EDZNtUjNEAVN0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Sn4EDZNtUjNEAVN0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .cluster text{fill:#333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .cluster span{color:#333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Sn4EDZNtUjNEAVN0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .icon-shape,#mermaid-svg-Sn4EDZNtUjNEAVN0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .icon-shape p,#mermaid-svg-Sn4EDZNtUjNEAVN0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .icon-shape .label rect,#mermaid-svg-Sn4EDZNtUjNEAVN0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Sn4EDZNtUjNEAVN0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Sn4EDZNtUjNEAVN0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Sn4EDZNtUjNEAVN0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
tools/list 结果
注册表构建
工具→Server 映射
call_tool 查表
路由到目标 Server
4.2 注册表的数据结构
最简单实现是哈希表:
search_code → {server: GitHub, session: s1}
create_issue → {server: GitHub, session: s1}
send_message → {server: Slack, session: s2}
list_channels → {server: Slack, session: s2}
值里不仅要记 Server 标识,还要记会话句柄(因为同一个 Server 可能有多个会话)。
4.3 注册流程
#mermaid-svg-2IIw3a9iRh9XTV9o{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2IIw3a9iRh9XTV9o .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2IIw3a9iRh9XTV9o .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2IIw3a9iRh9XTV9o .error-icon{fill:#552222;}#mermaid-svg-2IIw3a9iRh9XTV9o .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2IIw3a9iRh9XTV9o .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2IIw3a9iRh9XTV9o .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2IIw3a9iRh9XTV9o .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2IIw3a9iRh9XTV9o .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2IIw3a9iRh9XTV9o .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2IIw3a9iRh9XTV9o .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2IIw3a9iRh9XTV9o .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2IIw3a9iRh9XTV9o .marker.cross{stroke:#333333;}#mermaid-svg-2IIw3a9iRh9XTV9o svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2IIw3a9iRh9XTV9o p{margin:0;}#mermaid-svg-2IIw3a9iRh9XTV9o .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-2IIw3a9iRh9XTV9o .cluster-label text{fill:#333;}#mermaid-svg-2IIw3a9iRh9XTV9o .cluster-label span{color:#333;}#mermaid-svg-2IIw3a9iRh9XTV9o .cluster-label span p{background-color:transparent;}#mermaid-svg-2IIw3a9iRh9XTV9o .label text,#mermaid-svg-2IIw3a9iRh9XTV9o span{fill:#333;color:#333;}#mermaid-svg-2IIw3a9iRh9XTV9o .node rect,#mermaid-svg-2IIw3a9iRh9XTV9o .node circle,#mermaid-svg-2IIw3a9iRh9XTV9o .node ellipse,#mermaid-svg-2IIw3a9iRh9XTV9o .node polygon,#mermaid-svg-2IIw3a9iRh9XTV9o .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2IIw3a9iRh9XTV9o .rough-node .label text,#mermaid-svg-2IIw3a9iRh9XTV9o .node .label text,#mermaid-svg-2IIw3a9iRh9XTV9o .image-shape .label,#mermaid-svg-2IIw3a9iRh9XTV9o .icon-shape .label{text-anchor:middle;}#mermaid-svg-2IIw3a9iRh9XTV9o .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2IIw3a9iRh9XTV9o .rough-node .label,#mermaid-svg-2IIw3a9iRh9XTV9o .node .label,#mermaid-svg-2IIw3a9iRh9XTV9o .image-shape .label,#mermaid-svg-2IIw3a9iRh9XTV9o .icon-shape .label{text-align:center;}#mermaid-svg-2IIw3a9iRh9XTV9o .node.clickable{cursor:pointer;}#mermaid-svg-2IIw3a9iRh9XTV9o .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2IIw3a9iRh9XTV9o .arrowheadPath{fill:#333333;}#mermaid-svg-2IIw3a9iRh9XTV9o .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2IIw3a9iRh9XTV9o .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2IIw3a9iRh9XTV9o .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2IIw3a9iRh9XTV9o .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2IIw3a9iRh9XTV9o .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2IIw3a9iRh9XTV9o .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2IIw3a9iRh9XTV9o .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2IIw3a9iRh9XTV9o .cluster text{fill:#333;}#mermaid-svg-2IIw3a9iRh9XTV9o .cluster span{color:#333;}#mermaid-svg-2IIw3a9iRh9XTV9o div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2IIw3a9iRh9XTV9o .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2IIw3a9iRh9XTV9o rect.text{fill:none;stroke-width:0;}#mermaid-svg-2IIw3a9iRh9XTV9o .icon-shape,#mermaid-svg-2IIw3a9iRh9XTV9o .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2IIw3a9iRh9XTV9o .icon-shape p,#mermaid-svg-2IIw3a9iRh9XTV9o .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2IIw3a9iRh9XTV9o .icon-shape .label rect,#mermaid-svg-2IIw3a9iRh9XTV9o .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2IIw3a9iRh9XTV9o .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2IIw3a9iRh9XTV9o .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2IIw3a9iRh9XTV9o :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
是
否
tools/list 返回
工具名已存在?
写入映射
来自同一 Server?
更新 schema/描述
冲突处理: 前缀/优先级/告警
注册完成
4.4 工具名冲突处理
多 Server 场景下,"同名工具"并不罕见(例如 GitHub 和 GitLab 都有 list_repos)。处理策略:
4.5 注册表的更新时机
注册表不是一次建好就永不变。以下时机需要刷新:
- Server 推送 notifications/tools/list_changed。
- 定时重新 tools/list(长驻会话定期刷新)。
- 调用失败后主动重新发现(怀疑清单过期)。
4.6 缓存与失效
发现结果缓存可省大量往返,但必须配套失效机制:
| Server 通知变更 | 立即重新拉取 |
| 定时过期 | TTL 到期刷新 |
| 调用报 MethodNotFound | 刷新后重试一次 |
4.7 注册表与权限的联动
注册表还应记录工具的"危险等级":
delete_issue → {server: GitHub, destructive: true}
search_code → {server: GitHub, destructive: false}
调用 destructive 工具前,Client 可触发二次确认或策略拦截(详见 8 章安全部分)。
4.8 注册表的可观测性
工程上建议对注册表打点:
- 工具总数、Server 数。
- 每次查表的命中率。
- 冲突次数、刷新次数。
- 未命中(查不到工具)的错误次数——这是 Agent 幻觉调用工具的前兆。
4.9 注册表实现示例
class ToolRegistry:
def __init__(self):
self._map = {} # tool_name -> (server, session, meta)
def register(self, tool_name, server, session, meta):
if tool_name in self._map and self._map[tool_name][0] != server:
self._handle_conflict(tool_name, server)
self._map[tool_name] = (server, session, meta)
def lookup(self, tool_name):
return self._map.get(tool_name)
def refresh(self, server, tools):
for t in tools:
self.register(t.name, server, server.session, t.meta)
4.10 注册表性能
查表是 O(1) 哈希查找,性能无忧;瓶颈在"建表"(发现)与"失效刷新"。因此工程重点是控制发现频率,而不是优化查表本身。
4.12 注册表的数据模型(完整版)
生产级注册表条目应包含:
{
"tool_name": "create_issue",
"server": "github-server",
"session_id": "s1",
"meta": {
"description": "创建 GitHub Issue",
"input_schema": { "…": "…" },
"destructive": false,
"read_only": false,
"timeout_ms": 30000,
"idempotent": true,
"requires_confirm": false
}
}
meta 里的标注不只是给 Client 看,也是给 Agent 的安全提示——destructive=true 的工具,Agent 在规划时就应更谨慎。
4.13 注册表的三种实现形态
| 内存哈希表 | 最快,进程内 | 单 Client |
| 分布式 KV | 跨进程共享 | 多 Client 复用发现结果 |
| 带版本号快照 | 可回滚 | 需要灰度/回滚的场景 |
4.14 注册表与"工具编排"的区别
- 注册表:静态映射,回答"工具在哪个 Server"。
- 编排:动态决策,回答"这次任务先调哪个、调完调哪个"。
不要把两者混为一谈:注册表是基础设施,编排是 Agent 智能。编排层查注册表做路由,注册表不参与任务决策。
4.15 冲突处理实战:前缀 vs 显式选择
#mermaid-svg-3dKYry8e8x8XaX5e{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3dKYry8e8x8XaX5e .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3dKYry8e8x8XaX5e .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3dKYry8e8x8XaX5e .error-icon{fill:#552222;}#mermaid-svg-3dKYry8e8x8XaX5e .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3dKYry8e8x8XaX5e .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3dKYry8e8x8XaX5e .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3dKYry8e8x8XaX5e .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3dKYry8e8x8XaX5e .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3dKYry8e8x8XaX5e .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3dKYry8e8x8XaX5e .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3dKYry8e8x8XaX5e .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3dKYry8e8x8XaX5e .marker.cross{stroke:#333333;}#mermaid-svg-3dKYry8e8x8XaX5e svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3dKYry8e8x8XaX5e p{margin:0;}#mermaid-svg-3dKYry8e8x8XaX5e .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-3dKYry8e8x8XaX5e .cluster-label text{fill:#333;}#mermaid-svg-3dKYry8e8x8XaX5e .cluster-label span{color:#333;}#mermaid-svg-3dKYry8e8x8XaX5e .cluster-label span p{background-color:transparent;}#mermaid-svg-3dKYry8e8x8XaX5e .label text,#mermaid-svg-3dKYry8e8x8XaX5e span{fill:#333;color:#333;}#mermaid-svg-3dKYry8e8x8XaX5e .node rect,#mermaid-svg-3dKYry8e8x8XaX5e .node circle,#mermaid-svg-3dKYry8e8x8XaX5e .node ellipse,#mermaid-svg-3dKYry8e8x8XaX5e .node polygon,#mermaid-svg-3dKYry8e8x8XaX5e .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3dKYry8e8x8XaX5e .rough-node .label text,#mermaid-svg-3dKYry8e8x8XaX5e .node .label text,#mermaid-svg-3dKYry8e8x8XaX5e .image-shape .label,#mermaid-svg-3dKYry8e8x8XaX5e .icon-shape .label{text-anchor:middle;}#mermaid-svg-3dKYry8e8x8XaX5e .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3dKYry8e8x8XaX5e .rough-node .label,#mermaid-svg-3dKYry8e8x8XaX5e .node .label,#mermaid-svg-3dKYry8e8x8XaX5e .image-shape .label,#mermaid-svg-3dKYry8e8x8XaX5e .icon-shape .label{text-align:center;}#mermaid-svg-3dKYry8e8x8XaX5e .node.clickable{cursor:pointer;}#mermaid-svg-3dKYry8e8x8XaX5e .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3dKYry8e8x8XaX5e .arrowheadPath{fill:#333333;}#mermaid-svg-3dKYry8e8x8XaX5e .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3dKYry8e8x8XaX5e .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3dKYry8e8x8XaX5e .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3dKYry8e8x8XaX5e .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3dKYry8e8x8XaX5e .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3dKYry8e8x8XaX5e .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3dKYry8e8x8XaX5e .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3dKYry8e8x8XaX5e .cluster text{fill:#333;}#mermaid-svg-3dKYry8e8x8XaX5e .cluster span{color:#333;}#mermaid-svg-3dKYry8e8x8XaX5e div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3dKYry8e8x8XaX5e .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3dKYry8e8x8XaX5e rect.text{fill:none;stroke-width:0;}#mermaid-svg-3dKYry8e8x8XaX5e .icon-shape,#mermaid-svg-3dKYry8e8x8XaX5e .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3dKYry8e8x8XaX5e .icon-shape p,#mermaid-svg-3dKYry8e8x8XaX5e .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3dKYry8e8x8XaX5e .icon-shape .label rect,#mermaid-svg-3dKYry8e8x8XaX5e .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3dKYry8e8x8XaX5e .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3dKYry8e8x8XaX5e .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3dKYry8e8x8XaX5e :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
是
否
发现同名工具
可加前缀?
github.list_repos
自动消除冲突
可配置优先级?
按优先级路由
告警 + Agent 显式选择
4.16 注册表的失效刷新流程
注册表ClientServer注册表ClientServer#mermaid-svg-nvVRcZV1mGxWcnqi{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nvVRcZV1mGxWcnqi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nvVRcZV1mGxWcnqi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nvVRcZV1mGxWcnqi .error-icon{fill:#552222;}#mermaid-svg-nvVRcZV1mGxWcnqi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nvVRcZV1mGxWcnqi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nvVRcZV1mGxWcnqi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nvVRcZV1mGxWcnqi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nvVRcZV1mGxWcnqi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nvVRcZV1mGxWcnqi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nvVRcZV1mGxWcnqi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nvVRcZV1mGxWcnqi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nvVRcZV1mGxWcnqi .marker.cross{stroke:#333333;}#mermaid-svg-nvVRcZV1mGxWcnqi svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nvVRcZV1mGxWcnqi p{margin:0;}#mermaid-svg-nvVRcZV1mGxWcnqi .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-nvVRcZV1mGxWcnqi text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-nvVRcZV1mGxWcnqi .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-nvVRcZV1mGxWcnqi .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-nvVRcZV1mGxWcnqi .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-nvVRcZV1mGxWcnqi .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-nvVRcZV1mGxWcnqi #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-nvVRcZV1mGxWcnqi .sequenceNumber{fill:white;}#mermaid-svg-nvVRcZV1mGxWcnqi #sequencenumber{fill:#333;}#mermaid-svg-nvVRcZV1mGxWcnqi #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-nvVRcZV1mGxWcnqi .messageText{fill:#333;stroke:none;}#mermaid-svg-nvVRcZV1mGxWcnqi .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-nvVRcZV1mGxWcnqi .labelText,#mermaid-svg-nvVRcZV1mGxWcnqi .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-nvVRcZV1mGxWcnqi .loopText,#mermaid-svg-nvVRcZV1mGxWcnqi .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-nvVRcZV1mGxWcnqi .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-nvVRcZV1mGxWcnqi .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-nvVRcZV1mGxWcnqi .noteText,#mermaid-svg-nvVRcZV1mGxWcnqi .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-nvVRcZV1mGxWcnqi .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-nvVRcZV1mGxWcnqi .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-nvVRcZV1mGxWcnqi .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-nvVRcZV1mGxWcnqi .actorPopupMenu{position:absolute;}#mermaid-svg-nvVRcZV1mGxWcnqi .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-nvVRcZV1mGxWcnqi .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-nvVRcZV1mGxWcnqi .actor-man circle,#mermaid-svg-nvVRcZV1mGxWcnqi line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-nvVRcZV1mGxWcnqi :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}notifications/tools/list_changed标记该 Server 清单过期tools/list(增量)变更后的工具集更新映射刷新完成
4.17 注册表与可观测性打点
建议对注册表打以下指标:
- 工具总数、Server 数、会话数。
- 查表命中率(未命中往往是幻觉调用的信号)。
- 冲突次数、刷新次数、失效次数。
- 平均查表耗时(正常应 <1ms,若升高查哈希退化)。
4.18 注册表的安全设计
4.19 注册表与多 Server 的故障联动
某 Server 熔断后,注册表应把该 Server 的工具标记为"不可用":
- 查表命中但 Server 不可用 → 返回"暂不可用"而非路由失败。
- 熔断恢复后自动恢复可用性。
- 降级策略:同名工具可路由到备用 Server。
4.21 注册表的查询 API
Client 给上层(编排层/Agent)暴露的典型查询:
class ToolRegistry:
def list_servers(self) –> list[str]: ...
def list_tools(self, server=None) –> list[str]: ...
def lookup(self, tool_name) –> RouteInfo | None: ...
def search_by_keyword(self, keyword) –> list[RouteInfo]: ...
def is_destructive(self, tool_name) –> bool: ...
def status(self, server) –> ServerStatus: ...
search_by_keyword 是"工具搜索"的底层支撑,供 Agent 在工具很多时做描述级检索。
4.22 注册表与工具描述的管理
注册表里的描述不应只来自 Server,还可叠加平台层增强:
- Server 原描述 + 平台补充(示例、常见坑)。
- 按 Agent 画像裁剪(运维 Agent 只看运维相关)。
- 统一去重、统一格式。
4.23 注册表的快照与回滚
发布新 Server/新工具前,给注册表打快照:
- 版本号 + 时间戳 + 变更记录。
- 出问题可一键回滚到旧快照。
- 灰度场景按快照对比差异。
4.24 注册表与 CI/CD
注册表变更纳入 CI:
- 契约测试:schema 变更检测。
- 冲突检测:新工具名是否冲突。
- 权限审核:destructive 工具需审批。
- 发布流水线:变更先走灰度。
4.25 注册表的容量规划
| 小 | <50 | 单机内存 |
| 中 | 50–500 | 内存+缓存分层 |
| 大 | 500+ | 分布式+索引 |
4.26 注册表与"工具下线"流程
工具下线不是直接删,而是分步走:
#mermaid-svg-Tme58JJTCRUSWXHD{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Tme58JJTCRUSWXHD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Tme58JJTCRUSWXHD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Tme58JJTCRUSWXHD .error-icon{fill:#552222;}#mermaid-svg-Tme58JJTCRUSWXHD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Tme58JJTCRUSWXHD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Tme58JJTCRUSWXHD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Tme58JJTCRUSWXHD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Tme58JJTCRUSWXHD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Tme58JJTCRUSWXHD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Tme58JJTCRUSWXHD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Tme58JJTCRUSWXHD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Tme58JJTCRUSWXHD .marker.cross{stroke:#333333;}#mermaid-svg-Tme58JJTCRUSWXHD svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Tme58JJTCRUSWXHD p{margin:0;}#mermaid-svg-Tme58JJTCRUSWXHD .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Tme58JJTCRUSWXHD .cluster-label text{fill:#333;}#mermaid-svg-Tme58JJTCRUSWXHD .cluster-label span{color:#333;}#mermaid-svg-Tme58JJTCRUSWXHD .cluster-label span p{background-color:transparent;}#mermaid-svg-Tme58JJTCRUSWXHD .label text,#mermaid-svg-Tme58JJTCRUSWXHD span{fill:#333;color:#333;}#mermaid-svg-Tme58JJTCRUSWXHD .node rect,#mermaid-svg-Tme58JJTCRUSWXHD .node circle,#mermaid-svg-Tme58JJTCRUSWXHD .node ellipse,#mermaid-svg-Tme58JJTCRUSWXHD .node polygon,#mermaid-svg-Tme58JJTCRUSWXHD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Tme58JJTCRUSWXHD .rough-node .label text,#mermaid-svg-Tme58JJTCRUSWXHD .node .label text,#mermaid-svg-Tme58JJTCRUSWXHD .image-shape .label,#mermaid-svg-Tme58JJTCRUSWXHD .icon-shape .label{text-anchor:middle;}#mermaid-svg-Tme58JJTCRUSWXHD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Tme58JJTCRUSWXHD .rough-node .label,#mermaid-svg-Tme58JJTCRUSWXHD .node .label,#mermaid-svg-Tme58JJTCRUSWXHD .image-shape .label,#mermaid-svg-Tme58JJTCRUSWXHD .icon-shape .label{text-align:center;}#mermaid-svg-Tme58JJTCRUSWXHD .node.clickable{cursor:pointer;}#mermaid-svg-Tme58JJTCRUSWXHD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Tme58JJTCRUSWXHD .arrowheadPath{fill:#333333;}#mermaid-svg-Tme58JJTCRUSWXHD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Tme58JJTCRUSWXHD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Tme58JJTCRUSWXHD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Tme58JJTCRUSWXHD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Tme58JJTCRUSWXHD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Tme58JJTCRUSWXHD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Tme58JJTCRUSWXHD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Tme58JJTCRUSWXHD .cluster text{fill:#333;}#mermaid-svg-Tme58JJTCRUSWXHD .cluster span{color:#333;}#mermaid-svg-Tme58JJTCRUSWXHD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Tme58JJTCRUSWXHD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Tme58JJTCRUSWXHD rect.text{fill:none;stroke-width:0;}#mermaid-svg-Tme58JJTCRUSWXHD .icon-shape,#mermaid-svg-Tme58JJTCRUSWXHD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Tme58JJTCRUSWXHD .icon-shape p,#mermaid-svg-Tme58JJTCRUSWXHD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Tme58JJTCRUSWXHD .icon-shape .label rect,#mermaid-svg-Tme58JJTCRUSWXHD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Tme58JJTCRUSWXHD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Tme58JJTCRUSWXHD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Tme58JJTCRUSWXHD :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
标记deprecated
迁移通知
观察期
移除
审计留痕
4.27 注册表的健康检查
- 条目数与预期一致?
- 所有 Server 可达?
- 无过期条目?
- 命中率正常?
异常自动告警,避免"注册表静默损坏"。
4.28 本章小结(终版)
路由注册表是"发现"与"调用"之间的枢纽。深挖覆盖查询 API、描述增强、快照回滚、CI/CD 集成、容量规划、下线流程、健康检查,加上此前的完整数据模型、实现形态、冲突处理、失效刷新、可观测、安全设计、故障联动——从"能用"到"生产可用"再到"可治理"。
第 5 章 工具发现机制深拆
5.1 tools/list 的返回结构
tools/list 是发现阶段的核心方法。它的响应是一个工具数组,每个工具包含:
- name:工具名,Agent 调用时使用。
- description:工具说明,直接决定 Agent 是否选中它。
- inputSchema:JSON Schema,描述参数结构。
{
"jsonrpc": "2.0",
"result": {
"tools": [
{
"name": "search_code",
"description": "在指定仓库中搜索代码,返回匹配文件列表",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "搜索关键字" },
"repo": { "type": "string", "description": "仓库名" }
},
"required": ["query"]
}
}
]
}
}
5.2 description 是"销售文案"
Agent 面对几十上百个工具,靠 description 决定用哪个。描述写得差,工具就"卖不出去":
| “搜索代码” | 泛泛,Agent 难判断 |
| “在指定 GitHub 仓库中按关键字搜索代码,返回匹配文件路径列表,常用于定位某段逻辑的实现位置” | 明确,Agent 易命中 |
5.3 inputSchema 是"参数说明书"
Schema 质量决定调用成功率。三条铁律:
5.4 发现的时机
| 启动时 | 首次连接 | 必做 |
| 通知触发 | Server 说工具变了 | 增量刷新 |
| 定时 | 长驻会话 | TTL 控制 |
| 失败后 | 调用 MethodNotFound | 刷新重试 |
5.5 发现的优化:增量与缓存
全量 tools/list 在工具多、Server 多时开销不小。优化思路:
#mermaid-svg-lp9swTWmuJ2ugxv2{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lp9swTWmuJ2ugxv2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lp9swTWmuJ2ugxv2 .error-icon{fill:#552222;}#mermaid-svg-lp9swTWmuJ2ugxv2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lp9swTWmuJ2ugxv2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lp9swTWmuJ2ugxv2 .marker.cross{stroke:#333333;}#mermaid-svg-lp9swTWmuJ2ugxv2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lp9swTWmuJ2ugxv2 p{margin:0;}#mermaid-svg-lp9swTWmuJ2ugxv2 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-lp9swTWmuJ2ugxv2 .cluster-label text{fill:#333;}#mermaid-svg-lp9swTWmuJ2ugxv2 .cluster-label span{color:#333;}#mermaid-svg-lp9swTWmuJ2ugxv2 .cluster-label span p{background-color:transparent;}#mermaid-svg-lp9swTWmuJ2ugxv2 .label text,#mermaid-svg-lp9swTWmuJ2ugxv2 span{fill:#333;color:#333;}#mermaid-svg-lp9swTWmuJ2ugxv2 .node rect,#mermaid-svg-lp9swTWmuJ2ugxv2 .node circle,#mermaid-svg-lp9swTWmuJ2ugxv2 .node ellipse,#mermaid-svg-lp9swTWmuJ2ugxv2 .node polygon,#mermaid-svg-lp9swTWmuJ2ugxv2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lp9swTWmuJ2ugxv2 .rough-node .label text,#mermaid-svg-lp9swTWmuJ2ugxv2 .node .label text,#mermaid-svg-lp9swTWmuJ2ugxv2 .image-shape .label,#mermaid-svg-lp9swTWmuJ2ugxv2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-lp9swTWmuJ2ugxv2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lp9swTWmuJ2ugxv2 .rough-node .label,#mermaid-svg-lp9swTWmuJ2ugxv2 .node .label,#mermaid-svg-lp9swTWmuJ2ugxv2 .image-shape .label,#mermaid-svg-lp9swTWmuJ2ugxv2 .icon-shape .label{text-align:center;}#mermaid-svg-lp9swTWmuJ2ugxv2 .node.clickable{cursor:pointer;}#mermaid-svg-lp9swTWmuJ2ugxv2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lp9swTWmuJ2ugxv2 .arrowheadPath{fill:#333333;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lp9swTWmuJ2ugxv2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lp9swTWmuJ2ugxv2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lp9swTWmuJ2ugxv2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lp9swTWmuJ2ugxv2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lp9swTWmuJ2ugxv2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lp9swTWmuJ2ugxv2 .cluster text{fill:#333;}#mermaid-svg-lp9swTWmuJ2ugxv2 .cluster span{color:#333;}#mermaid-svg-lp9swTWmuJ2ugxv2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lp9swTWmuJ2ugxv2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lp9swTWmuJ2ugxv2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-lp9swTWmuJ2ugxv2 .icon-shape,#mermaid-svg-lp9swTWmuJ2ugxv2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lp9swTWmuJ2ugxv2 .icon-shape p,#mermaid-svg-lp9swTWmuJ2ugxv2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lp9swTWmuJ2ugxv2 .icon-shape .label rect,#mermaid-svg-lp9swTWmuJ2ugxv2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lp9swTWmuJ2ugxv2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lp9swTWmuJ2ugxv2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lp9swTWmuJ2ugxv2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
首次发现
全量拉取+缓存
运行中
Server 通知变更
按变更增量更新
5.6 发现与权限
某些 Server 的工具清单可能因身份而异(登录用户不同,可用工具不同)。Client 应把"发现结果"与"当前身份"绑定缓存,避免串权限。
5.7 发现失败处理
tools/list 失败(超时/网络断)时:
5.9 发现与 Agent 提示词的关系
发现结果最终会进入 Agent 的上下文。工具多了之后,提示词会膨胀:
#mermaid-svg-iTkHHxJ3Ub3s8bDy{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .error-icon{fill:#552222;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .marker.cross{stroke:#333333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iTkHHxJ3Ub3s8bDy p{margin:0;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .cluster-label text{fill:#333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .cluster-label span{color:#333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .cluster-label span p{background-color:transparent;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .label text,#mermaid-svg-iTkHHxJ3Ub3s8bDy span{fill:#333;color:#333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .node rect,#mermaid-svg-iTkHHxJ3Ub3s8bDy .node circle,#mermaid-svg-iTkHHxJ3Ub3s8bDy .node ellipse,#mermaid-svg-iTkHHxJ3Ub3s8bDy .node polygon,#mermaid-svg-iTkHHxJ3Ub3s8bDy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .rough-node .label text,#mermaid-svg-iTkHHxJ3Ub3s8bDy .node .label text,#mermaid-svg-iTkHHxJ3Ub3s8bDy .image-shape .label,#mermaid-svg-iTkHHxJ3Ub3s8bDy .icon-shape .label{text-anchor:middle;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .rough-node .label,#mermaid-svg-iTkHHxJ3Ub3s8bDy .node .label,#mermaid-svg-iTkHHxJ3Ub3s8bDy .image-shape .label,#mermaid-svg-iTkHHxJ3Ub3s8bDy .icon-shape .label{text-align:center;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .node.clickable{cursor:pointer;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .arrowheadPath{fill:#333333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iTkHHxJ3Ub3s8bDy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iTkHHxJ3Ub3s8bDy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iTkHHxJ3Ub3s8bDy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .cluster text{fill:#333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .cluster span{color:#333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iTkHHxJ3Ub3s8bDy rect.text{fill:none;stroke-width:0;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .icon-shape,#mermaid-svg-iTkHHxJ3Ub3s8bDy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .icon-shape p,#mermaid-svg-iTkHHxJ3Ub3s8bDy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .icon-shape .label rect,#mermaid-svg-iTkHHxJ3Ub3s8bDy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iTkHHxJ3Ub3s8bDy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iTkHHxJ3Ub3s8bDy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iTkHHxJ3Ub3s8bDy :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
发现结果
工具描述精简
进入系统提示词
Agent 选型
调用
优化手段:对大量工具做分层描述——热门工具给全描述,冷门工具给一句话 + 需要时再展开。
5.10 发现结果去重与合并
多 Server 提供同类工具时,Client 可以:
合并式发现对 Agent 最友好,但对 Client 实现要求高。
5.11 发现的权限过滤
Server 按身份返回不同工具集时,Client 应:
- 缓存与身份绑定,不跨身份共享。
- 权限变更后强制刷新。
- 对降权工具调用返回明确错误而非"工具不存在"。
5.12 发现的版本管理
工具也有版本:Server 升级工具后,老会话可能还在用旧 schema。建议:
- schema 带版本号或哈希。
- Client 检测到变更时提示"工具已更新"。
- 旧参数按兼容规则处理(新字段可选、删字段需迁移)。
5.13 发现的批量与分页
工具极多(上百个)时,tools/list 支持分页:
{ "method": "tools/list", "params": { "cursor": "next-page-key" } }
Client 分批拉取,边拉边注册,避免一次性内存爆炸。
5.14 发现与"工具搜索"
Agent 端可以内置"工具搜索":不把全部工具塞进上下文,而是按任务关键字检索描述,只把最相关的几个工具给模型。这本质是发现结果之上的二级索引。
5.15 发现结果的质量评估
| 工具命中率 | 描述是否贴任务 | 重写 description |
| 参数错误率 | schema 是否清晰 | 补全 inputSchema |
| 发现耗时 | 清单大小/网络 | 分页/缓存/增量 |
| 冗余度 | 是否重复 | 合并/折叠 |
5.17 发现的时序图(完整版)
ServerClientAgentServerClientAgent#mermaid-svg-dZ70c3AEMpjlESaf{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dZ70c3AEMpjlESaf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dZ70c3AEMpjlESaf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dZ70c3AEMpjlESaf .error-icon{fill:#552222;}#mermaid-svg-dZ70c3AEMpjlESaf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dZ70c3AEMpjlESaf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dZ70c3AEMpjlESaf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dZ70c3AEMpjlESaf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dZ70c3AEMpjlESaf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dZ70c3AEMpjlESaf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dZ70c3AEMpjlESaf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dZ70c3AEMpjlESaf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dZ70c3AEMpjlESaf .marker.cross{stroke:#333333;}#mermaid-svg-dZ70c3AEMpjlESaf svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dZ70c3AEMpjlESaf p{margin:0;}#mermaid-svg-dZ70c3AEMpjlESaf .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-dZ70c3AEMpjlESaf text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-dZ70c3AEMpjlESaf .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-dZ70c3AEMpjlESaf .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-dZ70c3AEMpjlESaf .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-dZ70c3AEMpjlESaf .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-dZ70c3AEMpjlESaf #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-dZ70c3AEMpjlESaf .sequenceNumber{fill:white;}#mermaid-svg-dZ70c3AEMpjlESaf #sequencenumber{fill:#333;}#mermaid-svg-dZ70c3AEMpjlESaf #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-dZ70c3AEMpjlESaf .messageText{fill:#333;stroke:none;}#mermaid-svg-dZ70c3AEMpjlESaf .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-dZ70c3AEMpjlESaf .labelText,#mermaid-svg-dZ70c3AEMpjlESaf .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-dZ70c3AEMpjlESaf .loopText,#mermaid-svg-dZ70c3AEMpjlESaf .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-dZ70c3AEMpjlESaf .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-dZ70c3AEMpjlESaf .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-dZ70c3AEMpjlESaf .noteText,#mermaid-svg-dZ70c3AEMpjlESaf .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-dZ70c3AEMpjlESaf .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-dZ70c3AEMpjlESaf .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-dZ70c3AEMpjlESaf .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-dZ70c3AEMpjlESaf .actorPopupMenu{position:absolute;}#mermaid-svg-dZ70c3AEMpjlESaf .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-dZ70c3AEMpjlESaf .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-dZ70c3AEMpjlESaf .actor-man circle,#mermaid-svg-dZ70c3AEMpjlESaf line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-dZ70c3AEMpjlESaf :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}需要工具清单tools/list工具数组(含schema)校验/去重/权限过滤缓存 + 注册能力地图就绪
5.18 发现结果的校验
拿到清单后,Client 应校验:
- 工具名合法性(命名规范)。
- description 非空(空描述的工具形同虚设)。
- inputSchema 是合法 JSON Schema。
- 无重复工具名。
不合规的工具标记告警,避免"带病上线"。
5.19 发现的降级:清单不可用时的行为
tools/list 失败时按场景降级:
| 首次失败 | 该 Server 视为不可用 |
| 刷新失败 | 沿用旧缓存(标 stale) |
| 连续失败 | 熔断 + 告警 |
| 部分失败 | 已成功的 Server 正常用 |
5.20 发现的幂等性
tools/list 是只读方法,天然幂等。但"发现后注册"要防重复:同一工具重复注册应更新而非追加;注册过程支持重入。
5.21 发现的审计
记录发现行为本身:谁发起的、何时、哪个 Server、返回多少工具、耗时。审计数据用于:追踪权限异常、评估 Server 稳定性、优化发现策略。
5.22 发现的测试
- 单元:mock Server 返回固定清单,验证注册结果。
- 集成:真实 Server 联调,验证 schema 解析。
- 异常:Server 返回空清单/畸形 schema/超时。
- 性能:100 个工具分页拉取的耗时。
5.23 发现的配置项
discovery:
cache_ttl: 300s
refresh_on_notify: true
refresh_on_error: true
lazy_enabled: false
page_size: 50
timeout_ms: 5000
5.24 本章小结(终版)
发现机制的核心是 tools/list + 缓存失效 + 失败降级,配套校验、幂等、审计、测试、配置。深挖覆盖描述与 schema 质量、分层描述、去重合并、权限过滤、版本管理、分页、工具搜索、质量评估——description 与 inputSchema 的质量直接决定工具命中率与调用成功率。
第 6 章 工具调用机制深拆
6.1 tools/call 的请求结构
调用阶段的核心方法是 tools/call:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "search_code",
"arguments": { "query": "auth", "repo": "myrepo" }
}
}
Server 执行后返回结果:
{
"jsonrpc": "2.0",
"result": {
"content": [
{ "type": "text", "text": "找到5个匹配文件" }
],
"isError": false
}
}
6.2 调用前的参数校验
Client 在转发前,应先用 inputSchema 校验参数:
#mermaid-svg-xmnxF0g9xhl94JQX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xmnxF0g9xhl94JQX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xmnxF0g9xhl94JQX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xmnxF0g9xhl94JQX .error-icon{fill:#552222;}#mermaid-svg-xmnxF0g9xhl94JQX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xmnxF0g9xhl94JQX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xmnxF0g9xhl94JQX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xmnxF0g9xhl94JQX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xmnxF0g9xhl94JQX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xmnxF0g9xhl94JQX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xmnxF0g9xhl94JQX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xmnxF0g9xhl94JQX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xmnxF0g9xhl94JQX .marker.cross{stroke:#333333;}#mermaid-svg-xmnxF0g9xhl94JQX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xmnxF0g9xhl94JQX p{margin:0;}#mermaid-svg-xmnxF0g9xhl94JQX .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-xmnxF0g9xhl94JQX .cluster-label text{fill:#333;}#mermaid-svg-xmnxF0g9xhl94JQX .cluster-label span{color:#333;}#mermaid-svg-xmnxF0g9xhl94JQX .cluster-label span p{background-color:transparent;}#mermaid-svg-xmnxF0g9xhl94JQX .label text,#mermaid-svg-xmnxF0g9xhl94JQX span{fill:#333;color:#333;}#mermaid-svg-xmnxF0g9xhl94JQX .node rect,#mermaid-svg-xmnxF0g9xhl94JQX .node circle,#mermaid-svg-xmnxF0g9xhl94JQX .node ellipse,#mermaid-svg-xmnxF0g9xhl94JQX .node polygon,#mermaid-svg-xmnxF0g9xhl94JQX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xmnxF0g9xhl94JQX .rough-node .label text,#mermaid-svg-xmnxF0g9xhl94JQX .node .label text,#mermaid-svg-xmnxF0g9xhl94JQX .image-shape .label,#mermaid-svg-xmnxF0g9xhl94JQX .icon-shape .label{text-anchor:middle;}#mermaid-svg-xmnxF0g9xhl94JQX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xmnxF0g9xhl94JQX .rough-node .label,#mermaid-svg-xmnxF0g9xhl94JQX .node .label,#mermaid-svg-xmnxF0g9xhl94JQX .image-shape .label,#mermaid-svg-xmnxF0g9xhl94JQX .icon-shape .label{text-align:center;}#mermaid-svg-xmnxF0g9xhl94JQX .node.clickable{cursor:pointer;}#mermaid-svg-xmnxF0g9xhl94JQX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xmnxF0g9xhl94JQX .arrowheadPath{fill:#333333;}#mermaid-svg-xmnxF0g9xhl94JQX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xmnxF0g9xhl94JQX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xmnxF0g9xhl94JQX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xmnxF0g9xhl94JQX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xmnxF0g9xhl94JQX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xmnxF0g9xhl94JQX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xmnxF0g9xhl94JQX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xmnxF0g9xhl94JQX .cluster text{fill:#333;}#mermaid-svg-xmnxF0g9xhl94JQX .cluster span{color:#333;}#mermaid-svg-xmnxF0g9xhl94JQX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xmnxF0g9xhl94JQX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xmnxF0g9xhl94JQX rect.text{fill:none;stroke-width:0;}#mermaid-svg-xmnxF0g9xhl94JQX .icon-shape,#mermaid-svg-xmnxF0g9xhl94JQX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xmnxF0g9xhl94JQX .icon-shape p,#mermaid-svg-xmnxF0g9xhl94JQX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xmnxF0g9xhl94JQX .icon-shape .label rect,#mermaid-svg-xmnxF0g9xhl94JQX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xmnxF0g9xhl94JQX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xmnxF0g9xhl94JQX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xmnxF0g9xhl94JQX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
Agent 构造参数
按 schema 校验
合法?
路由+调用
补充/修正参数
校验不过时,Client 返回友好错误,而非直接打到 Server。
6.3 结果处理
Server 返回的内容类型多样(text/image/resource),Client 统一包装后交给 Agent:
- isError: false:正常结果,Agent 继续推理。
- isError: true:业务错误,Agent 需决定重试或换策略。
6.4 调用超时与取消
- 超时:按工具类型分级(快工具 10s、慢工具 60s+)。
- 取消:Agent 中途反悔,发 notifications/cancelled 中止在途调用。
6.5 调用的幂等性
写操作(create_issue、send_message)在重试时可能重复执行。Server 应支持幂等键,Client 重试时带上同一幂等键,Server 去重。
6.6 调用链路的可观测
ServerClientAgentServerClientAgent#mermaid-svg-SxXtpTXLuIvPQTCa{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SxXtpTXLuIvPQTCa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SxXtpTXLuIvPQTCa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SxXtpTXLuIvPQTCa .error-icon{fill:#552222;}#mermaid-svg-SxXtpTXLuIvPQTCa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SxXtpTXLuIvPQTCa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SxXtpTXLuIvPQTCa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SxXtpTXLuIvPQTCa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SxXtpTXLuIvPQTCa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SxXtpTXLuIvPQTCa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SxXtpTXLuIvPQTCa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SxXtpTXLuIvPQTCa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SxXtpTXLuIvPQTCa .marker.cross{stroke:#333333;}#mermaid-svg-SxXtpTXLuIvPQTCa svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SxXtpTXLuIvPQTCa p{margin:0;}#mermaid-svg-SxXtpTXLuIvPQTCa .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-SxXtpTXLuIvPQTCa text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-SxXtpTXLuIvPQTCa .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-SxXtpTXLuIvPQTCa .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-SxXtpTXLuIvPQTCa .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-SxXtpTXLuIvPQTCa .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-SxXtpTXLuIvPQTCa #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-SxXtpTXLuIvPQTCa .sequenceNumber{fill:white;}#mermaid-svg-SxXtpTXLuIvPQTCa #sequencenumber{fill:#333;}#mermaid-svg-SxXtpTXLuIvPQTCa #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-SxXtpTXLuIvPQTCa .messageText{fill:#333;stroke:none;}#mermaid-svg-SxXtpTXLuIvPQTCa .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-SxXtpTXLuIvPQTCa .labelText,#mermaid-svg-SxXtpTXLuIvPQTCa .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-SxXtpTXLuIvPQTCa .loopText,#mermaid-svg-SxXtpTXLuIvPQTCa .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-SxXtpTXLuIvPQTCa .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-SxXtpTXLuIvPQTCa .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-SxXtpTXLuIvPQTCa .noteText,#mermaid-svg-SxXtpTXLuIvPQTCa .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-SxXtpTXLuIvPQTCa .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-SxXtpTXLuIvPQTCa .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-SxXtpTXLuIvPQTCa .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-SxXtpTXLuIvPQTCa .actorPopupMenu{position:absolute;}#mermaid-svg-SxXtpTXLuIvPQTCa .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-SxXtpTXLuIvPQTCa .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-SxXtpTXLuIvPQTCa .actor-man circle,#mermaid-svg-SxXtpTXLuIvPQTCa line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-SxXtpTXLuIvPQTCa :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}call_tool(name, args)记录 traceId/耗时tools/call结果(isError)记录结果/错误码返回
6.7 调用失败的类型与处理
| 参数错误 | 缺必填字段 | 补参重试 |
| 工具不存在 | MethodNotFound | 刷新清单后重试 |
| Server 错误 | 内部异常 | 上报,不自动重试 |
| 限流 | ResourceExhausted | 退避后重试 |
6.9 参数校验的自动化
理想情况下,Client 用 JSON Schema 校验库(如 Python 的 jsonschema、JS 的 ajv)自动校验:
import jsonschema
schema = tool["inputSchema"]
jsonschema.validate(arguments, schema) # 不合法抛异常
校验失败时返回人可读的错误,Agent 才能据此修正:
参数错误:缺少必填字段 "query"(search_code 需要 query 和可选的 repo)
6.10 工具调用的重试策略矩阵
| InvalidParams | 否 | 修正参数 |
| MethodNotFound | 是(1次) | 刷新清单 |
| InternalError | 否 | 上报 |
| 超时 | 是 | 退避重试 |
| 限流 | 是 | 退避+抖动 |
| 网络断 | 是 | 重连后重试 |
6.11 调用的并发控制
Agent 可能同时发起多个工具调用(并行编排)。Client 应:
- 每个调用独立跟踪(request id)。
- 按 Server/会话维度限制并发数。
- 超时独立,不互相阻塞。
#mermaid-svg-sRWY0pRnLyR8ompT{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sRWY0pRnLyR8ompT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sRWY0pRnLyR8ompT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sRWY0pRnLyR8ompT .error-icon{fill:#552222;}#mermaid-svg-sRWY0pRnLyR8ompT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sRWY0pRnLyR8ompT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sRWY0pRnLyR8ompT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sRWY0pRnLyR8ompT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sRWY0pRnLyR8ompT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sRWY0pRnLyR8ompT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sRWY0pRnLyR8ompT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sRWY0pRnLyR8ompT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sRWY0pRnLyR8ompT .marker.cross{stroke:#333333;}#mermaid-svg-sRWY0pRnLyR8ompT svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sRWY0pRnLyR8ompT p{margin:0;}#mermaid-svg-sRWY0pRnLyR8ompT .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-sRWY0pRnLyR8ompT .cluster-label text{fill:#333;}#mermaid-svg-sRWY0pRnLyR8ompT .cluster-label span{color:#333;}#mermaid-svg-sRWY0pRnLyR8ompT .cluster-label span p{background-color:transparent;}#mermaid-svg-sRWY0pRnLyR8ompT .label text,#mermaid-svg-sRWY0pRnLyR8ompT span{fill:#333;color:#333;}#mermaid-svg-sRWY0pRnLyR8ompT .node rect,#mermaid-svg-sRWY0pRnLyR8ompT .node circle,#mermaid-svg-sRWY0pRnLyR8ompT .node ellipse,#mermaid-svg-sRWY0pRnLyR8ompT .node polygon,#mermaid-svg-sRWY0pRnLyR8ompT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sRWY0pRnLyR8ompT .rough-node .label text,#mermaid-svg-sRWY0pRnLyR8ompT .node .label text,#mermaid-svg-sRWY0pRnLyR8ompT .image-shape .label,#mermaid-svg-sRWY0pRnLyR8ompT .icon-shape .label{text-anchor:middle;}#mermaid-svg-sRWY0pRnLyR8ompT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sRWY0pRnLyR8ompT .rough-node .label,#mermaid-svg-sRWY0pRnLyR8ompT .node .label,#mermaid-svg-sRWY0pRnLyR8ompT .image-shape .label,#mermaid-svg-sRWY0pRnLyR8ompT .icon-shape .label{text-align:center;}#mermaid-svg-sRWY0pRnLyR8ompT .node.clickable{cursor:pointer;}#mermaid-svg-sRWY0pRnLyR8ompT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sRWY0pRnLyR8ompT .arrowheadPath{fill:#333333;}#mermaid-svg-sRWY0pRnLyR8ompT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sRWY0pRnLyR8ompT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sRWY0pRnLyR8ompT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sRWY0pRnLyR8ompT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sRWY0pRnLyR8ompT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sRWY0pRnLyR8ompT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sRWY0pRnLyR8ompT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sRWY0pRnLyR8ompT .cluster text{fill:#333;}#mermaid-svg-sRWY0pRnLyR8ompT .cluster span{color:#333;}#mermaid-svg-sRWY0pRnLyR8ompT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sRWY0pRnLyR8ompT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sRWY0pRnLyR8ompT rect.text{fill:none;stroke-width:0;}#mermaid-svg-sRWY0pRnLyR8ompT .icon-shape,#mermaid-svg-sRWY0pRnLyR8ompT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sRWY0pRnLyR8ompT .icon-shape p,#mermaid-svg-sRWY0pRnLyR8ompT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sRWY0pRnLyR8ompT .icon-shape .label rect,#mermaid-svg-sRWY0pRnLyR8ompT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sRWY0pRnLyR8ompT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sRWY0pRnLyR8ompT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sRWY0pRnLyR8ompT :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Agent
并发调用池
call A
call B
call C
结果聚合
返回 Agent
6.12 调用的进度反馈
慢工具(长任务)应支持进度上报:
- Server 通过 notifications/progress 推进度。
- Client 展示进度或供 Agent 判断是否继续等待。
- 超时阈值与进度挂钩(有进度就续期)。
6.13 调用结果的后处理
结果返回 Agent 前,Client 可以做:
6.14 调用的审计日志
每次调用记录:who(会话身份)、what(工具名)、args(脱敏后)、when、result(摘要)、latency、error。审计日志用于安全追溯与质量分析。
6.15 调用的降级链路
工具不可用时,按优先级降级:
6.16 调用与上下文管理的配合
调用结果进入上下文后,会占用 Token。建议:
- 结果摘要化后再入上下文。
- 超大结果存外部,只给 Agent 引用。
- 历史调用结果按需淘汰。
6.18 调用的完整时序(含校验与审计)
Server注册表ClientAgentServer注册表ClientAgent#mermaid-svg-KCClHnQWLfOjFHAO{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KCClHnQWLfOjFHAO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KCClHnQWLfOjFHAO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KCClHnQWLfOjFHAO .error-icon{fill:#552222;}#mermaid-svg-KCClHnQWLfOjFHAO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KCClHnQWLfOjFHAO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KCClHnQWLfOjFHAO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KCClHnQWLfOjFHAO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KCClHnQWLfOjFHAO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KCClHnQWLfOjFHAO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KCClHnQWLfOjFHAO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KCClHnQWLfOjFHAO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KCClHnQWLfOjFHAO .marker.cross{stroke:#333333;}#mermaid-svg-KCClHnQWLfOjFHAO svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KCClHnQWLfOjFHAO p{margin:0;}#mermaid-svg-KCClHnQWLfOjFHAO .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KCClHnQWLfOjFHAO text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-KCClHnQWLfOjFHAO .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-KCClHnQWLfOjFHAO .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-KCClHnQWLfOjFHAO .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-KCClHnQWLfOjFHAO .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-KCClHnQWLfOjFHAO #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-KCClHnQWLfOjFHAO .sequenceNumber{fill:white;}#mermaid-svg-KCClHnQWLfOjFHAO #sequencenumber{fill:#333;}#mermaid-svg-KCClHnQWLfOjFHAO #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-KCClHnQWLfOjFHAO .messageText{fill:#333;stroke:none;}#mermaid-svg-KCClHnQWLfOjFHAO .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KCClHnQWLfOjFHAO .labelText,#mermaid-svg-KCClHnQWLfOjFHAO .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-KCClHnQWLfOjFHAO .loopText,#mermaid-svg-KCClHnQWLfOjFHAO .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-KCClHnQWLfOjFHAO .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-KCClHnQWLfOjFHAO .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-KCClHnQWLfOjFHAO .noteText,#mermaid-svg-KCClHnQWLfOjFHAO .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-KCClHnQWLfOjFHAO .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KCClHnQWLfOjFHAO .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KCClHnQWLfOjFHAO .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KCClHnQWLfOjFHAO .actorPopupMenu{position:absolute;}#mermaid-svg-KCClHnQWLfOjFHAO .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-KCClHnQWLfOjFHAO .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KCClHnQWLfOjFHAO .actor-man circle,#mermaid-svg-KCClHnQWLfOjFHAO line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-KCClHnQWLfOjFHAO :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}call_tool(name, arguments)schema 校验查路由权限检查(二次确认?)tools/call结果/错误脱敏/摘要/审计返回
6.19 调用的权限检查
调用前检查:
任一不过 → 本地拦截,返回明确错误,不打扰 Server。
6.20 调用的请求 ID 与追踪
每个调用分配唯一 requestId:
- 贯穿 Client → Server 全链路。
- 日志、指标、审计都挂 requestId。
- 用户反馈"某次调用出错"时可按 ID 秒查。
6.21 调用的结果校验
Server 返回后,Client 校验:
- 是否符合 outputSchema(若声明)。
- isError 是否正确设置。
- 内容类型是否可解析。
不合规的结果标记告警,防止"坏数据"污染 Agent 推理。
6.22 调用的批量优化
高频小调用可合并:
- 相同 Server 的多个独立调用并行发送。
- 支持 batch 的 Server 合并请求。
- 减少往返,提升吞吐。
6.23 调用的成本控制
- 每工具/每 Server 配额。
- 结果缓存(读多写少场景)。
- 大结果摘要化,省 Token 与带宽。
- 成本看板 + 超预算告警。
6.24 调用的测试
- 单元:mock Server 验证校验/路由/重试逻辑。
- 集成:真实 Server 跑典型调用。
- 异常:注入超时/限流/坏 schema。
- 回归:工具更新后全量回归调用用例。
6.25 调用的配置项
call:
validate_args: true
retry_max: 2
retry_backoff: [200ms, 800ms, 2s]
timeout_default_ms: 10000
idempotency_key: auto
audit_log: true
6.26 本章小结(终版)
调用机制的核心:schema 校验前置、结果统一包装、超时/取消分级、写操作幂等、全链路可观测,配套权限检查、请求追踪、结果校验、批量优化、成本控制、测试、配置。调用成败的三要素:参数对不对、路由准不准、Server 稳不稳。
第 7 章 多 Server 组合与编排
7.1 多 Server 的价值
同一个 Agent 同时连接 GitHub、Slack、数据库等多个 MCP Server,就能组合出复杂能力:查完代码(GitHub)→ 通知团队(Slack)→ 记录数据(数据库)。
#mermaid-svg-fZKcgXSnN9iA86xi{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fZKcgXSnN9iA86xi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fZKcgXSnN9iA86xi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fZKcgXSnN9iA86xi .error-icon{fill:#552222;}#mermaid-svg-fZKcgXSnN9iA86xi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fZKcgXSnN9iA86xi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fZKcgXSnN9iA86xi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fZKcgXSnN9iA86xi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fZKcgXSnN9iA86xi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fZKcgXSnN9iA86xi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fZKcgXSnN9iA86xi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fZKcgXSnN9iA86xi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fZKcgXSnN9iA86xi .marker.cross{stroke:#333333;}#mermaid-svg-fZKcgXSnN9iA86xi svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fZKcgXSnN9iA86xi p{margin:0;}#mermaid-svg-fZKcgXSnN9iA86xi .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-fZKcgXSnN9iA86xi .cluster-label text{fill:#333;}#mermaid-svg-fZKcgXSnN9iA86xi .cluster-label span{color:#333;}#mermaid-svg-fZKcgXSnN9iA86xi .cluster-label span p{background-color:transparent;}#mermaid-svg-fZKcgXSnN9iA86xi .label text,#mermaid-svg-fZKcgXSnN9iA86xi span{fill:#333;color:#333;}#mermaid-svg-fZKcgXSnN9iA86xi .node rect,#mermaid-svg-fZKcgXSnN9iA86xi .node circle,#mermaid-svg-fZKcgXSnN9iA86xi .node ellipse,#mermaid-svg-fZKcgXSnN9iA86xi .node polygon,#mermaid-svg-fZKcgXSnN9iA86xi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fZKcgXSnN9iA86xi .rough-node .label text,#mermaid-svg-fZKcgXSnN9iA86xi .node .label text,#mermaid-svg-fZKcgXSnN9iA86xi .image-shape .label,#mermaid-svg-fZKcgXSnN9iA86xi .icon-shape .label{text-anchor:middle;}#mermaid-svg-fZKcgXSnN9iA86xi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fZKcgXSnN9iA86xi .rough-node .label,#mermaid-svg-fZKcgXSnN9iA86xi .node .label,#mermaid-svg-fZKcgXSnN9iA86xi .image-shape .label,#mermaid-svg-fZKcgXSnN9iA86xi .icon-shape .label{text-align:center;}#mermaid-svg-fZKcgXSnN9iA86xi .node.clickable{cursor:pointer;}#mermaid-svg-fZKcgXSnN9iA86xi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fZKcgXSnN9iA86xi .arrowheadPath{fill:#333333;}#mermaid-svg-fZKcgXSnN9iA86xi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fZKcgXSnN9iA86xi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fZKcgXSnN9iA86xi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fZKcgXSnN9iA86xi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fZKcgXSnN9iA86xi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fZKcgXSnN9iA86xi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fZKcgXSnN9iA86xi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fZKcgXSnN9iA86xi .cluster text{fill:#333;}#mermaid-svg-fZKcgXSnN9iA86xi .cluster span{color:#333;}#mermaid-svg-fZKcgXSnN9iA86xi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fZKcgXSnN9iA86xi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fZKcgXSnN9iA86xi rect.text{fill:none;stroke-width:0;}#mermaid-svg-fZKcgXSnN9iA86xi .icon-shape,#mermaid-svg-fZKcgXSnN9iA86xi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fZKcgXSnN9iA86xi .icon-shape p,#mermaid-svg-fZKcgXSnN9iA86xi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fZKcgXSnN9iA86xi .icon-shape .label rect,#mermaid-svg-fZKcgXSnN9iA86xi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fZKcgXSnN9iA86xi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fZKcgXSnN9iA86xi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fZKcgXSnN9iA86xi :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Agent
MCP Client
GitHub Server
Slack Server
数据库 Server
文件系统 Server
7.2 多 Server 的编排模式
7.3 多 Server 的隔离
一个 Server 挂了不能拖垮全部:
- 每 Server 独立会话、独立超时。
- 熔断器按 Server 维度。
- 舱壁模式:每 Server 独立线程池/队列。
7.4 多 Server 的负载与配额
- 每 Server 独立限流配额。
- 慢 Server 的调用不阻塞快 Server。
- 调度器优先执行关键路径工具。
7.5 多 Server 组合案例
DSlackGitHubClientAgentDSlackGitHubClientAgent#mermaid-svg-G1jUEEeNxsY9eQxJ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-G1jUEEeNxsY9eQxJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-G1jUEEeNxsY9eQxJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-G1jUEEeNxsY9eQxJ .error-icon{fill:#552222;}#mermaid-svg-G1jUEEeNxsY9eQxJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-G1jUEEeNxsY9eQxJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-G1jUEEeNxsY9eQxJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-G1jUEEeNxsY9eQxJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-G1jUEEeNxsY9eQxJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-G1jUEEeNxsY9eQxJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-G1jUEEeNxsY9eQxJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-G1jUEEeNxsY9eQxJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-G1jUEEeNxsY9eQxJ .marker.cross{stroke:#333333;}#mermaid-svg-G1jUEEeNxsY9eQxJ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-G1jUEEeNxsY9eQxJ p{margin:0;}#mermaid-svg-G1jUEEeNxsY9eQxJ .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-G1jUEEeNxsY9eQxJ text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-G1jUEEeNxsY9eQxJ .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-G1jUEEeNxsY9eQxJ .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-G1jUEEeNxsY9eQxJ .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-G1jUEEeNxsY9eQxJ .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-G1jUEEeNxsY9eQxJ #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-G1jUEEeNxsY9eQxJ .sequenceNumber{fill:white;}#mermaid-svg-G1jUEEeNxsY9eQxJ #sequencenumber{fill:#333;}#mermaid-svg-G1jUEEeNxsY9eQxJ #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-G1jUEEeNxsY9eQxJ .messageText{fill:#333;stroke:none;}#mermaid-svg-G1jUEEeNxsY9eQxJ .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-G1jUEEeNxsY9eQxJ .labelText,#mermaid-svg-G1jUEEeNxsY9eQxJ .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-G1jUEEeNxsY9eQxJ .loopText,#mermaid-svg-G1jUEEeNxsY9eQxJ .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-G1jUEEeNxsY9eQxJ .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-G1jUEEeNxsY9eQxJ .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-G1jUEEeNxsY9eQxJ .noteText,#mermaid-svg-G1jUEEeNxsY9eQxJ .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-G1jUEEeNxsY9eQxJ .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-G1jUEEeNxsY9eQxJ .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-G1jUEEeNxsY9eQxJ .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-G1jUEEeNxsY9eQxJ .actorPopupMenu{position:absolute;}#mermaid-svg-G1jUEEeNxsY9eQxJ .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-G1jUEEeNxsY9eQxJ .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-G1jUEEeNxsY9eQxJ .actor-man circle,#mermaid-svg-G1jUEEeNxsY9eQxJ line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-G1jUEEeNxsY9eQxJ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}call_tool(search_code)tools/call5 个文件call_tool(send_message)tools/call已发送call_tool(execute_query)tools/call
7.7 多 Server 的会话管理
每个 Server 一个(或多个)会话。会话管理要点:
- 会话级配置独立(超时、权限、限流)。
- 会话状态统一跟踪(connecting/ready/error/closed)。
- 批量初始化失败不阻断整体。
#mermaid-svg-YjC7OFIkHk47poMF{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YjC7OFIkHk47poMF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YjC7OFIkHk47poMF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YjC7OFIkHk47poMF .error-icon{fill:#552222;}#mermaid-svg-YjC7OFIkHk47poMF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YjC7OFIkHk47poMF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YjC7OFIkHk47poMF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YjC7OFIkHk47poMF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YjC7OFIkHk47poMF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YjC7OFIkHk47poMF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YjC7OFIkHk47poMF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YjC7OFIkHk47poMF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YjC7OFIkHk47poMF .marker.cross{stroke:#333333;}#mermaid-svg-YjC7OFIkHk47poMF svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YjC7OFIkHk47poMF p{margin:0;}#mermaid-svg-YjC7OFIkHk47poMF defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-YjC7OFIkHk47poMF g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-YjC7OFIkHk47poMF g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-YjC7OFIkHk47poMF g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-YjC7OFIkHk47poMF g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-YjC7OFIkHk47poMF g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-YjC7OFIkHk47poMF .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-YjC7OFIkHk47poMF .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-YjC7OFIkHk47poMF .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-YjC7OFIkHk47poMF .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-YjC7OFIkHk47poMF .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-YjC7OFIkHk47poMF .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-YjC7OFIkHk47poMF .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-YjC7OFIkHk47poMF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YjC7OFIkHk47poMF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YjC7OFIkHk47poMF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YjC7OFIkHk47poMF .edgeLabel .label text{fill:#333;}#mermaid-svg-YjC7OFIkHk47poMF .label div .edgeLabel{color:#333;}#mermaid-svg-YjC7OFIkHk47poMF .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-YjC7OFIkHk47poMF .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-YjC7OFIkHk47poMF .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-YjC7OFIkHk47poMF .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-YjC7OFIkHk47poMF .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-YjC7OFIkHk47poMF .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YjC7OFIkHk47poMF .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YjC7OFIkHk47poMF #statediagram-barbEnd{fill:#333333;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YjC7OFIkHk47poMF .cluster-label,#mermaid-svg-YjC7OFIkHk47poMF .nodeLabel{color:#131300;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-YjC7OFIkHk47poMF .note-edge{stroke-dasharray:5;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-note text{fill:black;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram-note .nodeLabel{color:black;}#mermaid-svg-YjC7OFIkHk47poMF .statediagram .edgeLabel{color:red;}#mermaid-svg-YjC7OFIkHk47poMF #dependencyStart,#mermaid-svg-YjC7OFIkHk47poMF #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-YjC7OFIkHk47poMF .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YjC7OFIkHk47poMF :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
连接
连接
连接
initialize
initialize
initialize
GitHub会话
Slack会话
数据库会话
GitHub就绪
Slack就绪
数据库就绪
7.8 多 Server 的组合策略
| 顺序 | 结果作为下一步输入 | 查代码→发通知 |
| 并行 | 互不依赖同时调 | 多仓库同时搜索 |
| 条件 | 按结果决定分支 | 有问题才建 Issue |
| 汇总 | 多源结果聚合 | 多数据库对比 |
7.9 多 Server 的路由优先级
同名工具跨 Server 时,可配置路由优先级:
list_repos:
– github-server (priority 1)
– gitlab-server (priority 2)
优先路由到优先级高的;失败时降级到下一优先级的 Server。
7.10 多 Server 的故障隔离实战
#mermaid-svg-ZwBgKmPTH1moOCwV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZwBgKmPTH1moOCwV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZwBgKmPTH1moOCwV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZwBgKmPTH1moOCwV .error-icon{fill:#552222;}#mermaid-svg-ZwBgKmPTH1moOCwV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZwBgKmPTH1moOCwV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZwBgKmPTH1moOCwV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZwBgKmPTH1moOCwV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZwBgKmPTH1moOCwV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZwBgKmPTH1moOCwV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZwBgKmPTH1moOCwV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZwBgKmPTH1moOCwV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZwBgKmPTH1moOCwV .marker.cross{stroke:#333333;}#mermaid-svg-ZwBgKmPTH1moOCwV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZwBgKmPTH1moOCwV p{margin:0;}#mermaid-svg-ZwBgKmPTH1moOCwV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZwBgKmPTH1moOCwV .cluster-label text{fill:#333;}#mermaid-svg-ZwBgKmPTH1moOCwV .cluster-label span{color:#333;}#mermaid-svg-ZwBgKmPTH1moOCwV .cluster-label span p{background-color:transparent;}#mermaid-svg-ZwBgKmPTH1moOCwV .label text,#mermaid-svg-ZwBgKmPTH1moOCwV span{fill:#333;color:#333;}#mermaid-svg-ZwBgKmPTH1moOCwV .node rect,#mermaid-svg-ZwBgKmPTH1moOCwV .node circle,#mermaid-svg-ZwBgKmPTH1moOCwV .node ellipse,#mermaid-svg-ZwBgKmPTH1moOCwV .node polygon,#mermaid-svg-ZwBgKmPTH1moOCwV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZwBgKmPTH1moOCwV .rough-node .label text,#mermaid-svg-ZwBgKmPTH1moOCwV .node .label text,#mermaid-svg-ZwBgKmPTH1moOCwV .image-shape .label,#mermaid-svg-ZwBgKmPTH1moOCwV .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZwBgKmPTH1moOCwV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZwBgKmPTH1moOCwV .rough-node .label,#mermaid-svg-ZwBgKmPTH1moOCwV .node .label,#mermaid-svg-ZwBgKmPTH1moOCwV .image-shape .label,#mermaid-svg-ZwBgKmPTH1moOCwV .icon-shape .label{text-align:center;}#mermaid-svg-ZwBgKmPTH1moOCwV .node.clickable{cursor:pointer;}#mermaid-svg-ZwBgKmPTH1moOCwV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZwBgKmPTH1moOCwV .arrowheadPath{fill:#333333;}#mermaid-svg-ZwBgKmPTH1moOCwV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZwBgKmPTH1moOCwV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZwBgKmPTH1moOCwV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZwBgKmPTH1moOCwV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZwBgKmPTH1moOCwV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZwBgKmPTH1moOCwV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZwBgKmPTH1moOCwV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZwBgKmPTH1moOCwV .cluster text{fill:#333;}#mermaid-svg-ZwBgKmPTH1moOCwV .cluster span{color:#333;}#mermaid-svg-ZwBgKmPTH1moOCwV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZwBgKmPTH1moOCwV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZwBgKmPTH1moOCwV rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZwBgKmPTH1moOCwV .icon-shape,#mermaid-svg-ZwBgKmPTH1moOCwV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZwBgKmPTH1moOCwV .icon-shape p,#mermaid-svg-ZwBgKmPTH1moOCwV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZwBgKmPTH1moOCwV .icon-shape .label rect,#mermaid-svg-ZwBgKmPTH1moOCwV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZwBgKmPTH1moOCwV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZwBgKmPTH1moOCwV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZwBgKmPTH1moOCwV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
熔断
正常
正常
Agent
Client
GitHub Server
Slack Server
数据库 Server
GitHub 降级
继续服务
继续服务
Slack 挂了,GitHub 和数据库照常工作;Agent 仍能完成"查代码 + 记库",只是通知环节降级为"稍后重试"。
7.11 多 Server 的配额管理
每 Server 独立配额:
- 每分钟调用上限。
- 并发数上限。
- 数据量上限。
超配额返回 ResourceExhausted,由调度器排队或降级。
7.12 多 Server 的可观测聚合
多 Server 场景下,单 Server 的指标不够,需要聚合视图:
- 按 Server 维度看延迟/错误率/配额。
- 跨 Server 链路看一次任务的总耗时。
- 定位瓶颈 Server(哪一步最慢)。
7.13 多 Server 的配置中心
建议用配置中心统一管理:
servers:
github:
transport: stdio
command: mcp–github
permissions: [read, write]
slack:
transport: http
url: https://slack–mcp.example.com
token_env: SLACK_TOKEN
database:
transport: stdio
command: mcp–postgres
dsn_env: PG_DSN
7.14 多 Server 的版本协同
多 Server 版本不同步时(一个 v1 一个 v2),Client 按会话分别协商:
- 每个会话独立 protocolVersion。
- 老版本 Server 的功能受限但可用。
- 升级 Server 时灰度替换,避免一刀切。
7.15 多 Server 的测试策略
- 单 Server 冒烟:各 Server 独立可用。
- 组合集成:多 Server 联合跑典型任务。
- 故障演练:杀一个 Server 验证隔离。
- 契约测试:schema 漂移检测。
7.17 多 Server 的注册与编排分离
- 注册层:每个 Server 独立发现、注册、维护会话。
- 编排层:跨 Server 的任务调度(顺序/并行/条件/汇总)。
注册层保证"每个 Server 可靠可用",编排层保证"多个 Server 协同成事"。两层解耦,故障域清晰。
7.18 多 Server 的延迟优化
| 并行初始化 | 启动快 N 倍 |
| 懒发现冷门 Server | 启动不被拖累 |
| 连接池复用 | 减少握手 |
| 结果缓存 | 读操作省往返 |
| 就近路由 | 网络延迟低 |
7.19 多 Server 的权限矩阵
| GitHub | 读写 | 只读 |
| Slack | 发消息 | 不可用 |
| 数据库 | 查询 | 查询+写 |
权限矩阵应在注册阶段落地:每个会话的注册表只包含该身份有权限的工具。
7.20 多 Server 的优雅降级顺序
Server 不可用时,按优先级降级:
7.21 多 Server 的容量与扩展
- 水平扩展:加 Server 实例,注册表按实例路由。
- 垂直扩展:提升单 Server 配额。
- 分片:不同工具集分到不同 Server。
7.22 多 Server 的测试矩阵
| 单 Server 冒烟 | 各自可用 |
| 组合集成 | 多 Server 联合 |
| 故障注入 | 杀一个验证隔离 |
| 并发压测 | 高并发调用 |
| 契约测试 | schema 漂移检测 |
7.23 本章小结(终版)
多 Server 组合是 MCP"一套标准连所有工具"价值的集中体现。深挖覆盖注册与编排分离、延迟优化、权限矩阵、优雅降级、容量扩展、测试矩阵,加上此前的会话管理、组合策略、路由优先级、故障隔离、配额管理、可观测聚合、配置中心、版本协同——编排要点:路由准确、隔离可靠、配额公平、链路可查。
第 8 章 技术挑战与解决方案
8.1 挑战总览
#mermaid-svg-tWMWOQMIjqkuW2eB{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tWMWOQMIjqkuW2eB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tWMWOQMIjqkuW2eB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tWMWOQMIjqkuW2eB .error-icon{fill:#552222;}#mermaid-svg-tWMWOQMIjqkuW2eB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tWMWOQMIjqkuW2eB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tWMWOQMIjqkuW2eB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tWMWOQMIjqkuW2eB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tWMWOQMIjqkuW2eB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tWMWOQMIjqkuW2eB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tWMWOQMIjqkuW2eB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tWMWOQMIjqkuW2eB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tWMWOQMIjqkuW2eB .marker.cross{stroke:#333333;}#mermaid-svg-tWMWOQMIjqkuW2eB svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tWMWOQMIjqkuW2eB p{margin:0;}#mermaid-svg-tWMWOQMIjqkuW2eB .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-tWMWOQMIjqkuW2eB .cluster-label text{fill:#333;}#mermaid-svg-tWMWOQMIjqkuW2eB .cluster-label span{color:#333;}#mermaid-svg-tWMWOQMIjqkuW2eB .cluster-label span p{background-color:transparent;}#mermaid-svg-tWMWOQMIjqkuW2eB .label text,#mermaid-svg-tWMWOQMIjqkuW2eB span{fill:#333;color:#333;}#mermaid-svg-tWMWOQMIjqkuW2eB .node rect,#mermaid-svg-tWMWOQMIjqkuW2eB .node circle,#mermaid-svg-tWMWOQMIjqkuW2eB .node ellipse,#mermaid-svg-tWMWOQMIjqkuW2eB .node polygon,#mermaid-svg-tWMWOQMIjqkuW2eB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tWMWOQMIjqkuW2eB .rough-node .label text,#mermaid-svg-tWMWOQMIjqkuW2eB .node .label text,#mermaid-svg-tWMWOQMIjqkuW2eB .image-shape .label,#mermaid-svg-tWMWOQMIjqkuW2eB .icon-shape .label{text-anchor:middle;}#mermaid-svg-tWMWOQMIjqkuW2eB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tWMWOQMIjqkuW2eB .rough-node .label,#mermaid-svg-tWMWOQMIjqkuW2eB .node .label,#mermaid-svg-tWMWOQMIjqkuW2eB .image-shape .label,#mermaid-svg-tWMWOQMIjqkuW2eB .icon-shape .label{text-align:center;}#mermaid-svg-tWMWOQMIjqkuW2eB .node.clickable{cursor:pointer;}#mermaid-svg-tWMWOQMIjqkuW2eB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tWMWOQMIjqkuW2eB .arrowheadPath{fill:#333333;}#mermaid-svg-tWMWOQMIjqkuW2eB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tWMWOQMIjqkuW2eB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tWMWOQMIjqkuW2eB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tWMWOQMIjqkuW2eB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tWMWOQMIjqkuW2eB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tWMWOQMIjqkuW2eB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tWMWOQMIjqkuW2eB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tWMWOQMIjqkuW2eB .cluster text{fill:#333;}#mermaid-svg-tWMWOQMIjqkuW2eB .cluster span{color:#333;}#mermaid-svg-tWMWOQMIjqkuW2eB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tWMWOQMIjqkuW2eB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tWMWOQMIjqkuW2eB rect.text{fill:none;stroke-width:0;}#mermaid-svg-tWMWOQMIjqkuW2eB .icon-shape,#mermaid-svg-tWMWOQMIjqkuW2eB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tWMWOQMIjqkuW2eB .icon-shape p,#mermaid-svg-tWMWOQMIjqkuW2eB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tWMWOQMIjqkuW2eB .icon-shape .label rect,#mermaid-svg-tWMWOQMIjqkuW2eB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tWMWOQMIjqkuW2eB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tWMWOQMIjqkuW2eB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tWMWOQMIjqkuW2eB :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
发现风暴
解法: 缓存+通知
路由冲突
解法: 前缀+优先级
schema 漂移
解法: 哈希校验+重拉
调用超时
解法: 分级超时+重试
写操作重复
解法: 幂等键
安全越权
解法: 权限联动
8.2 发现风暴
问题:每个 Server 频繁重新 tools/list,造成大量无效请求。
解法:
- 缓存清单 + TTL。
- 依赖 Server 的变更通知,而非定时轮询。
- 增量更新而非全量重拉。
8.3 路由冲突
问题:多 Server 提供同名工具,查表可能路由错。
解法:
- 命名空间前缀(github.list_repos)。
- 显式指定优先级。
- 冲突时告警并让 Agent 显式选择。
8.4 Schema 漂移
问题:Server 改了 inputSchema 但 Client 缓存没更新,导致调用参数不合法。
解法:
- 为 schema 计算哈希,变更即刷新。
- 调用失败(InvalidParams)时强制重拉清单。
- Server 主动推送变更通知。
8.5 调用超时与重试风暴
问题:网络抖动引发批量重试,压垮 Server。
解法:
- 指数退避 + 抖动。
- 写操作不自动重试(等幂键除外)。
- 熔断器防止雪崩。
8.6 安全:越权与注入
问题:Agent 被诱导调用危险工具,或工具参数被注入恶意内容。
解法:
- 注册表标记 destructive 工具,调用前二次确认/策略拦截。
- 工具结果中的外部内容做注入扫描。
- 敏感操作要求 HITL(人在环)。
8.7 可观测性
问题:跨 Agent/Client/Server 的链路难追踪。
解法:
- 全链路 traceId。
- 日志统一字段(sessionId/method/toolName/latency)。
- 注册表命中率、发现频率、错误码分布等指标看板。
8.8 排障决策树
#mermaid-svg-hKdNgJME4XRiAM60{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hKdNgJME4XRiAM60 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hKdNgJME4XRiAM60 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hKdNgJME4XRiAM60 .error-icon{fill:#552222;}#mermaid-svg-hKdNgJME4XRiAM60 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hKdNgJME4XRiAM60 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hKdNgJME4XRiAM60 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hKdNgJME4XRiAM60 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hKdNgJME4XRiAM60 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hKdNgJME4XRiAM60 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hKdNgJME4XRiAM60 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hKdNgJME4XRiAM60 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hKdNgJME4XRiAM60 .marker.cross{stroke:#333333;}#mermaid-svg-hKdNgJME4XRiAM60 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hKdNgJME4XRiAM60 p{margin:0;}#mermaid-svg-hKdNgJME4XRiAM60 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-hKdNgJME4XRiAM60 .cluster-label text{fill:#333;}#mermaid-svg-hKdNgJME4XRiAM60 .cluster-label span{color:#333;}#mermaid-svg-hKdNgJME4XRiAM60 .cluster-label span p{background-color:transparent;}#mermaid-svg-hKdNgJME4XRiAM60 .label text,#mermaid-svg-hKdNgJME4XRiAM60 span{fill:#333;color:#333;}#mermaid-svg-hKdNgJME4XRiAM60 .node rect,#mermaid-svg-hKdNgJME4XRiAM60 .node circle,#mermaid-svg-hKdNgJME4XRiAM60 .node ellipse,#mermaid-svg-hKdNgJME4XRiAM60 .node polygon,#mermaid-svg-hKdNgJME4XRiAM60 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hKdNgJME4XRiAM60 .rough-node .label text,#mermaid-svg-hKdNgJME4XRiAM60 .node .label text,#mermaid-svg-hKdNgJME4XRiAM60 .image-shape .label,#mermaid-svg-hKdNgJME4XRiAM60 .icon-shape .label{text-anchor:middle;}#mermaid-svg-hKdNgJME4XRiAM60 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hKdNgJME4XRiAM60 .rough-node .label,#mermaid-svg-hKdNgJME4XRiAM60 .node .label,#mermaid-svg-hKdNgJME4XRiAM60 .image-shape .label,#mermaid-svg-hKdNgJME4XRiAM60 .icon-shape .label{text-align:center;}#mermaid-svg-hKdNgJME4XRiAM60 .node.clickable{cursor:pointer;}#mermaid-svg-hKdNgJME4XRiAM60 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hKdNgJME4XRiAM60 .arrowheadPath{fill:#333333;}#mermaid-svg-hKdNgJME4XRiAM60 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hKdNgJME4XRiAM60 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hKdNgJME4XRiAM60 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hKdNgJME4XRiAM60 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hKdNgJME4XRiAM60 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hKdNgJME4XRiAM60 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hKdNgJME4XRiAM60 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hKdNgJME4XRiAM60 .cluster text{fill:#333;}#mermaid-svg-hKdNgJME4XRiAM60 .cluster span{color:#333;}#mermaid-svg-hKdNgJME4XRiAM60 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hKdNgJME4XRiAM60 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hKdNgJME4XRiAM60 rect.text{fill:none;stroke-width:0;}#mermaid-svg-hKdNgJME4XRiAM60 .icon-shape,#mermaid-svg-hKdNgJME4XRiAM60 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hKdNgJME4XRiAM60 .icon-shape p,#mermaid-svg-hKdNgJME4XRiAM60 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hKdNgJME4XRiAM60 .icon-shape .label rect,#mermaid-svg-hKdNgJME4XRiAM60 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hKdNgJME4XRiAM60 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hKdNgJME4XRiAM60 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hKdNgJME4XRiAM60 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
否
是
否
是
调用失败
路由命中?
刷新注册表
参数合法?
按 schema 修正
Server 可用?
熔断/降级
错误码?
按码处理/上报
8.10 挑战:Agent 幻觉调用
问题:Agent 可能编造一个不存在的工具名(幻觉),或对工具能力过度想象。
解法:
- 注册表未命中 → 返回"工具不存在"并列出可用工具,纠正 Agent。
- 工具描述写清楚边界(“本工具只支持 X,不支持 Y”)。
- 对高频幻觉工具做提示词约束。
#mermaid-svg-Xwhs18lvn7hm8OoZ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Xwhs18lvn7hm8OoZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Xwhs18lvn7hm8OoZ .error-icon{fill:#552222;}#mermaid-svg-Xwhs18lvn7hm8OoZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Xwhs18lvn7hm8OoZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Xwhs18lvn7hm8OoZ .marker.cross{stroke:#333333;}#mermaid-svg-Xwhs18lvn7hm8OoZ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Xwhs18lvn7hm8OoZ p{margin:0;}#mermaid-svg-Xwhs18lvn7hm8OoZ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Xwhs18lvn7hm8OoZ .cluster-label text{fill:#333;}#mermaid-svg-Xwhs18lvn7hm8OoZ .cluster-label span{color:#333;}#mermaid-svg-Xwhs18lvn7hm8OoZ .cluster-label span p{background-color:transparent;}#mermaid-svg-Xwhs18lvn7hm8OoZ .label text,#mermaid-svg-Xwhs18lvn7hm8OoZ span{fill:#333;color:#333;}#mermaid-svg-Xwhs18lvn7hm8OoZ .node rect,#mermaid-svg-Xwhs18lvn7hm8OoZ .node circle,#mermaid-svg-Xwhs18lvn7hm8OoZ .node ellipse,#mermaid-svg-Xwhs18lvn7hm8OoZ .node polygon,#mermaid-svg-Xwhs18lvn7hm8OoZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Xwhs18lvn7hm8OoZ .rough-node .label text,#mermaid-svg-Xwhs18lvn7hm8OoZ .node .label text,#mermaid-svg-Xwhs18lvn7hm8OoZ .image-shape .label,#mermaid-svg-Xwhs18lvn7hm8OoZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-Xwhs18lvn7hm8OoZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Xwhs18lvn7hm8OoZ .rough-node .label,#mermaid-svg-Xwhs18lvn7hm8OoZ .node .label,#mermaid-svg-Xwhs18lvn7hm8OoZ .image-shape .label,#mermaid-svg-Xwhs18lvn7hm8OoZ .icon-shape .label{text-align:center;}#mermaid-svg-Xwhs18lvn7hm8OoZ .node.clickable{cursor:pointer;}#mermaid-svg-Xwhs18lvn7hm8OoZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Xwhs18lvn7hm8OoZ .arrowheadPath{fill:#333333;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Xwhs18lvn7hm8OoZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Xwhs18lvn7hm8OoZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Xwhs18lvn7hm8OoZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Xwhs18lvn7hm8OoZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Xwhs18lvn7hm8OoZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Xwhs18lvn7hm8OoZ .cluster text{fill:#333;}#mermaid-svg-Xwhs18lvn7hm8OoZ .cluster span{color:#333;}#mermaid-svg-Xwhs18lvn7hm8OoZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Xwhs18lvn7hm8OoZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Xwhs18lvn7hm8OoZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-Xwhs18lvn7hm8OoZ .icon-shape,#mermaid-svg-Xwhs18lvn7hm8OoZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Xwhs18lvn7hm8OoZ .icon-shape p,#mermaid-svg-Xwhs18lvn7hm8OoZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Xwhs18lvn7hm8OoZ .icon-shape .label rect,#mermaid-svg-Xwhs18lvn7hm8OoZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Xwhs18lvn7hm8OoZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Xwhs18lvn7hm8OoZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Xwhs18lvn7hm8OoZ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
Agent 调用 call_tool
注册表命中?
返回可用工具列表
Agent 重新选择
正常调用
8.11 挑战:工具参数注入
问题:外部内容(网页、文件)被塞进工具参数,改变工具行为(提示注入的运行时变体)。
解法:
- 参数校验白名单(枚举、正则)。
- 敏感字段(URL、命令)做消毒。
- 工具结果中的外部内容标注"不可信",不入系统指令区。
8.12 挑战:发现与调用的时序竞态
问题:发现后工具被下架,注册表还没刷新,调用落空。
解法:
- 调用失败 MethodNotFound → 触发刷新 → 重试一次。
- Server 在工具变更时立即推送通知。
- 注册表条目带"获取时间",超龄强制刷新。
8.13 挑战:大并发下的注册表一致
问题:多线程/多 Agent 并发调用,注册表并发读写。
解法:
- 读写锁 / 原子替换。
- 不可变快照 + 指针切换。
- 分布式场景用版本号 CAS。
8.14 挑战:跨 Server 的事务
问题:任务需要"GitHub 建 Issue + Slack 通知 + 数据库记录",中间失败怎么办?
解法:
- 补偿事务:失败回滚已执行步骤(删除已建 Issue)。
- 编排层记录任务状态,支持重入。
- 幂等键保证重复执行不产生副作用。
数据库GitHubClientAgent数据库GitHubClientAgent#mermaid-svg-go6J3h2VxdlH53XL{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-go6J3h2VxdlH53XL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-go6J3h2VxdlH53XL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-go6J3h2VxdlH53XL .error-icon{fill:#552222;}#mermaid-svg-go6J3h2VxdlH53XL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-go6J3h2VxdlH53XL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-go6J3h2VxdlH53XL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-go6J3h2VxdlH53XL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-go6J3h2VxdlH53XL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-go6J3h2VxdlH53XL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-go6J3h2VxdlH53XL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-go6J3h2VxdlH53XL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-go6J3h2VxdlH53XL .marker.cross{stroke:#333333;}#mermaid-svg-go6J3h2VxdlH53XL svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-go6J3h2VxdlH53XL p{margin:0;}#mermaid-svg-go6J3h2VxdlH53XL .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-go6J3h2VxdlH53XL text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-go6J3h2VxdlH53XL .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-go6J3h2VxdlH53XL .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-go6J3h2VxdlH53XL .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-go6J3h2VxdlH53XL .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-go6J3h2VxdlH53XL #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-go6J3h2VxdlH53XL .sequenceNumber{fill:white;}#mermaid-svg-go6J3h2VxdlH53XL #sequencenumber{fill:#333;}#mermaid-svg-go6J3h2VxdlH53XL #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-go6J3h2VxdlH53XL .messageText{fill:#333;stroke:none;}#mermaid-svg-go6J3h2VxdlH53XL .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-go6J3h2VxdlH53XL .labelText,#mermaid-svg-go6J3h2VxdlH53XL .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-go6J3h2VxdlH53XL .loopText,#mermaid-svg-go6J3h2VxdlH53XL .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-go6J3h2VxdlH53XL .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-go6J3h2VxdlH53XL .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-go6J3h2VxdlH53XL .noteText,#mermaid-svg-go6J3h2VxdlH53XL .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-go6J3h2VxdlH53XL .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-go6J3h2VxdlH53XL .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-go6J3h2VxdlH53XL .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-go6J3h2VxdlH53XL .actorPopupMenu{position:absolute;}#mermaid-svg-go6J3h2VxdlH53XL .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-go6J3h2VxdlH53XL .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-go6J3h2VxdlH53XL .actor-man circle,#mermaid-svg-go6J3h2VxdlH53XL line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-go6J3h2VxdlH53XL :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}任务开始create_issue ✅insert_record ❌补偿: close_issue任务失败,已回滚
8.15 挑战:发现结果过大
问题:上百个工具的清单塞进上下文,Token 爆炸。
解法:
- 分页 + 按需加载。
- 工具搜索(描述级检索)。
- 分层描述(热门全量、冷门摘要)。
8.16 挑战:Server 半死状态
问题:Server 进程活着但卡死(假活),调用全部超时。
解法:
- 心跳探测。
- 连续超时阈值触发重启。
- 熔断 + 半开探测恢复。
8.17 挑战:多版本协议并存
问题:老 Server 只支持旧协议,新 Client 默认新协议。
解法:
- 会话级版本协商(每 Server 独立)。
- 兼容层适配旧协议。
- 升级排期管理,避免强制一刀切。
8.18 挑战:工具链的循环依赖
问题:工具 A 的结果需要工具 B,B 又需要 A(编排死锁)。
解法:
- 编排层检测循环依赖。
- 限制调用深度。
- 失败时明确报"依赖循环",不无限重试。
8.19 挑战:成本失控
问题:高频调用产生大量 API 费用(尤其 LLM 与外部付费 API)。
解法:
- 每 Server/每工具配额。
- 结果缓存减少重复调用。
- 成本看板 + 异常告警。
8.20 挑战:安全性纵深的落实
把安全落实到发现-调用全链路:
| 发现 | 按身份过滤工具 |
| 注册 | destructive 标注 |
| 调用 | 参数校验 + 二次确认 |
| 结果 | 脱敏 + 注入扫描 |
| 审计 | 全量调用留痕 |
8.21 挑战:可观测的端到端
#mermaid-svg-49reM8D04zms3rd9{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-49reM8D04zms3rd9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-49reM8D04zms3rd9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-49reM8D04zms3rd9 .error-icon{fill:#552222;}#mermaid-svg-49reM8D04zms3rd9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-49reM8D04zms3rd9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-49reM8D04zms3rd9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-49reM8D04zms3rd9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-49reM8D04zms3rd9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-49reM8D04zms3rd9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-49reM8D04zms3rd9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-49reM8D04zms3rd9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-49reM8D04zms3rd9 .marker.cross{stroke:#333333;}#mermaid-svg-49reM8D04zms3rd9 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-49reM8D04zms3rd9 p{margin:0;}#mermaid-svg-49reM8D04zms3rd9 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-49reM8D04zms3rd9 .cluster-label text{fill:#333;}#mermaid-svg-49reM8D04zms3rd9 .cluster-label span{color:#333;}#mermaid-svg-49reM8D04zms3rd9 .cluster-label span p{background-color:transparent;}#mermaid-svg-49reM8D04zms3rd9 .label text,#mermaid-svg-49reM8D04zms3rd9 span{fill:#333;color:#333;}#mermaid-svg-49reM8D04zms3rd9 .node rect,#mermaid-svg-49reM8D04zms3rd9 .node circle,#mermaid-svg-49reM8D04zms3rd9 .node ellipse,#mermaid-svg-49reM8D04zms3rd9 .node polygon,#mermaid-svg-49reM8D04zms3rd9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-49reM8D04zms3rd9 .rough-node .label text,#mermaid-svg-49reM8D04zms3rd9 .node .label text,#mermaid-svg-49reM8D04zms3rd9 .image-shape .label,#mermaid-svg-49reM8D04zms3rd9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-49reM8D04zms3rd9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-49reM8D04zms3rd9 .rough-node .label,#mermaid-svg-49reM8D04zms3rd9 .node .label,#mermaid-svg-49reM8D04zms3rd9 .image-shape .label,#mermaid-svg-49reM8D04zms3rd9 .icon-shape .label{text-align:center;}#mermaid-svg-49reM8D04zms3rd9 .node.clickable{cursor:pointer;}#mermaid-svg-49reM8D04zms3rd9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-49reM8D04zms3rd9 .arrowheadPath{fill:#333333;}#mermaid-svg-49reM8D04zms3rd9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-49reM8D04zms3rd9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-49reM8D04zms3rd9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-49reM8D04zms3rd9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-49reM8D04zms3rd9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-49reM8D04zms3rd9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-49reM8D04zms3rd9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-49reM8D04zms3rd9 .cluster text{fill:#333;}#mermaid-svg-49reM8D04zms3rd9 .cluster span{color:#333;}#mermaid-svg-49reM8D04zms3rd9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-49reM8D04zms3rd9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-49reM8D04zms3rd9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-49reM8D04zms3rd9 .icon-shape,#mermaid-svg-49reM8D04zms3rd9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-49reM8D04zms3rd9 .icon-shape p,#mermaid-svg-49reM8D04zms3rd9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-49reM8D04zms3rd9 .icon-shape .label rect,#mermaid-svg-49reM8D04zms3rd9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-49reM8D04zms3rd9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-49reM8D04zms3rd9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-49reM8D04zms3rd9 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Agent 调用
Client 打点
注册表命中率
调用延迟
错误码分布
配额使用
看板/告警
8.22 挑战:排障手册速查
| 工具找不到 | 注册表过期 | 刷新清单 |
| 调用全超时 | Server 假活 | 心跳+重启 |
| 参数被拒 | schema 漂移 | 重拉清单 |
| 结果乱码 | 编码问题 | 检查 UTF-8 |
| 偶发失败 | 网络抖动 | 查重试日志 |
8.23 挑战:清单(挑战对照)
| 发现风暴 | 缓存+通知 |
| 路由冲突 | 前缀+优先级 |
| Schema 漂移 | 哈希校验+重拉 |
| 调用超时 | 分级超时+退避 |
| 写操作重复 | 幂等键 |
| 幻觉调用 | 未命中返回清单 |
| 参数注入 | 白名单+消毒 |
| 时序竞态 | 失败刷新重试 |
| 并发一致 | 原子替换 |
| 跨 Server 事务 | 补偿事务 |
| 结果过大 | 分页+摘要 |
| Server 假活 | 心跳+熔断 |
| 版本并存 | 会话级协商 |
| 循环依赖 | 编排检测 |
| 成本失控 | 配额+缓存 |
| 越权 | 权限联动 |
8.25 挑战:多 Server 的时钟与顺序
分布式场景下,跨 Server 的事件顺序(先建 Issue 再通知)可能因时钟偏差错乱。解法:编排层用逻辑时钟/单调序号,不依赖墙钟排序;重要顺序操作串行化。
8.26 挑战:工具结果的语言与格式
Server 返回英文、中文、HTML 混杂,Agent 解析易错。解法:Client 统一转纯文本/标准结构;Server 声明结果语言;超长 HTML 转摘要。
8.27 挑战:配额突增
业务高峰所有 Agent 同时调工具,配额瞬间耗尽。解法:配额预留 + 优先级排队;关键任务优先;低优先级任务降级或延后。
8.28 挑战:依赖外部 API 的 Server 抖动
GitHub Server 本身依赖 GitHub API,外部抖动传导到工具调用。解法:Server 侧做外部调用缓存/熔断;Client 侧对慢 Server 限流;编排层容忍部分失败。
8.29 挑战:测试环境与生产的工具差异
测试 Server 和生产 Server 工具集不同,Agent 在测试环境学到的行为到生产失效。解法:环境对齐(工具集一致);契约测试覆盖两环境;配置中心统一管理环境差异。
8.30 挑战:安全审计的合规要求
金融/医疗场景要求工具调用可审计、可回溯、可解释。解法:全量审计 + 结果留档;destructive 操作双人复核(HITL);定期合规审查工具权限。
8.31 挑战:本章小结(终版)
工具发现与调用的挑战覆盖发现效率、路由准确性、契约一致性、调用韧性、安全、可观测、成本、事务,以及时钟顺序、语言格式、配额突增、外部依赖、环境差异、合规审计。解法组合:缓存+通知、前缀+优先级、哈希校验、退避+幂等、权限联动、补偿事务、全链路 trace、配额预留、环境对齐、审计留档。
第 9 章 通俗案例深度解析
9.1 案例全景:智能运维机器人
以一个"运维机器人"为主线,演示完整四阶段。机器人连接 GitHub、Slack、数据库三个 Server,任务:检查线上仓库是否有高危漏洞,有则建 Issue 并通知运维群。
Slack数据库GitHubMCP Client运维机器人Slack数据库GitHubMCP Client运维机器人#mermaid-svg-vbbhaoaL5Bh7N2IW{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vbbhaoaL5Bh7N2IW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vbbhaoaL5Bh7N2IW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vbbhaoaL5Bh7N2IW .error-icon{fill:#552222;}#mermaid-svg-vbbhaoaL5Bh7N2IW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vbbhaoaL5Bh7N2IW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vbbhaoaL5Bh7N2IW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vbbhaoaL5Bh7N2IW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vbbhaoaL5Bh7N2IW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vbbhaoaL5Bh7N2IW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vbbhaoaL5Bh7N2IW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vbbhaoaL5Bh7N2IW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vbbhaoaL5Bh7N2IW .marker.cross{stroke:#333333;}#mermaid-svg-vbbhaoaL5Bh7N2IW svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vbbhaoaL5Bh7N2IW p{margin:0;}#mermaid-svg-vbbhaoaL5Bh7N2IW .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-vbbhaoaL5Bh7N2IW text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-vbbhaoaL5Bh7N2IW .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-vbbhaoaL5Bh7N2IW .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-vbbhaoaL5Bh7N2IW .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-vbbhaoaL5Bh7N2IW .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-vbbhaoaL5Bh7N2IW #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-vbbhaoaL5Bh7N2IW .sequenceNumber{fill:white;}#mermaid-svg-vbbhaoaL5Bh7N2IW #sequencenumber{fill:#333;}#mermaid-svg-vbbhaoaL5Bh7N2IW #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-vbbhaoaL5Bh7N2IW .messageText{fill:#333;stroke:none;}#mermaid-svg-vbbhaoaL5Bh7N2IW .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-vbbhaoaL5Bh7N2IW .labelText,#mermaid-svg-vbbhaoaL5Bh7N2IW .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-vbbhaoaL5Bh7N2IW .loopText,#mermaid-svg-vbbhaoaL5Bh7N2IW .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-vbbhaoaL5Bh7N2IW .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-vbbhaoaL5Bh7N2IW .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-vbbhaoaL5Bh7N2IW .noteText,#mermaid-svg-vbbhaoaL5Bh7N2IW .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-vbbhaoaL5Bh7N2IW .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-vbbhaoaL5Bh7N2IW .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-vbbhaoaL5Bh7N2IW .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-vbbhaoaL5Bh7N2IW .actorPopupMenu{position:absolute;}#mermaid-svg-vbbhaoaL5Bh7N2IW .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-vbbhaoaL5Bh7N2IW .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-vbbhaoaL5Bh7N2IW .actor-man circle,#mermaid-svg-vbbhaoaL5Bh7N2IW line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-vbbhaoaL5Bh7N2IW :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}阶段1+2: 初始化与发现阶段3: 注册阶段4: 调用启动initialize + tools/listinitialize + tools/listinitialize + tools/list注册表: search_code→G, execute_query→D, send_message→Scall_tool(execute_query, 查漏洞)tools/call发现3个高危依赖call_tool(create_issue)tools/callIssuecall_tool(send_message)tools/call
9.2 案例细节一:发现阶段的"菜单"
机器人启动时,三个 Server 的"菜单"长这样:
- GitHub:search_code、get_file_contents、create_issue、list_pulls、merge_pull…
- 数据库:execute_query、explain_query、list_tables、describe_table…
- Slack:send_message、list_channels、create_channel…
机器人不需要预知这些名字——它运行起来看菜单(tools/list)才知道。
9.3 案例细节二:路由的"秒查"
调用 execute_query 时,Client 查注册表直接命中数据库 Server,耗时 <1ms。如果没注册表,Client 得问三个 Server"你有没有 execute_query",慢一个数量级。
9.4 案例细节三:schema 帮机器人"学会填参数"
机器人第一次调用 create_issue 时,靠 inputSchema 知道要填 repo/title/body,还知道 labels 是可选枚举。这就是"能力协商"——不需要写死调用代码。
9.5 案例细节四:失败与重试
第一次查数据库超时(慢查询),Client 按退避重试一次成功。如果连续失败,熔断器打开,机器人改为降级方案(用 GitHub 的 search_code 找配置确认)。
9.6 案例细节五:安全问题
create_issue 是写操作,注册表标记为非 destructive(可自动执行);而 delete_issue、merge_pull 等破坏性操作则要求二次确认,防止 Agent 误操作。
9.7 微案例:新 Server 即插即用
周五上线"日历 Server",机器人重新发现一次,注册表新增 list_events、create_event。周一开始,机器人已能"查漏洞→建 Issue→通知→顺手创建跟进日程"——零代码改动。
9.8 微案例:工具更名
GitHub Server 把 get_file_contents 改名为 read_file,并推送变更通知。Client 刷新注册表,旧名调用自动失效——Agent 重新发现后使用新名,全程无感。
9.9 微案例:权限差异
同一 Server 对"管理员会话"暴露 20 个工具,对"访客会话"只暴露 8 个。Client 按会话缓存不同注册表,访客机器人永远查不到危险工具——权限在发现层就隔离了。
9.10 反例:硬编码工具名
某 Agent 代码里写死 call_tool("get_file_contents"),Server 改名后直接报 MethodNotFound。修正:Agent 应基于最新发现结果选择工具名,而非写死。
9.11 反例:无缓存疯狂发现
某 Client 每次调用前都 tools/list 全量拉取,10 个 Server × 每次 50ms = 500ms 固定开销。修正:缓存 + TTL + 变更通知,把发现从"每次"降为"必要时"。
9.12 反例:忽略 isError
某 Agent 把 isError: true 的结果当成功继续推理,把"创建 Issue 失败"当成"已创建",通知群说完成了。修正:Agent 必须先检查 isError,再决定后续动作。
9.14 案例深拆:多 Agent 协作中的共享注册表
大型系统里,多个 Agent 共享一个 MCP Client 与路由注册表(如平台级编排)。此时注册表成为"公共设施":
#mermaid-svg-IVMIHjGx2X3RuVhJ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IVMIHjGx2X3RuVhJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IVMIHjGx2X3RuVhJ .error-icon{fill:#552222;}#mermaid-svg-IVMIHjGx2X3RuVhJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IVMIHjGx2X3RuVhJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IVMIHjGx2X3RuVhJ .marker.cross{stroke:#333333;}#mermaid-svg-IVMIHjGx2X3RuVhJ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IVMIHjGx2X3RuVhJ p{margin:0;}#mermaid-svg-IVMIHjGx2X3RuVhJ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-IVMIHjGx2X3RuVhJ .cluster-label text{fill:#333;}#mermaid-svg-IVMIHjGx2X3RuVhJ .cluster-label span{color:#333;}#mermaid-svg-IVMIHjGx2X3RuVhJ .cluster-label span p{background-color:transparent;}#mermaid-svg-IVMIHjGx2X3RuVhJ .label text,#mermaid-svg-IVMIHjGx2X3RuVhJ span{fill:#333;color:#333;}#mermaid-svg-IVMIHjGx2X3RuVhJ .node rect,#mermaid-svg-IVMIHjGx2X3RuVhJ .node circle,#mermaid-svg-IVMIHjGx2X3RuVhJ .node ellipse,#mermaid-svg-IVMIHjGx2X3RuVhJ .node polygon,#mermaid-svg-IVMIHjGx2X3RuVhJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IVMIHjGx2X3RuVhJ .rough-node .label text,#mermaid-svg-IVMIHjGx2X3RuVhJ .node .label text,#mermaid-svg-IVMIHjGx2X3RuVhJ .image-shape .label,#mermaid-svg-IVMIHjGx2X3RuVhJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-IVMIHjGx2X3RuVhJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IVMIHjGx2X3RuVhJ .rough-node .label,#mermaid-svg-IVMIHjGx2X3RuVhJ .node .label,#mermaid-svg-IVMIHjGx2X3RuVhJ .image-shape .label,#mermaid-svg-IVMIHjGx2X3RuVhJ .icon-shape .label{text-align:center;}#mermaid-svg-IVMIHjGx2X3RuVhJ .node.clickable{cursor:pointer;}#mermaid-svg-IVMIHjGx2X3RuVhJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IVMIHjGx2X3RuVhJ .arrowheadPath{fill:#333333;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IVMIHjGx2X3RuVhJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IVMIHjGx2X3RuVhJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IVMIHjGx2X3RuVhJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IVMIHjGx2X3RuVhJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IVMIHjGx2X3RuVhJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IVMIHjGx2X3RuVhJ .cluster text{fill:#333;}#mermaid-svg-IVMIHjGx2X3RuVhJ .cluster span{color:#333;}#mermaid-svg-IVMIHjGx2X3RuVhJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IVMIHjGx2X3RuVhJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IVMIHjGx2X3RuVhJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-IVMIHjGx2X3RuVhJ .icon-shape,#mermaid-svg-IVMIHjGx2X3RuVhJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IVMIHjGx2X3RuVhJ .icon-shape p,#mermaid-svg-IVMIHjGx2X3RuVhJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IVMIHjGx2X3RuVhJ .icon-shape .label rect,#mermaid-svg-IVMIHjGx2X3RuVhJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IVMIHjGx2X3RuVhJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IVMIHjGx2X3RuVhJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IVMIHjGx2X3RuVhJ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Agent1 运维
共享 Client/注册表
Agent2 数据分析
Agent3 客服
GitHub Server
Slack Server
数据库 Server
文件系统 Server
好处:发现一次、全员复用;权限按 Agent 身份隔离;配额按 Agent 分配。这是"工具即服务(TaaS)"的雏形。
9.15 案例深拆:注册表命中率与幻觉预防
某平台观察到"工具未命中"错误率 12%,排查发现:Agent 在上下文里看到的工具清单是旧版,而注册表已更新。修复:
#mermaid-svg-jUVFmPcWMWioAEqV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jUVFmPcWMWioAEqV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jUVFmPcWMWioAEqV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jUVFmPcWMWioAEqV .error-icon{fill:#552222;}#mermaid-svg-jUVFmPcWMWioAEqV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jUVFmPcWMWioAEqV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jUVFmPcWMWioAEqV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jUVFmPcWMWioAEqV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jUVFmPcWMWioAEqV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jUVFmPcWMWioAEqV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jUVFmPcWMWioAEqV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jUVFmPcWMWioAEqV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jUVFmPcWMWioAEqV .marker.cross{stroke:#333333;}#mermaid-svg-jUVFmPcWMWioAEqV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jUVFmPcWMWioAEqV p{margin:0;}#mermaid-svg-jUVFmPcWMWioAEqV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-jUVFmPcWMWioAEqV .cluster-label text{fill:#333;}#mermaid-svg-jUVFmPcWMWioAEqV .cluster-label span{color:#333;}#mermaid-svg-jUVFmPcWMWioAEqV .cluster-label span p{background-color:transparent;}#mermaid-svg-jUVFmPcWMWioAEqV .label text,#mermaid-svg-jUVFmPcWMWioAEqV span{fill:#333;color:#333;}#mermaid-svg-jUVFmPcWMWioAEqV .node rect,#mermaid-svg-jUVFmPcWMWioAEqV .node circle,#mermaid-svg-jUVFmPcWMWioAEqV .node ellipse,#mermaid-svg-jUVFmPcWMWioAEqV .node polygon,#mermaid-svg-jUVFmPcWMWioAEqV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jUVFmPcWMWioAEqV .rough-node .label text,#mermaid-svg-jUVFmPcWMWioAEqV .node .label text,#mermaid-svg-jUVFmPcWMWioAEqV .image-shape .label,#mermaid-svg-jUVFmPcWMWioAEqV .icon-shape .label{text-anchor:middle;}#mermaid-svg-jUVFmPcWMWioAEqV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jUVFmPcWMWioAEqV .rough-node .label,#mermaid-svg-jUVFmPcWMWioAEqV .node .label,#mermaid-svg-jUVFmPcWMWioAEqV .image-shape .label,#mermaid-svg-jUVFmPcWMWioAEqV .icon-shape .label{text-align:center;}#mermaid-svg-jUVFmPcWMWioAEqV .node.clickable{cursor:pointer;}#mermaid-svg-jUVFmPcWMWioAEqV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jUVFmPcWMWioAEqV .arrowheadPath{fill:#333333;}#mermaid-svg-jUVFmPcWMWioAEqV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jUVFmPcWMWioAEqV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jUVFmPcWMWioAEqV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jUVFmPcWMWioAEqV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jUVFmPcWMWioAEqV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jUVFmPcWMWioAEqV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jUVFmPcWMWioAEqV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jUVFmPcWMWioAEqV .cluster text{fill:#333;}#mermaid-svg-jUVFmPcWMWioAEqV .cluster span{color:#333;}#mermaid-svg-jUVFmPcWMWioAEqV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jUVFmPcWMWioAEqV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jUVFmPcWMWioAEqV rect.text{fill:none;stroke-width:0;}#mermaid-svg-jUVFmPcWMWioAEqV .icon-shape,#mermaid-svg-jUVFmPcWMWioAEqV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jUVFmPcWMWioAEqV .icon-shape p,#mermaid-svg-jUVFmPcWMWioAEqV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jUVFmPcWMWioAEqV .icon-shape .label rect,#mermaid-svg-jUVFmPcWMWioAEqV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jUVFmPcWMWioAEqV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jUVFmPcWMWioAEqV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jUVFmPcWMWioAEqV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
修复前: 未命中12%
会话开始强制刷新
未命中返回清单纠正
修复后: 0.5%
9.16 案例深拆:慢工具的超时与进度
某 Agent 调用"数据分析"工具,预计 5 分钟。直接固定 10s 超时必然失败;不设超时又可能挂死。解法:
结果:Agent 能耐心等待长任务,且进度可见。
9.17 案例深拆:权限差异下的发现隔离
同一 GitHub Server:
- 管理员会话发现 20 个工具(含 delete_repo)。
- 只读会话发现 8 个工具(无写操作)。
注册表按会话隔离后,只读 Agent 的上下文里根本不会出现 delete_repo——权限在源头(发现层)就被剪掉了,比"调用时拦截"更安全。
9.18 微案例:工具灰度
新工具 ai_code_review 先对 5% 会话暴露,观察调用成功率与耗时。灰度通过后全量;有问题则从名单移除——不重启 Server,只改发现策略。
9.19 微案例:工具下线
Server 要下架 legacy_export:先推送变更通知 → Client 刷新注册表 → 旧工具调用返回 MethodNotFound → Agent 改用新工具 export_v2。全程平滑过渡。
9.20 微案例:网络分区下的降级
Agent 与 Slack Server 网络分区,注册表中 Slack 工具全部标记"暂不可用"。Agent 改为"先记日志(文件系统 Server),网络恢复后补发"——编排层感知注册表可用性,自动走降级路径。
9.21 微案例:多 Server 的负载均衡
两个数据库 Server(主/读副本)提供同名 execute_query:
execute_query → {server: db-master, weight: 10}
execute_query → {server: db-replica, weight: 90}
Client 按权重路由:读多写少,90% 查询走副本。写操作强制走主库(按工具 meta 的 read_only 判断)。
9.22 推演一:如果发现延迟 10 倍
场景:假设 tools/list 每次都要 500ms。启动时 3 个 Server = 1.5s 阻塞。若改为"懒发现"(用到才拉):
- Agent 第一次要调用 search_code 时才拉 GitHub 清单。
- 调用前多等 500ms,但启动不被阻塞。
结论:懒发现适合"工具用得少"的场景,预发现适合"启动就要用"的场景。工程上常取折中:预发现热门 Server,懒发现冷门 Server。
9.23 推演二:如果注册表没有失效机制
场景:Server 把 create_issue 改名为 create_issue_v2,注册表不刷新。Agent 继续用旧名 → MethodNotFound → 任务失败。如果注册表有"失败触发刷新"机制:第一次失败 → 刷新 → 重试成功。失败驱动刷新是兜底保险。
9.24 推演三:如果调用不校验参数
场景:Agent 传了 repo 但漏了 query(search_code 必填)。不校验直接转发 → Server 报 InvalidParams → Agent 再修正 → 多一次往返。若 Client 本地校验:直接提示"缺 query",Agent 一次修正到位。校验前置省一次往返。
9.25 推演四:如果所有 Server 共用一个会话
场景:把 GitHub 和 Slack 塞进同一会话,工具清单混在一起。问题:权限无法区分(GitHub 的写权限泄露给 Slack 场景)、配额无法独立、故障互相牵连。会话隔离是安全底线——一个 Server 一个会话。
9.26 反例:把发现结果写死在提示词里
某团队把工具清单手工写进系统提示词,Server 更新后提示词没同步 → Agent 用旧工具名 → 全部 MethodNotFound。修正:清单必须来自运行时发现,提示词只描述"怎么选工具",不写死工具名。
9.27 反例:注册表用线性扫描
工具 200 个、Server 10 个,每次调用线性扫一遍 = 2000 次比较。虽然现代 CPU 下也不慢,但哈希表 O(1) 是底线工程素养,且扫描代码容易引入顺序 bug。
9.28 反例:调用结果全量入上下文
每次调用结果原样塞进上下文,20 次调用后 Token 爆掉。修正:结果摘要化、只保留关键字段、长结果外部存储。
9.29 反例:超时一刀切
所有工具统一 10s 超时:慢工具(数据分析)必失败,快工具(查表)浪费等待。修正:按工具 meta 分级超时。
9.30 案例库总结
本篇案例覆盖:四阶段主案例(运维机器人)、共享注册表、命中率优化、慢工具超时、权限隔离、工具灰度/下线、网络降级、负载均衡、四推演、六反例。结论:发现与调用的成败,80% 取决于注册表设计与描述质量,20% 取决于错误处理与降级。
9.32 案例:跨系统工作流"代码审查到发布"
Slack数据库GitHubClientAgentSlack数据库GitHubClientAgent#mermaid-svg-LWb6In3VHYgDb4rS{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LWb6In3VHYgDb4rS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LWb6In3VHYgDb4rS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LWb6In3VHYgDb4rS .error-icon{fill:#552222;}#mermaid-svg-LWb6In3VHYgDb4rS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LWb6In3VHYgDb4rS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LWb6In3VHYgDb4rS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LWb6In3VHYgDb4rS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LWb6In3VHYgDb4rS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LWb6In3VHYgDb4rS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LWb6In3VHYgDb4rS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LWb6In3VHYgDb4rS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LWb6In3VHYgDb4rS .marker.cross{stroke:#333333;}#mermaid-svg-LWb6In3VHYgDb4rS svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LWb6In3VHYgDb4rS p{margin:0;}#mermaid-svg-LWb6In3VHYgDb4rS .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LWb6In3VHYgDb4rS text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-LWb6In3VHYgDb4rS .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LWb6In3VHYgDb4rS .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-LWb6In3VHYgDb4rS .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-LWb6In3VHYgDb4rS .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-LWb6In3VHYgDb4rS #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-LWb6In3VHYgDb4rS .sequenceNumber{fill:white;}#mermaid-svg-LWb6In3VHYgDb4rS #sequencenumber{fill:#333;}#mermaid-svg-LWb6In3VHYgDb4rS #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-LWb6In3VHYgDb4rS .messageText{fill:#333;stroke:none;}#mermaid-svg-LWb6In3VHYgDb4rS .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LWb6In3VHYgDb4rS .labelText,#mermaid-svg-LWb6In3VHYgDb4rS .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-LWb6In3VHYgDb4rS .loopText,#mermaid-svg-LWb6In3VHYgDb4rS .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-LWb6In3VHYgDb4rS .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LWb6In3VHYgDb4rS .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-LWb6In3VHYgDb4rS .noteText,#mermaid-svg-LWb6In3VHYgDb4rS .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-LWb6In3VHYgDb4rS .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LWb6In3VHYgDb4rS .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LWb6In3VHYgDb4rS .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LWb6In3VHYgDb4rS .actorPopupMenu{position:absolute;}#mermaid-svg-LWb6In3VHYgDb4rS .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-LWb6In3VHYgDb4rS .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LWb6In3VHYgDb4rS .actor-man circle,#mermaid-svg-LWb6In3VHYgDb4rS line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-LWb6In3VHYgDb4rS :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}call_tool(list_pulls)tools/callPRcall_tool(get_file_contents)tools/call代码内容call_tool(execute_query, 查历史缺陷率)tools/call缺陷率 3.2%call_tool(create_review_comment)tools/call评论已加call_tool(send_message)tools/call已通知评审人
亮点:Agent 在一次任务里横跨 3 个 Server、5 次调用,全部靠注册表路由 + schema 填参,无一行硬编码。
9.33 案例:发现结果驱动 Agent 提示词
某 Agent 的系统提示词在会话开始时自动拼装工具清单:
当前可用工具:
– GitHub: search_code(搜索代码), create_issue(创建Issue)…
– Slack: send_message(发送消息)…
– 数据库: execute_query(执行查询)…
请根据任务选择合适的工具。
工具清单随发现结果动态变化——这是"能力地图"最直接的落地。
9.34 案例:注册表未命中的兜底体验
Agent 幻觉调用 delete_repo(注册表无此工具,或权限不足),Client 返回:
工具 delete_repo 不存在或不可用。当前可用工具:
– search_code, create_issue, list_pulls, …
请从可用工具中选择。
Agent 据此纠正行为,任务继续而非中断——未命中兜底是 Agent 鲁棒性的关键一环。
9.35 案例:慢工具的进度条
"数据分析"工具运行 4 分钟,Server 每 30s 推进度:
[进度 25%] 正在清洗数据…
[进度 50%] 正在计算指标…
[进度 100%] 分析完成
Agent 看到进度后选择继续等待;Client 依据"有进度"动态续期超时。用户也能看到透明进展。
9.36 微案例:工具搜索在 200 个工具中找"发邮件"
Agent 不把 200 个工具全塞上下文,而是搜索"发邮件":
search("发邮件") → [send_email(SMTP), send_slack_dm(通知)]
只把命中工具的描述给模型,Token 省 90%,选型更准。
9.37 微案例:灰度 5% 暴露新工具
ai_summarize 工具先对 5% 会话暴露,A/B 观察调用成功率与耗时。通过后全量;失败则回滚名单——发现层灰度比部署灰度更轻量。
9.38 微案例:断线重连后工具续用
Agent 与 Server 断线,重连后重新 initialize + tools/list,注册表刷新。正在进行的任务用"幂等键 + 任务状态"续跑,不重复执行写操作。
9.39 推演五:如果发现全部走懒加载
场景:Agent 启动不做任何发现,用到才拉对应 Server 清单。好处:启动秒开。代价:首次调用慢。结论:混合策略最优——热门 Server 预发现,冷门懒发现。
9.40 推演六:如果注册表命中率 80%
场景:20% 调用未命中,每次都要"查表失败→刷新→重试"。任务耗时平均 +40%。结论:注册表命中率是核心健康指标,低于 99% 就要排查清单同步问题。
9.41 反例:不区分身份缓存清单
某 Client 把管理员会话的清单缓存给访客会话用 → 访客看到了危险工具名 → 尝试调用被拒。修正:缓存与身份绑定。
9.42 反例:忽略工具下线通知
Server 推送了 list_changed,Client 没处理 → 旧工具调用失败率上升。修正:实现变更通知处理。
9.43 反例:审计日志为空
出了安全事故想追责,发现没有调用审计。修正:启用全量审计(who/what/when/args 脱敏)。
9.44 案例库总结(终版)
案例覆盖:四阶段主案例、跨系统工作流、动态提示词、未命中兜底、慢工具进度、工具搜索、灰度暴露、断线续用、六推演、八反例。结论:发现与调用的成败,80% 取决于注册表设计与描述质量,20% 取决于错误处理与降级。
9.45 本章小结(终版)
通过运维机器人案例,四阶段流程从抽象变具体:初始化连菜单、发现看菜单、注册记菜单、调用点菜。深挖覆盖跨系统工作流、动态提示词、未命中兜底、进度反馈、工具搜索、灰度、断线续用、六推演、八反例——动态发现的三大价值(即插即用/变更无感/权限隔离)与完整避坑清单。
第 10 章 本章小结与全链路衔接
10.1 核心要点回顾
10.2 与 25/26 篇的衔接
- 25 篇给了连接协议层的"骨架"(为什么有这层、谁来管)。
- 26 篇给了协议"语法"(消息、方法、原语)。
- 本篇给了运行时"编舞"(发现与调用的流程编排)。
- 28 篇将深入三个典型 Server 的"工具树"长什么样。
10.3 自测题
10.4 工程检查单
- 启动时对所有 Server 完成 initialize 与 tools/list。
- 注册表覆盖全部工具,冲突已处理。
- 缓存 + TTL + 变更通知已配置。
- 调用前按 schema 校验参数。
- 写操作支持幂等键。
- 熔断/舱壁/限流按 Server 维度配置。
- trace 覆盖发现与调用全链路。
- destructive 工具二次确认已启用。
10.6 四阶段速记卡
| 初始化 | 建会话 | initialize | 打通通道 |
| 发现 | 拉清单 | tools/list | 看菜单 |
| 注册 | 建路由 | Client 内部 | 记菜单 |
| 调用 | 执行 | tools/call | 点菜 |
10.7 关键设计决策清单(ADR 风格)
| 发现时机 | 启动/懒/定时/通知 | 通知驱动+启动预发现 |
| 注册表存储 | 内存/分布式 | 单 Client 内存即可 |
| 冲突处理 | 前缀/优先级/告警 | 前缀优先 |
| 超时策略 | 统一/分级 | 按工具 meta 分级 |
| 重试策略 | 统一/按错误 | 按错误类型矩阵 |
| 写操作幂等 | 支持/不支持 | 必须支持 |
10.8 常见面试题
10.9 FAQ
Q1:发现一次还是每次都发现?
缓存 + 通知驱动刷新;失败时强制刷新兜底。
Q2:注册表放 Client 还是独立服务?
小场景 Client 内;平台级可独立服务共享。
Q3:同名工具一定冲突吗?
不一定,可合并/折叠;冲突时前缀或优先级。
Q4:调用失败就重试?
看错误类型:参数错不重试,网络/限流退避重试。
Q5:Server 挂了怎么办?
熔断 + 降级 + 备用 Server;编排层感知可用性。
10.10 端到端示例:一次完整的"查漏洞并通知"
SlackGitHub数据库注册表ClientAgent用户SlackGitHub数据库注册表ClientAgent用户#mermaid-svg-Dy4qnSb7SmsyABtu{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Dy4qnSb7SmsyABtu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Dy4qnSb7SmsyABtu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Dy4qnSb7SmsyABtu .error-icon{fill:#552222;}#mermaid-svg-Dy4qnSb7SmsyABtu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Dy4qnSb7SmsyABtu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Dy4qnSb7SmsyABtu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Dy4qnSb7SmsyABtu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Dy4qnSb7SmsyABtu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Dy4qnSb7SmsyABtu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Dy4qnSb7SmsyABtu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Dy4qnSb7SmsyABtu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Dy4qnSb7SmsyABtu .marker.cross{stroke:#333333;}#mermaid-svg-Dy4qnSb7SmsyABtu svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Dy4qnSb7SmsyABtu p{margin:0;}#mermaid-svg-Dy4qnSb7SmsyABtu .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Dy4qnSb7SmsyABtu text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-Dy4qnSb7SmsyABtu .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Dy4qnSb7SmsyABtu .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-Dy4qnSb7SmsyABtu .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-Dy4qnSb7SmsyABtu .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-Dy4qnSb7SmsyABtu #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-Dy4qnSb7SmsyABtu .sequenceNumber{fill:white;}#mermaid-svg-Dy4qnSb7SmsyABtu #sequencenumber{fill:#333;}#mermaid-svg-Dy4qnSb7SmsyABtu #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-Dy4qnSb7SmsyABtu .messageText{fill:#333;stroke:none;}#mermaid-svg-Dy4qnSb7SmsyABtu .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Dy4qnSb7SmsyABtu .labelText,#mermaid-svg-Dy4qnSb7SmsyABtu .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-Dy4qnSb7SmsyABtu .loopText,#mermaid-svg-Dy4qnSb7SmsyABtu .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-Dy4qnSb7SmsyABtu .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Dy4qnSb7SmsyABtu .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Dy4qnSb7SmsyABtu .noteText,#mermaid-svg-Dy4qnSb7SmsyABtu .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-Dy4qnSb7SmsyABtu .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Dy4qnSb7SmsyABtu .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Dy4qnSb7SmsyABtu .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Dy4qnSb7SmsyABtu .actorPopupMenu{position:absolute;}#mermaid-svg-Dy4qnSb7SmsyABtu .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-Dy4qnSb7SmsyABtu .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Dy4qnSb7SmsyABtu .actor-man circle,#mermaid-svg-Dy4qnSb7SmsyABtu line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-Dy4qnSb7SmsyABtu :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}检查线上高危漏洞启动/发现/注册(若未就绪)initialize + tools/listinitialize + tools/listinitialize + tools/list注册全部工具call_tool(execute_query, 查漏洞)命中 → 数据库tools/call3 个高危依赖call_tool(create_issue, 建Issue)tools/callIssuecall_tool(send_message, 通知群)tools/call已发送全部完成已建Issue并通知
10.11 度量指标
| 注册表命中率 | >99.5% | Client |
| 发现耗时 | <100ms | Client |
| 调用成功率 | >99% | Client |
| 未命中率 | <1% | Client |
| 平均调用延迟 | 按工具 | Server |
| 熔断次数 | 极少 | Client |
10.12 工程落地建议(按优先级)
10.13 反模式速查
| 每次调用都发现 | 缓存+通知 |
| 工具名写死 | 动态发现 |
| 忽略 isError | 检查结果 |
| 统一超时 | 分级超时 |
| 无幂等键 | 写操作幂等 |
| 全量入上下文 | 摘要化 |
10.14 术语终表
| Discovery | 工具发现 |
| Invocation | 工具调用 |
| Registry | 路由注册表 |
| Schema | 参数结构描述 |
| Capability | 能力声明 |
| Idempotency | 幂等性 |
10.15 本篇贡献
源 6.4 扩展:核心概念、四阶段深挖、注册表深拆、发现/调用机制、多 Server 编排、16+ 挑战、案例库(1 主案例 + 10 深拆/微案例 + 4 推演 + 6 反例)。
10.16 衔接下篇
第 28 篇讲典型 MCP Server 详解(源 6.5):GitHub/数据库/浏览器的工具树长什么样,把本篇的"发现结果"落成具体清单。
10.17 金句
发现解决"有什么可用",调用解决"怎么用起来",注册表解决"找谁用"。
10.18 新人计划
读 2→3→4 理解流程;跑 9 章运维机器人案例;用 10.12 清单落地。
10.19 性能调优
缓存、懒发现、并行初始化、结果摘要、工具搜索。
10.20 安全加固
权限过滤、destructive 标注、参数校验、注入扫描、审计。
10.21 故障演练
杀 Server、断网络、改 schema、超时注入、限流触发。
10.22 检查单总表
初始化/发现/注册/调用/隔离/配额/可观测/安全(25 篇 9 扩展)。
10.23 速记卡 v2
四阶段、三要素(参数/路由/Server)、双保障(缓存/幂等)。
10.24 结语
工具发现与调用是 Agent"长出双手"的过程:协议给了手,流程让手听话。下一篇看三只典型的手长什么样。
10.25 与行动层(第 7 章)的衔接
源文档第 7 章(行动层,30 篇起)讲工具背后的真实执行器:API 调用、代码沙箱、数据库操作等。本篇的"调用"是协议层面的流转,行动层的"执行"是业务层面的落地——两者通过 tools/call 无缝衔接:Client 路由到位,Server 内部再把调用转成真实的执行器动作。
10.26 全链路速览(一篇看懂)
#mermaid-svg-F5lnXCPfLTHfqBmL{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-F5lnXCPfLTHfqBmL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-F5lnXCPfLTHfqBmL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-F5lnXCPfLTHfqBmL .error-icon{fill:#552222;}#mermaid-svg-F5lnXCPfLTHfqBmL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-F5lnXCPfLTHfqBmL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-F5lnXCPfLTHfqBmL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-F5lnXCPfLTHfqBmL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-F5lnXCPfLTHfqBmL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-F5lnXCPfLTHfqBmL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-F5lnXCPfLTHfqBmL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-F5lnXCPfLTHfqBmL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-F5lnXCPfLTHfqBmL .marker.cross{stroke:#333333;}#mermaid-svg-F5lnXCPfLTHfqBmL svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-F5lnXCPfLTHfqBmL p{margin:0;}#mermaid-svg-F5lnXCPfLTHfqBmL .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-F5lnXCPfLTHfqBmL .cluster-label text{fill:#333;}#mermaid-svg-F5lnXCPfLTHfqBmL .cluster-label span{color:#333;}#mermaid-svg-F5lnXCPfLTHfqBmL .cluster-label span p{background-color:transparent;}#mermaid-svg-F5lnXCPfLTHfqBmL .label text,#mermaid-svg-F5lnXCPfLTHfqBmL span{fill:#333;color:#333;}#mermaid-svg-F5lnXCPfLTHfqBmL .node rect,#mermaid-svg-F5lnXCPfLTHfqBmL .node circle,#mermaid-svg-F5lnXCPfLTHfqBmL .node ellipse,#mermaid-svg-F5lnXCPfLTHfqBmL .node polygon,#mermaid-svg-F5lnXCPfLTHfqBmL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-F5lnXCPfLTHfqBmL .rough-node .label text,#mermaid-svg-F5lnXCPfLTHfqBmL .node .label text,#mermaid-svg-F5lnXCPfLTHfqBmL .image-shape .label,#mermaid-svg-F5lnXCPfLTHfqBmL .icon-shape .label{text-anchor:middle;}#mermaid-svg-F5lnXCPfLTHfqBmL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-F5lnXCPfLTHfqBmL .rough-node .label,#mermaid-svg-F5lnXCPfLTHfqBmL .node .label,#mermaid-svg-F5lnXCPfLTHfqBmL .image-shape .label,#mermaid-svg-F5lnXCPfLTHfqBmL .icon-shape .label{text-align:center;}#mermaid-svg-F5lnXCPfLTHfqBmL .node.clickable{cursor:pointer;}#mermaid-svg-F5lnXCPfLTHfqBmL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-F5lnXCPfLTHfqBmL .arrowheadPath{fill:#333333;}#mermaid-svg-F5lnXCPfLTHfqBmL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-F5lnXCPfLTHfqBmL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-F5lnXCPfLTHfqBmL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-F5lnXCPfLTHfqBmL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-F5lnXCPfLTHfqBmL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-F5lnXCPfLTHfqBmL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-F5lnXCPfLTHfqBmL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-F5lnXCPfLTHfqBmL .cluster text{fill:#333;}#mermaid-svg-F5lnXCPfLTHfqBmL .cluster span{color:#333;}#mermaid-svg-F5lnXCPfLTHfqBmL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-F5lnXCPfLTHfqBmL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-F5lnXCPfLTHfqBmL rect.text{fill:none;stroke-width:0;}#mermaid-svg-F5lnXCPfLTHfqBmL .icon-shape,#mermaid-svg-F5lnXCPfLTHfqBmL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-F5lnXCPfLTHfqBmL .icon-shape p,#mermaid-svg-F5lnXCPfLTHfqBmL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-F5lnXCPfLTHfqBmL .icon-shape .label rect,#mermaid-svg-F5lnXCPfLTHfqBmL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-F5lnXCPfLTHfqBmL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-F5lnXCPfLTHfqBmL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-F5lnXCPfLTHfqBmL :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
Agent决策
选择工具
call_tool
注册表路由
Server执行
结果回传
Agent推理
继续?
任务完成
10.27 关键成功因素(CSF)
10.28 团队协作分工
| Server 开发者 | 写好 description/schema |
| Client 开发者 | 注册表/校验/重试 |
| 平台运维 | 配额/灰度/可观测 |
| Agent 工程师 | 工具选择与编排 |
10.29 版本演进建议
- v1:单 Server,跑通四阶段。
- v2:多 Server + 注册表 + 缓存。
- v3:熔断/配额/灰度/可观测。
- v4:工具搜索 + 成本控制 + 治理。
10.30 本篇金句汇总
- 发现解决"有什么可用",调用解决"怎么用起来"。
- 描述是工具的销售文案,schema 是参数说明书。
- 注册表让调用从"遍历猜"变成"查表直达"。
10.32 速记卡 v3
- 四阶段:初始化/发现/注册/调用。
- 三要素:参数对、路由准、Server 稳。
- 双保障:缓存刷新、幂等重试。
- 一底线:权限过滤、审计留痕。
10.33 结语
工具发现与调用是 Agent"长出双手"的过程:协议给了手,流程让手听话。路由注册表是这双手的神经中枢——查表即达、失败可救、越权被拦。下一篇看三只典型的手(GitHub/数据库/浏览器 Server)长什么样。
10.35 术语对照
| 工具发现 | Tool Discovery | tools/list |
| 工具调用 | Tool Invocation | tools/call |
| 路由注册表 | Routing Registry | 工具→Server |
| 能力协商 | Capability Negotiation | schema 填参 |
10.36 三分钟回顾
10.37 结语
工具发现与调用是 Agent"长出双手"的过程:协议给了手,流程让手听话。路由注册表是神经中枢——查表即达、失败可救、越权被拦。下一篇看三只典型的手(GitHub/数据库/浏览器 Server)长什么样。
网硕互联帮助中心




评论前必须登录!
注册