1. 先给结论
一个成熟 MCP 系统通常不是"把所有 REST API 原样暴露为工具",而是分成四层:
#mermaid-svg-1hWXZpZiRDSLO131{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-1hWXZpZiRDSLO131 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1hWXZpZiRDSLO131 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1hWXZpZiRDSLO131 .error-icon{fill:#552222;}#mermaid-svg-1hWXZpZiRDSLO131 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1hWXZpZiRDSLO131 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1hWXZpZiRDSLO131 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1hWXZpZiRDSLO131 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1hWXZpZiRDSLO131 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1hWXZpZiRDSLO131 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1hWXZpZiRDSLO131 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1hWXZpZiRDSLO131 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1hWXZpZiRDSLO131 .marker.cross{stroke:#333333;}#mermaid-svg-1hWXZpZiRDSLO131 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1hWXZpZiRDSLO131 p{margin:0;}#mermaid-svg-1hWXZpZiRDSLO131 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1hWXZpZiRDSLO131 .cluster-label text{fill:#333;}#mermaid-svg-1hWXZpZiRDSLO131 .cluster-label span{color:#333;}#mermaid-svg-1hWXZpZiRDSLO131 .cluster-label span p{background-color:transparent;}#mermaid-svg-1hWXZpZiRDSLO131 .label text,#mermaid-svg-1hWXZpZiRDSLO131 span{fill:#333;color:#333;}#mermaid-svg-1hWXZpZiRDSLO131 .node rect,#mermaid-svg-1hWXZpZiRDSLO131 .node circle,#mermaid-svg-1hWXZpZiRDSLO131 .node ellipse,#mermaid-svg-1hWXZpZiRDSLO131 .node polygon,#mermaid-svg-1hWXZpZiRDSLO131 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1hWXZpZiRDSLO131 .rough-node .label text,#mermaid-svg-1hWXZpZiRDSLO131 .node .label text,#mermaid-svg-1hWXZpZiRDSLO131 .image-shape .label,#mermaid-svg-1hWXZpZiRDSLO131 .icon-shape .label{text-anchor:middle;}#mermaid-svg-1hWXZpZiRDSLO131 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1hWXZpZiRDSLO131 .rough-node .label,#mermaid-svg-1hWXZpZiRDSLO131 .node .label,#mermaid-svg-1hWXZpZiRDSLO131 .image-shape .label,#mermaid-svg-1hWXZpZiRDSLO131 .icon-shape .label{text-align:center;}#mermaid-svg-1hWXZpZiRDSLO131 .node.clickable{cursor:pointer;}#mermaid-svg-1hWXZpZiRDSLO131 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1hWXZpZiRDSLO131 .arrowheadPath{fill:#333333;}#mermaid-svg-1hWXZpZiRDSLO131 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1hWXZpZiRDSLO131 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1hWXZpZiRDSLO131 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1hWXZpZiRDSLO131 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1hWXZpZiRDSLO131 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1hWXZpZiRDSLO131 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1hWXZpZiRDSLO131 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1hWXZpZiRDSLO131 .cluster text{fill:#333;}#mermaid-svg-1hWXZpZiRDSLO131 .cluster span{color:#333;}#mermaid-svg-1hWXZpZiRDSLO131 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-1hWXZpZiRDSLO131 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1hWXZpZiRDSLO131 rect.text{fill:none;stroke-width:0;}#mermaid-svg-1hWXZpZiRDSLO131 .icon-shape,#mermaid-svg-1hWXZpZiRDSLO131 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1hWXZpZiRDSLO131 .icon-shape p,#mermaid-svg-1hWXZpZiRDSLO131 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1hWXZpZiRDSLO131 .icon-shape .label rect,#mermaid-svg-1hWXZpZiRDSLO131 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1hWXZpZiRDSLO131 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1hWXZpZiRDSLO131 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1hWXZpZiRDSLO131 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户
Host / Agent 应用
MCP Client
统一 MCP Gateway
认证、鉴权、限流、审计、协议
Registry / Control Plane
工具契约、版本、路由、策略
业务 Compose / Orchestrator
受控业务能力、聚合、流程
Atomic Adapter
单一上游 API / 数据源
业务 API / SaaS
数据库 / 搜索 / 向量库
消息、文件、工作流
最常见的成熟分工是:
| 层 | 核心职责 | 不应承担的职责 |
|---|---|---|
| Host / Agent | 理解用户意图、选工具、组织回答、请求确认 | 信任用户提供的权限范围、自由拼 SQL |
| MCP Gateway | 协议入口、可信身份、授权、审计、限流、统一错误 | 硬编码每个业务工具的业务规则 |
| Registry | 工具事实源、Schema、版本、可见性、路由与 Agent 元数据 | 执行具体业务逻辑 |
| Atomic Adapter | 对一个上游数据源/API 的薄适配 | 面向用户编排复杂业务流程 |
| Compose | 组合多个原子能力,完成业务投影、聚合、流程和安全收敛 | 放开任意上游/任意 SQL |
成熟度的关键不在"工具数量",而在于是否做到:
- 工具契约稳定、边界清晰、Agent 易于选择;
- 身份、数据权限和审批来自可信服务端上下文;
- 大结果不灌入模型上下文;
- 写操作可确认、可幂等、可审计、可恢复;
- 远程 MCP 的 OAuth、Token、SSRF 与提示注入风险可控;
- 每一次 Agent 回答都能回溯到工具版本、请求、权限和上游响应。
2. MCP 协议提供什么,不提供什么
2.1 MCP 的核心对象
MCP 是 Host---Client---Server 的 JSON-RPC 协议。一个 Host 可连接多个 Client 实例,每个 Client 再连接一个或多个 Server。
#mermaid-svg-Cgvarb0V1Fpdzilu{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-Cgvarb0V1Fpdzilu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Cgvarb0V1Fpdzilu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Cgvarb0V1Fpdzilu .error-icon{fill:#552222;}#mermaid-svg-Cgvarb0V1Fpdzilu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Cgvarb0V1Fpdzilu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Cgvarb0V1Fpdzilu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Cgvarb0V1Fpdzilu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Cgvarb0V1Fpdzilu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Cgvarb0V1Fpdzilu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Cgvarb0V1Fpdzilu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Cgvarb0V1Fpdzilu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Cgvarb0V1Fpdzilu .marker.cross{stroke:#333333;}#mermaid-svg-Cgvarb0V1Fpdzilu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Cgvarb0V1Fpdzilu p{margin:0;}#mermaid-svg-Cgvarb0V1Fpdzilu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Cgvarb0V1Fpdzilu .cluster-label text{fill:#333;}#mermaid-svg-Cgvarb0V1Fpdzilu .cluster-label span{color:#333;}#mermaid-svg-Cgvarb0V1Fpdzilu .cluster-label span p{background-color:transparent;}#mermaid-svg-Cgvarb0V1Fpdzilu .label text,#mermaid-svg-Cgvarb0V1Fpdzilu span{fill:#333;color:#333;}#mermaid-svg-Cgvarb0V1Fpdzilu .node rect,#mermaid-svg-Cgvarb0V1Fpdzilu .node circle,#mermaid-svg-Cgvarb0V1Fpdzilu .node ellipse,#mermaid-svg-Cgvarb0V1Fpdzilu .node polygon,#mermaid-svg-Cgvarb0V1Fpdzilu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Cgvarb0V1Fpdzilu .rough-node .label text,#mermaid-svg-Cgvarb0V1Fpdzilu .node .label text,#mermaid-svg-Cgvarb0V1Fpdzilu .image-shape .label,#mermaid-svg-Cgvarb0V1Fpdzilu .icon-shape .label{text-anchor:middle;}#mermaid-svg-Cgvarb0V1Fpdzilu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Cgvarb0V1Fpdzilu .rough-node .label,#mermaid-svg-Cgvarb0V1Fpdzilu .node .label,#mermaid-svg-Cgvarb0V1Fpdzilu .image-shape .label,#mermaid-svg-Cgvarb0V1Fpdzilu .icon-shape .label{text-align:center;}#mermaid-svg-Cgvarb0V1Fpdzilu .node.clickable{cursor:pointer;}#mermaid-svg-Cgvarb0V1Fpdzilu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Cgvarb0V1Fpdzilu .arrowheadPath{fill:#333333;}#mermaid-svg-Cgvarb0V1Fpdzilu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Cgvarb0V1Fpdzilu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Cgvarb0V1Fpdzilu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Cgvarb0V1Fpdzilu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Cgvarb0V1Fpdzilu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Cgvarb0V1Fpdzilu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Cgvarb0V1Fpdzilu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Cgvarb0V1Fpdzilu .cluster text{fill:#333;}#mermaid-svg-Cgvarb0V1Fpdzilu .cluster span{color:#333;}#mermaid-svg-Cgvarb0V1Fpdzilu 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-Cgvarb0V1Fpdzilu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Cgvarb0V1Fpdzilu rect.text{fill:none;stroke-width:0;}#mermaid-svg-Cgvarb0V1Fpdzilu .icon-shape,#mermaid-svg-Cgvarb0V1Fpdzilu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Cgvarb0V1Fpdzilu .icon-shape p,#mermaid-svg-Cgvarb0V1Fpdzilu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Cgvarb0V1Fpdzilu .icon-shape .label rect,#mermaid-svg-Cgvarb0V1Fpdzilu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Cgvarb0V1Fpdzilu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Cgvarb0V1Fpdzilu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Cgvarb0V1Fpdzilu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Host
Cursor / ChatGPT / 自建 Agent
MCP Client 1
MCP Client 2
本地 MCP Server
远程 MCP Server
企业 Gateway
Server 可暴露的主要原语:
| 原语 | 用途 | 典型例子 |
|---|---|---|
| Tools | 可执行的受控动作或查询 | search_orders、create_ticket、query_portfolio |
| Resources | 可读取的上下文、文件或数据引用 | file://、knowledge://policy/123 |
| Prompts | 参数化提示模板/工作流入口 | "生成周报""排查生产告警" |
| Sampling / Elicitation 等客户端能力 | Server 向 Host 请求模型推理或用户输入 | 长流程中要求补充审批理由 |
| Tasks 扩展 | 长任务、轮询、中途输入、持久句柄 | 批量导出、离线分析、代码扫描 |
2.2 协议没有替企业解决的问题
MCP 不会自动给出:
- 企业工具如何命名、如何拆分;
- 数据权限模型、租户隔离和字段脱敏;
- 如何从自然语言生成正确业务查询;
- 如何处理大结果、异步导出、成本和限流;
- 如何治理工具版本、灰度发布和回滚;
- 如何避免提示注入诱导 Agent 调用高风险工具。
这些需要通过下文的设计模式补齐。
3. 设计模式总览
#mermaid-svg-PNqAdRFB2nC708xc{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-PNqAdRFB2nC708xc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PNqAdRFB2nC708xc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PNqAdRFB2nC708xc .error-icon{fill:#552222;}#mermaid-svg-PNqAdRFB2nC708xc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PNqAdRFB2nC708xc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PNqAdRFB2nC708xc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PNqAdRFB2nC708xc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PNqAdRFB2nC708xc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PNqAdRFB2nC708xc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PNqAdRFB2nC708xc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PNqAdRFB2nC708xc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PNqAdRFB2nC708xc .marker.cross{stroke:#333333;}#mermaid-svg-PNqAdRFB2nC708xc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PNqAdRFB2nC708xc p{margin:0;}#mermaid-svg-PNqAdRFB2nC708xc .edge{stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .section--1 rect,#mermaid-svg-PNqAdRFB2nC708xc .section--1 path,#mermaid-svg-PNqAdRFB2nC708xc .section--1 circle,#mermaid-svg-PNqAdRFB2nC708xc .section--1 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section--1 text{fill:#ffffff;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth--1{stroke-width:17;}#mermaid-svg-PNqAdRFB2nC708xc .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-0 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-0 path,#mermaid-svg-PNqAdRFB2nC708xc .section-0 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-0 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-PNqAdRFB2nC708xc .section-0 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-0{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-0{stroke-width:14;}#mermaid-svg-PNqAdRFB2nC708xc .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-1 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-1 path,#mermaid-svg-PNqAdRFB2nC708xc .section-1 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-1 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-1 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-1{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-1{stroke-width:11;}#mermaid-svg-PNqAdRFB2nC708xc .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-2 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-2 path,#mermaid-svg-PNqAdRFB2nC708xc .section-2 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-2 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-2 text{fill:#ffffff;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-2{stroke-width:8;}#mermaid-svg-PNqAdRFB2nC708xc .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-3 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-3 path,#mermaid-svg-PNqAdRFB2nC708xc .section-3 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-3 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-3 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-3{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-3{stroke-width:5;}#mermaid-svg-PNqAdRFB2nC708xc .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-4 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-4 path,#mermaid-svg-PNqAdRFB2nC708xc .section-4 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-4 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-4 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-4{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-4{stroke-width:2;}#mermaid-svg-PNqAdRFB2nC708xc .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-5 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-5 path,#mermaid-svg-PNqAdRFB2nC708xc .section-5 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-5 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-5 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-5{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-5{stroke-width:-1;}#mermaid-svg-PNqAdRFB2nC708xc .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-6 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-6 path,#mermaid-svg-PNqAdRFB2nC708xc .section-6 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-6 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-6 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-6{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-6{stroke-width:-4;}#mermaid-svg-PNqAdRFB2nC708xc .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-7 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-7 path,#mermaid-svg-PNqAdRFB2nC708xc .section-7 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-7 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-7 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-7{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-7{stroke-width:-7;}#mermaid-svg-PNqAdRFB2nC708xc .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-8 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-8 path,#mermaid-svg-PNqAdRFB2nC708xc .section-8 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-8 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-8 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-8{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-8{stroke-width:-10;}#mermaid-svg-PNqAdRFB2nC708xc .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-9 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-9 path,#mermaid-svg-PNqAdRFB2nC708xc .section-9 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-9 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-9 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-9{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-9{stroke-width:-13;}#mermaid-svg-PNqAdRFB2nC708xc .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-10 rect,#mermaid-svg-PNqAdRFB2nC708xc .section-10 path,#mermaid-svg-PNqAdRFB2nC708xc .section-10 circle,#mermaid-svg-PNqAdRFB2nC708xc .section-10 polygon,#mermaid-svg-PNqAdRFB2nC708xc .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-10 text{fill:black;}#mermaid-svg-PNqAdRFB2nC708xc .node-icon-10{font-size:40px;color:black;}#mermaid-svg-PNqAdRFB2nC708xc .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .edge-depth-10{stroke-width:-16;}#mermaid-svg-PNqAdRFB2nC708xc .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-PNqAdRFB2nC708xc .disabled,#mermaid-svg-PNqAdRFB2nC708xc .disabled circle,#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:lightgray;}#mermaid-svg-PNqAdRFB2nC708xc .disabled text{fill:#efefef;}#mermaid-svg-PNqAdRFB2nC708xc .section-root rect,#mermaid-svg-PNqAdRFB2nC708xc .section-root path,#mermaid-svg-PNqAdRFB2nC708xc .section-root circle,#mermaid-svg-PNqAdRFB2nC708xc .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-PNqAdRFB2nC708xc .section-root text{fill:#ffffff;}#mermaid-svg-PNqAdRFB2nC708xc .section-root span{color:#ffffff;}#mermaid-svg-PNqAdRFB2nC708xc .section-2 span{color:#ffffff;}#mermaid-svg-PNqAdRFB2nC708xc .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-PNqAdRFB2nC708xc .edge{fill:none;}#mermaid-svg-PNqAdRFB2nC708xc .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-PNqAdRFB2nC708xc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} MCP 设计模式
接入
本地进程连接器
远程服务型 Server
API 原子适配器
多 Server 联邦
业务
Compose 业务编排
语义查询
RAG 检索与权限投影
命令与审批
异步任务与导出
治理
Gateway
Registry
契约版本
可观测与审计
安全
OAuth 2.1
最小权限
人工确认
输出脱敏
出网控制
以下模式不是互斥关系。企业平台通常同时使用"Gateway + Registry + Atomic + Compose + 异步任务 + 审计"。
4. 模式一:本地进程 MCP Server
适用场景
- IDE/桌面 Agent 访问本机文件、Git、数据库客户端或开发工具;
- 单个开发者使用的小型内部工具;
- 对延迟敏感且不需要跨网络共享的能力。
#mermaid-svg-frJAyCgWGf72fO39{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-frJAyCgWGf72fO39 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-frJAyCgWGf72fO39 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-frJAyCgWGf72fO39 .error-icon{fill:#552222;}#mermaid-svg-frJAyCgWGf72fO39 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-frJAyCgWGf72fO39 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-frJAyCgWGf72fO39 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-frJAyCgWGf72fO39 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-frJAyCgWGf72fO39 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-frJAyCgWGf72fO39 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-frJAyCgWGf72fO39 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-frJAyCgWGf72fO39 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-frJAyCgWGf72fO39 .marker.cross{stroke:#333333;}#mermaid-svg-frJAyCgWGf72fO39 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-frJAyCgWGf72fO39 p{margin:0;}#mermaid-svg-frJAyCgWGf72fO39 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-frJAyCgWGf72fO39 .cluster-label text{fill:#333;}#mermaid-svg-frJAyCgWGf72fO39 .cluster-label span{color:#333;}#mermaid-svg-frJAyCgWGf72fO39 .cluster-label span p{background-color:transparent;}#mermaid-svg-frJAyCgWGf72fO39 .label text,#mermaid-svg-frJAyCgWGf72fO39 span{fill:#333;color:#333;}#mermaid-svg-frJAyCgWGf72fO39 .node rect,#mermaid-svg-frJAyCgWGf72fO39 .node circle,#mermaid-svg-frJAyCgWGf72fO39 .node ellipse,#mermaid-svg-frJAyCgWGf72fO39 .node polygon,#mermaid-svg-frJAyCgWGf72fO39 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-frJAyCgWGf72fO39 .rough-node .label text,#mermaid-svg-frJAyCgWGf72fO39 .node .label text,#mermaid-svg-frJAyCgWGf72fO39 .image-shape .label,#mermaid-svg-frJAyCgWGf72fO39 .icon-shape .label{text-anchor:middle;}#mermaid-svg-frJAyCgWGf72fO39 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-frJAyCgWGf72fO39 .rough-node .label,#mermaid-svg-frJAyCgWGf72fO39 .node .label,#mermaid-svg-frJAyCgWGf72fO39 .image-shape .label,#mermaid-svg-frJAyCgWGf72fO39 .icon-shape .label{text-align:center;}#mermaid-svg-frJAyCgWGf72fO39 .node.clickable{cursor:pointer;}#mermaid-svg-frJAyCgWGf72fO39 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-frJAyCgWGf72fO39 .arrowheadPath{fill:#333333;}#mermaid-svg-frJAyCgWGf72fO39 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-frJAyCgWGf72fO39 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-frJAyCgWGf72fO39 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-frJAyCgWGf72fO39 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-frJAyCgWGf72fO39 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-frJAyCgWGf72fO39 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-frJAyCgWGf72fO39 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-frJAyCgWGf72fO39 .cluster text{fill:#333;}#mermaid-svg-frJAyCgWGf72fO39 .cluster span{color:#333;}#mermaid-svg-frJAyCgWGf72fO39 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-frJAyCgWGf72fO39 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-frJAyCgWGf72fO39 rect.text{fill:none;stroke-width:0;}#mermaid-svg-frJAyCgWGf72fO39 .icon-shape,#mermaid-svg-frJAyCgWGf72fO39 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-frJAyCgWGf72fO39 .icon-shape p,#mermaid-svg-frJAyCgWGf72fO39 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-frJAyCgWGf72fO39 .icon-shape .label rect,#mermaid-svg-frJAyCgWGf72fO39 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-frJAyCgWGf72fO39 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-frJAyCgWGf72fO39 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-frJAyCgWGf72fO39 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} stdio
IDE Host
MCP Server 本地子进程
本地文件系统
Git / CLI
开发环境
优点
- 接入简单,部署成本低;
- 不需要公开网络入口;
- 可直接复用本机登录态和开发工具。
风险与约束
本地不等于低风险。它通常拥有用户文件、Shell、环境变量和凭证可见性,危害面反而很大。
必须落实:
- 不把未知 MCP Server 当作"普通插件"安装;
- Agent 运行身份不使用管理员/root;
- 工具按目录、命令和网络最小授权;
- 不让工具静默读取 SSH Key、浏览器 Token、
.env或系统凭证; - 对安装脚本、依赖生命周期、子进程和外联进行审计;
- 高风险项目在隔离 VM/容器中运行。
常见反模式
text
"本地工具无需认证,所以允许任意 shell / 任意文件读取"
本机用户权限本身就是高价值授权。应把本地 MCP Server 视为本地特权应用,而不是无害脚本。
5. 模式二:远程服务型 MCP Server
适用场景
- SaaS、企业 API、共享知识库、统一数据服务;
- 多用户、多租户、跨设备访问;
- 需要集中审计、统一认证和弹性扩缩容。
Business Service Remote MCP Server Authorization Server Host / MCP Client Business Service Remote MCP Server Authorization Server Host / MCP Client #mermaid-svg-VAPOgvTfAinzJBM1{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-VAPOgvTfAinzJBM1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VAPOgvTfAinzJBM1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VAPOgvTfAinzJBM1 .error-icon{fill:#552222;}#mermaid-svg-VAPOgvTfAinzJBM1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VAPOgvTfAinzJBM1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VAPOgvTfAinzJBM1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VAPOgvTfAinzJBM1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VAPOgvTfAinzJBM1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VAPOgvTfAinzJBM1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VAPOgvTfAinzJBM1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VAPOgvTfAinzJBM1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VAPOgvTfAinzJBM1 .marker.cross{stroke:#333333;}#mermaid-svg-VAPOgvTfAinzJBM1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VAPOgvTfAinzJBM1 p{margin:0;}#mermaid-svg-VAPOgvTfAinzJBM1 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-VAPOgvTfAinzJBM1 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-VAPOgvTfAinzJBM1 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-VAPOgvTfAinzJBM1 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-VAPOgvTfAinzJBM1 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-VAPOgvTfAinzJBM1 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-VAPOgvTfAinzJBM1 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-VAPOgvTfAinzJBM1 .sequenceNumber{fill:white;}#mermaid-svg-VAPOgvTfAinzJBM1 #sequencenumber{fill:#333;}#mermaid-svg-VAPOgvTfAinzJBM1 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-VAPOgvTfAinzJBM1 .messageText{fill:#333;stroke:none;}#mermaid-svg-VAPOgvTfAinzJBM1 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-VAPOgvTfAinzJBM1 .labelText,#mermaid-svg-VAPOgvTfAinzJBM1 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-VAPOgvTfAinzJBM1 .loopText,#mermaid-svg-VAPOgvTfAinzJBM1 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-VAPOgvTfAinzJBM1 .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-VAPOgvTfAinzJBM1 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-VAPOgvTfAinzJBM1 .noteText,#mermaid-svg-VAPOgvTfAinzJBM1 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-VAPOgvTfAinzJBM1 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-VAPOgvTfAinzJBM1 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-VAPOgvTfAinzJBM1 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-VAPOgvTfAinzJBM1 .actorPopupMenu{position:absolute;}#mermaid-svg-VAPOgvTfAinzJBM1 .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-VAPOgvTfAinzJBM1 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-VAPOgvTfAinzJBM1 .actor-man circle,#mermaid-svg-VAPOgvTfAinzJBM1 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-VAPOgvTfAinzJBM1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 访问受保护资源 401 + resource metadata / required scope OAuth 2.1 + PKCE 授权 access token(audience 绑定 MCP Server) tools/call + token 校验 issuer / audience / scope / expiry 使用服务端受控身份调用 业务结果 MCP 结果
标准安全基线
对 HTTP 远程 MCP,当前官方授权体系以 OAuth 2.1 为基础。生产环境应具备:
| 控制 | 要求 |
|---|---|
| 传输 | 全链路 HTTPS;安全校验 redirect URI |
| Token | 校验签名、过期时间、issuer、audience、scope |
| Audience | 仅接收明确签发给本 MCP Server 的 Token |
| Resource Indicators | Client 在授权与换 Token 时绑定目标 resource |
| PKCE | 公共 Client 必须使用 PKCE,避免授权码截获 |
| Scope | 按工具/资源/动作最小化,禁止万能 scope |
| 元数据发现 | 支持 Protected Resource Metadata 与合规的 401 challenge |
| Token 存储 | 加密、最小留存、失效清理 |
| 禁止 Token Passthrough | 不把收到的用户 Token 原样转交给不受信任下游 |
为什么"Token Passthrough"危险
错误模式:
text
Client → MCP A(携带给 A 的 Token)→ MCP B / 第三方 API(原样转发)
问题是 B 可能把此 Token 当成自己的授权,形成 confused deputy(混淆代理)或 Token 泄露。正确做法是:
- 下游有自己的 OAuth 委托流程;或
- MCP Server 使用受控服务身份,再结合服务端权限检查;或
- 使用 token exchange / audience 受限的委托机制。
6. 模式三:API 原子适配器(Atomic Tool)
核心思想
一个原子工具只代表一个上游数据源或一个边界清晰的 API 动作,不承担跨域业务解释。
#mermaid-svg-ZdzOikI0yewOUVhM{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-ZdzOikI0yewOUVhM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZdzOikI0yewOUVhM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZdzOikI0yewOUVhM .error-icon{fill:#552222;}#mermaid-svg-ZdzOikI0yewOUVhM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZdzOikI0yewOUVhM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZdzOikI0yewOUVhM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZdzOikI0yewOUVhM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZdzOikI0yewOUVhM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZdzOikI0yewOUVhM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZdzOikI0yewOUVhM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZdzOikI0yewOUVhM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZdzOikI0yewOUVhM .marker.cross{stroke:#333333;}#mermaid-svg-ZdzOikI0yewOUVhM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZdzOikI0yewOUVhM p{margin:0;}#mermaid-svg-ZdzOikI0yewOUVhM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZdzOikI0yewOUVhM .cluster-label text{fill:#333;}#mermaid-svg-ZdzOikI0yewOUVhM .cluster-label span{color:#333;}#mermaid-svg-ZdzOikI0yewOUVhM .cluster-label span p{background-color:transparent;}#mermaid-svg-ZdzOikI0yewOUVhM .label text,#mermaid-svg-ZdzOikI0yewOUVhM span{fill:#333;color:#333;}#mermaid-svg-ZdzOikI0yewOUVhM .node rect,#mermaid-svg-ZdzOikI0yewOUVhM .node circle,#mermaid-svg-ZdzOikI0yewOUVhM .node ellipse,#mermaid-svg-ZdzOikI0yewOUVhM .node polygon,#mermaid-svg-ZdzOikI0yewOUVhM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZdzOikI0yewOUVhM .rough-node .label text,#mermaid-svg-ZdzOikI0yewOUVhM .node .label text,#mermaid-svg-ZdzOikI0yewOUVhM .image-shape .label,#mermaid-svg-ZdzOikI0yewOUVhM .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZdzOikI0yewOUVhM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZdzOikI0yewOUVhM .rough-node .label,#mermaid-svg-ZdzOikI0yewOUVhM .node .label,#mermaid-svg-ZdzOikI0yewOUVhM .image-shape .label,#mermaid-svg-ZdzOikI0yewOUVhM .icon-shape .label{text-align:center;}#mermaid-svg-ZdzOikI0yewOUVhM .node.clickable{cursor:pointer;}#mermaid-svg-ZdzOikI0yewOUVhM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZdzOikI0yewOUVhM .arrowheadPath{fill:#333333;}#mermaid-svg-ZdzOikI0yewOUVhM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZdzOikI0yewOUVhM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZdzOikI0yewOUVhM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZdzOikI0yewOUVhM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZdzOikI0yewOUVhM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZdzOikI0yewOUVhM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZdzOikI0yewOUVhM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZdzOikI0yewOUVhM .cluster text{fill:#333;}#mermaid-svg-ZdzOikI0yewOUVhM .cluster span{color:#333;}#mermaid-svg-ZdzOikI0yewOUVhM 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-ZdzOikI0yewOUVhM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZdzOikI0yewOUVhM rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZdzOikI0yewOUVhM .icon-shape,#mermaid-svg-ZdzOikI0yewOUVhM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZdzOikI0yewOUVhM .icon-shape p,#mermaid-svg-ZdzOikI0yewOUVhM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZdzOikI0yewOUVhM .icon-shape .label rect,#mermaid-svg-ZdzOikI0yewOUVhM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZdzOikI0yewOUVhM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZdzOikI0yewOUVhM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZdzOikI0yewOUVhM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent
atomic_get_customer
atomic_list_orders
atomic_get_fx_rate
CRM API
Order API
Market API
适用场景
- 将成熟的内部 OpenAPI、安全地转为 MCP 工具;
- 需要保留上游 API 的明确语义;
- 为 Compose 工具提供可复用的基础能力。
设计准则
- 一个工具只访问一个权威上游;
- 工具名以动词和资源表达用户目标,例如
get_customer_profile; - 输入 Schema 只保留必要参数;
- 上游字段不是默认全部暴露;需要字段投影和显示标签;
- 工具描述应标明何时使用、何时不用,以及与相似工具的边界;
- 上游错误转换为稳定的 MCP 业务错误,而不是透传内部堆栈。
原子工具与业务工具的区别
| 项 | Atomic Tool | Compose Tool |
|---|---|---|
| 上游 | 单一 | 一个或多个 |
| 目标 | 数据源/API 边界 | 用户业务问题 |
| 输入 | 上游所需的最小业务参数 | 高层业务意图 |
| 输出 | 受控的基础数据 | 面向用户的业务结果 |
| Agent 默认入口 | 通常不是 | 通常是 |
反模式是让 Agent 在几十个原子 API 中自行拼出业务流程。这样会造成权限遗漏、口径不一致、调用回合多和上下文膨胀。
7. 模式四:Compose / 业务能力编排
核心思想
将"用户真正想完成的事"封装为一个业务工具,由服务端完成跨 API、数据投影、权限收敛和流程控制。
#mermaid-svg-XYfsK79UGY9nwZQz{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-XYfsK79UGY9nwZQz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XYfsK79UGY9nwZQz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XYfsK79UGY9nwZQz .error-icon{fill:#552222;}#mermaid-svg-XYfsK79UGY9nwZQz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XYfsK79UGY9nwZQz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XYfsK79UGY9nwZQz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XYfsK79UGY9nwZQz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XYfsK79UGY9nwZQz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XYfsK79UGY9nwZQz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XYfsK79UGY9nwZQz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XYfsK79UGY9nwZQz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XYfsK79UGY9nwZQz .marker.cross{stroke:#333333;}#mermaid-svg-XYfsK79UGY9nwZQz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XYfsK79UGY9nwZQz p{margin:0;}#mermaid-svg-XYfsK79UGY9nwZQz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XYfsK79UGY9nwZQz .cluster-label text{fill:#333;}#mermaid-svg-XYfsK79UGY9nwZQz .cluster-label span{color:#333;}#mermaid-svg-XYfsK79UGY9nwZQz .cluster-label span p{background-color:transparent;}#mermaid-svg-XYfsK79UGY9nwZQz .label text,#mermaid-svg-XYfsK79UGY9nwZQz span{fill:#333;color:#333;}#mermaid-svg-XYfsK79UGY9nwZQz .node rect,#mermaid-svg-XYfsK79UGY9nwZQz .node circle,#mermaid-svg-XYfsK79UGY9nwZQz .node ellipse,#mermaid-svg-XYfsK79UGY9nwZQz .node polygon,#mermaid-svg-XYfsK79UGY9nwZQz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XYfsK79UGY9nwZQz .rough-node .label text,#mermaid-svg-XYfsK79UGY9nwZQz .node .label text,#mermaid-svg-XYfsK79UGY9nwZQz .image-shape .label,#mermaid-svg-XYfsK79UGY9nwZQz .icon-shape .label{text-anchor:middle;}#mermaid-svg-XYfsK79UGY9nwZQz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XYfsK79UGY9nwZQz .rough-node .label,#mermaid-svg-XYfsK79UGY9nwZQz .node .label,#mermaid-svg-XYfsK79UGY9nwZQz .image-shape .label,#mermaid-svg-XYfsK79UGY9nwZQz .icon-shape .label{text-align:center;}#mermaid-svg-XYfsK79UGY9nwZQz .node.clickable{cursor:pointer;}#mermaid-svg-XYfsK79UGY9nwZQz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XYfsK79UGY9nwZQz .arrowheadPath{fill:#333333;}#mermaid-svg-XYfsK79UGY9nwZQz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XYfsK79UGY9nwZQz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XYfsK79UGY9nwZQz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XYfsK79UGY9nwZQz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XYfsK79UGY9nwZQz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XYfsK79UGY9nwZQz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XYfsK79UGY9nwZQz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XYfsK79UGY9nwZQz .cluster text{fill:#333;}#mermaid-svg-XYfsK79UGY9nwZQz .cluster span{color:#333;}#mermaid-svg-XYfsK79UGY9nwZQz 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-XYfsK79UGY9nwZQz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XYfsK79UGY9nwZQz rect.text{fill:none;stroke-width:0;}#mermaid-svg-XYfsK79UGY9nwZQz .icon-shape,#mermaid-svg-XYfsK79UGY9nwZQz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XYfsK79UGY9nwZQz .icon-shape p,#mermaid-svg-XYfsK79UGY9nwZQz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XYfsK79UGY9nwZQz .icon-shape .label rect,#mermaid-svg-XYfsK79UGY9nwZQz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XYfsK79UGY9nwZQz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XYfsK79UGY9nwZQz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XYfsK79UGY9nwZQz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "查询某客户近 30 天的交易摘要"
query_customer_trade_summary
加载可信数据权限
客户实体消歧
atomic_get_customer_accounts
atomic_query_trades
汇总、排序、字段投影
摘要 + 分页结果 + 可追溯元数据
何时应创建 Compose 工具
出现以下任一情况就应优先考虑:
- 用户问题需要多个原子工具;
- 存在统一口径、固定过滤、汇率、时区或权限规则;
- 结果必须先聚合、排序、统计 total 再分页;
- 需要隐藏内部字段、内部路由或多系统复杂性;
- 业务流程存在顺序、补偿或审批要求。
关键约束
Compose 不是"万能工具"。一个工具塞入几十种无关 mode 会让 Agent 难以理解。应遵循:
text
一个工具 = 一个稳定业务意图 + 一组紧密相关输入 + 一种可解释结果
例如:
- 好:
query_portfolio_allocation - 好:
request_payment_approval - 不好:
do_everything(action, params) - 不好:
generic_openapi_proxy(url, method, body)
8. 模式五:MCP Gateway / BFF 统一入口
核心思想
所有外部 Host/Agent 仅连接 Gateway;Registry、Compose、BAM/Adapter、OpenAPI 和数据库是内部实现细节。
#mermaid-svg-FMvmDHknZdH2a6Ab{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-FMvmDHknZdH2a6Ab .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FMvmDHknZdH2a6Ab .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FMvmDHknZdH2a6Ab .error-icon{fill:#552222;}#mermaid-svg-FMvmDHknZdH2a6Ab .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FMvmDHknZdH2a6Ab .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FMvmDHknZdH2a6Ab .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FMvmDHknZdH2a6Ab .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FMvmDHknZdH2a6Ab .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FMvmDHknZdH2a6Ab .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FMvmDHknZdH2a6Ab .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FMvmDHknZdH2a6Ab .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FMvmDHknZdH2a6Ab .marker.cross{stroke:#333333;}#mermaid-svg-FMvmDHknZdH2a6Ab svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FMvmDHknZdH2a6Ab p{margin:0;}#mermaid-svg-FMvmDHknZdH2a6Ab .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FMvmDHknZdH2a6Ab .cluster-label text{fill:#333;}#mermaid-svg-FMvmDHknZdH2a6Ab .cluster-label span{color:#333;}#mermaid-svg-FMvmDHknZdH2a6Ab .cluster-label span p{background-color:transparent;}#mermaid-svg-FMvmDHknZdH2a6Ab .label text,#mermaid-svg-FMvmDHknZdH2a6Ab span{fill:#333;color:#333;}#mermaid-svg-FMvmDHknZdH2a6Ab .node rect,#mermaid-svg-FMvmDHknZdH2a6Ab .node circle,#mermaid-svg-FMvmDHknZdH2a6Ab .node ellipse,#mermaid-svg-FMvmDHknZdH2a6Ab .node polygon,#mermaid-svg-FMvmDHknZdH2a6Ab .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FMvmDHknZdH2a6Ab .rough-node .label text,#mermaid-svg-FMvmDHknZdH2a6Ab .node .label text,#mermaid-svg-FMvmDHknZdH2a6Ab .image-shape .label,#mermaid-svg-FMvmDHknZdH2a6Ab .icon-shape .label{text-anchor:middle;}#mermaid-svg-FMvmDHknZdH2a6Ab .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FMvmDHknZdH2a6Ab .rough-node .label,#mermaid-svg-FMvmDHknZdH2a6Ab .node .label,#mermaid-svg-FMvmDHknZdH2a6Ab .image-shape .label,#mermaid-svg-FMvmDHknZdH2a6Ab .icon-shape .label{text-align:center;}#mermaid-svg-FMvmDHknZdH2a6Ab .node.clickable{cursor:pointer;}#mermaid-svg-FMvmDHknZdH2a6Ab .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FMvmDHknZdH2a6Ab .arrowheadPath{fill:#333333;}#mermaid-svg-FMvmDHknZdH2a6Ab .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FMvmDHknZdH2a6Ab .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FMvmDHknZdH2a6Ab .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FMvmDHknZdH2a6Ab .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FMvmDHknZdH2a6Ab .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FMvmDHknZdH2a6Ab .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FMvmDHknZdH2a6Ab .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FMvmDHknZdH2a6Ab .cluster text{fill:#333;}#mermaid-svg-FMvmDHknZdH2a6Ab .cluster span{color:#333;}#mermaid-svg-FMvmDHknZdH2a6Ab 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-FMvmDHknZdH2a6Ab .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FMvmDHknZdH2a6Ab rect.text{fill:none;stroke-width:0;}#mermaid-svg-FMvmDHknZdH2a6Ab .icon-shape,#mermaid-svg-FMvmDHknZdH2a6Ab .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FMvmDHknZdH2a6Ab .icon-shape p,#mermaid-svg-FMvmDHknZdH2a6Ab .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FMvmDHknZdH2a6Ab .icon-shape .label rect,#mermaid-svg-FMvmDHknZdH2a6Ab .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FMvmDHknZdH2a6Ab .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FMvmDHknZdH2a6Ab .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FMvmDHknZdH2a6Ab :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Cursor
Gateway /mcp
ChatGPT
企业 Agent
认证/授权
限流/配额
审计/traceId
Registry
Compose
Adapter
内部服务
外部 API
Gateway 应统一实现
| 能力 | 原因 |
|---|---|
| MCP JSON-RPC 协议 | 统一 initialize、tools/list、tools/call、错误格式 |
| 身份认证 | 不让每个能力服务自己解析外部 Token |
| 数据权限注入 | 权限只能来自可信身份服务,不能信任 Agent 入参 |
| Schema 校验 | 尽早拒绝非法调用 |
| 工具可见性 | 不同角色/Scope 看到不同工具 |
| 限流与配额 | 防止 Agent 循环调用与昂贵查询 |
| 审计与 traceId | 形成端到端可回溯链路 |
| 风险拦截 | 写操作确认、合规、敏感字段、异常调用 |
错误分层
必须区分两类错误:
text
协议错误:JSON-RPC error
例:请求格式非法、方法不存在、参数类型不合法
工具业务错误:tools/call result.isError = true
例:无权限、实体歧义、上游超时、业务校验失败
如果把所有业务失败都做成 JSON-RPC 协议错误,Agent 很难判断是"修参数""追问用户"还是"稍后重试"。
9. 模式六:Registry / Control Plane(契约即配置)
核心思想
工具不是散落在代码里的字符串常量;应作为可治理资产注册。
#mermaid-svg-qLPh2o0RknM93xxz{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-qLPh2o0RknM93xxz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qLPh2o0RknM93xxz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qLPh2o0RknM93xxz .error-icon{fill:#552222;}#mermaid-svg-qLPh2o0RknM93xxz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qLPh2o0RknM93xxz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qLPh2o0RknM93xxz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qLPh2o0RknM93xxz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qLPh2o0RknM93xxz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qLPh2o0RknM93xxz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qLPh2o0RknM93xxz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qLPh2o0RknM93xxz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qLPh2o0RknM93xxz .marker.cross{stroke:#333333;}#mermaid-svg-qLPh2o0RknM93xxz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qLPh2o0RknM93xxz p{margin:0;}#mermaid-svg-qLPh2o0RknM93xxz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qLPh2o0RknM93xxz .cluster-label text{fill:#333;}#mermaid-svg-qLPh2o0RknM93xxz .cluster-label span{color:#333;}#mermaid-svg-qLPh2o0RknM93xxz .cluster-label span p{background-color:transparent;}#mermaid-svg-qLPh2o0RknM93xxz .label text,#mermaid-svg-qLPh2o0RknM93xxz span{fill:#333;color:#333;}#mermaid-svg-qLPh2o0RknM93xxz .node rect,#mermaid-svg-qLPh2o0RknM93xxz .node circle,#mermaid-svg-qLPh2o0RknM93xxz .node ellipse,#mermaid-svg-qLPh2o0RknM93xxz .node polygon,#mermaid-svg-qLPh2o0RknM93xxz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qLPh2o0RknM93xxz .rough-node .label text,#mermaid-svg-qLPh2o0RknM93xxz .node .label text,#mermaid-svg-qLPh2o0RknM93xxz .image-shape .label,#mermaid-svg-qLPh2o0RknM93xxz .icon-shape .label{text-anchor:middle;}#mermaid-svg-qLPh2o0RknM93xxz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qLPh2o0RknM93xxz .rough-node .label,#mermaid-svg-qLPh2o0RknM93xxz .node .label,#mermaid-svg-qLPh2o0RknM93xxz .image-shape .label,#mermaid-svg-qLPh2o0RknM93xxz .icon-shape .label{text-align:center;}#mermaid-svg-qLPh2o0RknM93xxz .node.clickable{cursor:pointer;}#mermaid-svg-qLPh2o0RknM93xxz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qLPh2o0RknM93xxz .arrowheadPath{fill:#333333;}#mermaid-svg-qLPh2o0RknM93xxz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qLPh2o0RknM93xxz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qLPh2o0RknM93xxz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qLPh2o0RknM93xxz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qLPh2o0RknM93xxz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qLPh2o0RknM93xxz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qLPh2o0RknM93xxz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qLPh2o0RknM93xxz .cluster text{fill:#333;}#mermaid-svg-qLPh2o0RknM93xxz .cluster span{color:#333;}#mermaid-svg-qLPh2o0RknM93xxz 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-qLPh2o0RknM93xxz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qLPh2o0RknM93xxz rect.text{fill:none;stroke-width:0;}#mermaid-svg-qLPh2o0RknM93xxz .icon-shape,#mermaid-svg-qLPh2o0RknM93xxz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qLPh2o0RknM93xxz .icon-shape p,#mermaid-svg-qLPh2o0RknM93xxz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qLPh2o0RknM93xxz .icon-shape .label rect,#mermaid-svg-qLPh2o0RknM93xxz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qLPh2o0RknM93xxz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qLPh2o0RknM93xxz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qLPh2o0RknM93xxz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 开发者/平台管理员
Registry
Schema / 策略校验
版本历史
发布批次
Gateway tools/list / 路由
Agent
Registry 常见元数据
| 分类 | 推荐内容 |
|---|---|
| 基本契约 | name、title、description、inputSchema、outputSchema |
| 路由 | capabilityType、service、path、依赖、超时 |
| Agent 指引 | intendedUse、preferredFor、notPreferredFor、示例、supersedes |
| 安全 | visibility、scope、dataPermission、risk level、confirmation policy |
| 展示 | display labels、hidden fields、国际化 |
| 治理 | owner、状态、版本、发布时间、回滚信息 |
常见发布流程
text
草稿 → Schema/安全校验 → 集成测试 → 版本快照 → 灰度发布
→ 运行监控 → 全量发布 / 回滚
Registry 的作用不是替代代码评审;它解决的是"工具契约、Agent 引导、路由和策略是否可审计、可发布、可回滚"。
10. 模式七:语义查询,而非 Text-to-SQL
问题
企业用户会问:
"我管理客户最新持仓里,市值前十的标的有哪些?"
直接让 LLM 生成 SQL 的风险包括:字段口径错误、跨租户、任意 Join、资源失控、分页后误判 TopN。
推荐模式:NL → Formula → 受控 SQL
#mermaid-svg-NpLzuwGwMgiOQdHP{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-NpLzuwGwMgiOQdHP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NpLzuwGwMgiOQdHP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NpLzuwGwMgiOQdHP .error-icon{fill:#552222;}#mermaid-svg-NpLzuwGwMgiOQdHP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NpLzuwGwMgiOQdHP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NpLzuwGwMgiOQdHP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NpLzuwGwMgiOQdHP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NpLzuwGwMgiOQdHP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NpLzuwGwMgiOQdHP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NpLzuwGwMgiOQdHP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NpLzuwGwMgiOQdHP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NpLzuwGwMgiOQdHP .marker.cross{stroke:#333333;}#mermaid-svg-NpLzuwGwMgiOQdHP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NpLzuwGwMgiOQdHP p{margin:0;}#mermaid-svg-NpLzuwGwMgiOQdHP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NpLzuwGwMgiOQdHP .cluster-label text{fill:#333;}#mermaid-svg-NpLzuwGwMgiOQdHP .cluster-label span{color:#333;}#mermaid-svg-NpLzuwGwMgiOQdHP .cluster-label span p{background-color:transparent;}#mermaid-svg-NpLzuwGwMgiOQdHP .label text,#mermaid-svg-NpLzuwGwMgiOQdHP span{fill:#333;color:#333;}#mermaid-svg-NpLzuwGwMgiOQdHP .node rect,#mermaid-svg-NpLzuwGwMgiOQdHP .node circle,#mermaid-svg-NpLzuwGwMgiOQdHP .node ellipse,#mermaid-svg-NpLzuwGwMgiOQdHP .node polygon,#mermaid-svg-NpLzuwGwMgiOQdHP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NpLzuwGwMgiOQdHP .rough-node .label text,#mermaid-svg-NpLzuwGwMgiOQdHP .node .label text,#mermaid-svg-NpLzuwGwMgiOQdHP .image-shape .label,#mermaid-svg-NpLzuwGwMgiOQdHP .icon-shape .label{text-anchor:middle;}#mermaid-svg-NpLzuwGwMgiOQdHP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NpLzuwGwMgiOQdHP .rough-node .label,#mermaid-svg-NpLzuwGwMgiOQdHP .node .label,#mermaid-svg-NpLzuwGwMgiOQdHP .image-shape .label,#mermaid-svg-NpLzuwGwMgiOQdHP .icon-shape .label{text-align:center;}#mermaid-svg-NpLzuwGwMgiOQdHP .node.clickable{cursor:pointer;}#mermaid-svg-NpLzuwGwMgiOQdHP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NpLzuwGwMgiOQdHP .arrowheadPath{fill:#333333;}#mermaid-svg-NpLzuwGwMgiOQdHP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NpLzuwGwMgiOQdHP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NpLzuwGwMgiOQdHP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NpLzuwGwMgiOQdHP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NpLzuwGwMgiOQdHP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NpLzuwGwMgiOQdHP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NpLzuwGwMgiOQdHP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NpLzuwGwMgiOQdHP .cluster text{fill:#333;}#mermaid-svg-NpLzuwGwMgiOQdHP .cluster span{color:#333;}#mermaid-svg-NpLzuwGwMgiOQdHP 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-NpLzuwGwMgiOQdHP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NpLzuwGwMgiOQdHP rect.text{fill:none;stroke-width:0;}#mermaid-svg-NpLzuwGwMgiOQdHP .icon-shape,#mermaid-svg-NpLzuwGwMgiOQdHP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NpLzuwGwMgiOQdHP .icon-shape p,#mermaid-svg-NpLzuwGwMgiOQdHP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NpLzuwGwMgiOQdHP .icon-shape .label rect,#mermaid-svg-NpLzuwGwMgiOQdHP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NpLzuwGwMgiOQdHP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NpLzuwGwMgiOQdHP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NpLzuwGwMgiOQdHP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 自然语言问题
Agent 规划
Query Formula
模型白名单校验
可信租户/账户范围
SQL Builder
分析数据库
total + 当前页 + 完整性
Formula 示例:
json
{
"domain": "position",
"queryType": "aggregate",
"metrics": ["marketValueSum"],
"dimensions": ["securityName"],
"timeRange": {"preset": "latest"},
"orderBy": [{"field": "marketValueSum", "direction": "desc"}],
"page": {"pageSize": 10}
}
关键规则:
- Agent 不传原始 SQL;
- 字段、指标、Join、聚合函数均来自模型白名单;
- 服务端先过滤、聚合、排序和统计 total,再分页;
- 输出带
total、hasMore、resultCompleteness; - 多币种、时间快照、数据权限必须由服务端明确披露。
这也是金融、订单、风控、医疗等高口径/高权限领域更可靠的模式。
11. 模式八:RAG 检索 + 权限投影
核心思想
向量相似度只负责"找得到",不能决定"能不能给用户看"。
#mermaid-svg-WiizgeW8raDlWt8Z{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-WiizgeW8raDlWt8Z .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WiizgeW8raDlWt8Z .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WiizgeW8raDlWt8Z .error-icon{fill:#552222;}#mermaid-svg-WiizgeW8raDlWt8Z .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WiizgeW8raDlWt8Z .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WiizgeW8raDlWt8Z .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WiizgeW8raDlWt8Z .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WiizgeW8raDlWt8Z .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WiizgeW8raDlWt8Z .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WiizgeW8raDlWt8Z .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WiizgeW8raDlWt8Z .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WiizgeW8raDlWt8Z .marker.cross{stroke:#333333;}#mermaid-svg-WiizgeW8raDlWt8Z svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WiizgeW8raDlWt8Z p{margin:0;}#mermaid-svg-WiizgeW8raDlWt8Z .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WiizgeW8raDlWt8Z .cluster-label text{fill:#333;}#mermaid-svg-WiizgeW8raDlWt8Z .cluster-label span{color:#333;}#mermaid-svg-WiizgeW8raDlWt8Z .cluster-label span p{background-color:transparent;}#mermaid-svg-WiizgeW8raDlWt8Z .label text,#mermaid-svg-WiizgeW8raDlWt8Z span{fill:#333;color:#333;}#mermaid-svg-WiizgeW8raDlWt8Z .node rect,#mermaid-svg-WiizgeW8raDlWt8Z .node circle,#mermaid-svg-WiizgeW8raDlWt8Z .node ellipse,#mermaid-svg-WiizgeW8raDlWt8Z .node polygon,#mermaid-svg-WiizgeW8raDlWt8Z .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WiizgeW8raDlWt8Z .rough-node .label text,#mermaid-svg-WiizgeW8raDlWt8Z .node .label text,#mermaid-svg-WiizgeW8raDlWt8Z .image-shape .label,#mermaid-svg-WiizgeW8raDlWt8Z .icon-shape .label{text-anchor:middle;}#mermaid-svg-WiizgeW8raDlWt8Z .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WiizgeW8raDlWt8Z .rough-node .label,#mermaid-svg-WiizgeW8raDlWt8Z .node .label,#mermaid-svg-WiizgeW8raDlWt8Z .image-shape .label,#mermaid-svg-WiizgeW8raDlWt8Z .icon-shape .label{text-align:center;}#mermaid-svg-WiizgeW8raDlWt8Z .node.clickable{cursor:pointer;}#mermaid-svg-WiizgeW8raDlWt8Z .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WiizgeW8raDlWt8Z .arrowheadPath{fill:#333333;}#mermaid-svg-WiizgeW8raDlWt8Z .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WiizgeW8raDlWt8Z .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WiizgeW8raDlWt8Z .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WiizgeW8raDlWt8Z .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WiizgeW8raDlWt8Z .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WiizgeW8raDlWt8Z .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WiizgeW8raDlWt8Z .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WiizgeW8raDlWt8Z .cluster text{fill:#333;}#mermaid-svg-WiizgeW8raDlWt8Z .cluster span{color:#333;}#mermaid-svg-WiizgeW8raDlWt8Z 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-WiizgeW8raDlWt8Z .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WiizgeW8raDlWt8Z rect.text{fill:none;stroke-width:0;}#mermaid-svg-WiizgeW8raDlWt8Z .icon-shape,#mermaid-svg-WiizgeW8raDlWt8Z .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WiizgeW8raDlWt8Z .icon-shape p,#mermaid-svg-WiizgeW8raDlWt8Z .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WiizgeW8raDlWt8Z .icon-shape .label rect,#mermaid-svg-WiizgeW8raDlWt8Z .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WiizgeW8raDlWt8Z .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WiizgeW8raDlWt8Z .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WiizgeW8raDlWt8Z :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户问题
Embedding
Vector Store
候选知识片段
租户过滤
角色/菜单/文档权限过滤
版本/有效期/来源校验
字段投影与引用
Agent 回答
企业知识工具的常见拆分
| 工具 | 职责 |
|---|---|
search_knowledge |
返回少量候选、标题、来源、摘要和稳定 ID |
get_knowledge_document |
根据稳定 ID 获取某篇已授权正文 |
get_navigation_link |
根据权限、平台和菜单生成可跳转入口 |
不推荐
- 把所有原始向量命中文本直接塞给模型;
- 根据"相似度最高"绕过文档权限;
- 返回其他租户、已下线版本或无菜单权限的链接;
- 将检索结果视为最终答案而不保留来源与时效。
12. 模式九:大结果集、资源句柄与异步导出
原则
模型上下文不是数据仓库。几千行明细、完整日志、CSV 或大对象不应直接放到 content.text。
#mermaid-svg-jGkyy1M6o9Nwzvhs{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-jGkyy1M6o9Nwzvhs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jGkyy1M6o9Nwzvhs .error-icon{fill:#552222;}#mermaid-svg-jGkyy1M6o9Nwzvhs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jGkyy1M6o9Nwzvhs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jGkyy1M6o9Nwzvhs .marker.cross{stroke:#333333;}#mermaid-svg-jGkyy1M6o9Nwzvhs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jGkyy1M6o9Nwzvhs p{margin:0;}#mermaid-svg-jGkyy1M6o9Nwzvhs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jGkyy1M6o9Nwzvhs .cluster-label text{fill:#333;}#mermaid-svg-jGkyy1M6o9Nwzvhs .cluster-label span{color:#333;}#mermaid-svg-jGkyy1M6o9Nwzvhs .cluster-label span p{background-color:transparent;}#mermaid-svg-jGkyy1M6o9Nwzvhs .label text,#mermaid-svg-jGkyy1M6o9Nwzvhs span{fill:#333;color:#333;}#mermaid-svg-jGkyy1M6o9Nwzvhs .node rect,#mermaid-svg-jGkyy1M6o9Nwzvhs .node circle,#mermaid-svg-jGkyy1M6o9Nwzvhs .node ellipse,#mermaid-svg-jGkyy1M6o9Nwzvhs .node polygon,#mermaid-svg-jGkyy1M6o9Nwzvhs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jGkyy1M6o9Nwzvhs .rough-node .label text,#mermaid-svg-jGkyy1M6o9Nwzvhs .node .label text,#mermaid-svg-jGkyy1M6o9Nwzvhs .image-shape .label,#mermaid-svg-jGkyy1M6o9Nwzvhs .icon-shape .label{text-anchor:middle;}#mermaid-svg-jGkyy1M6o9Nwzvhs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jGkyy1M6o9Nwzvhs .rough-node .label,#mermaid-svg-jGkyy1M6o9Nwzvhs .node .label,#mermaid-svg-jGkyy1M6o9Nwzvhs .image-shape .label,#mermaid-svg-jGkyy1M6o9Nwzvhs .icon-shape .label{text-align:center;}#mermaid-svg-jGkyy1M6o9Nwzvhs .node.clickable{cursor:pointer;}#mermaid-svg-jGkyy1M6o9Nwzvhs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jGkyy1M6o9Nwzvhs .arrowheadPath{fill:#333333;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jGkyy1M6o9Nwzvhs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jGkyy1M6o9Nwzvhs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jGkyy1M6o9Nwzvhs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jGkyy1M6o9Nwzvhs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jGkyy1M6o9Nwzvhs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jGkyy1M6o9Nwzvhs .cluster text{fill:#333;}#mermaid-svg-jGkyy1M6o9Nwzvhs .cluster span{color:#333;}#mermaid-svg-jGkyy1M6o9Nwzvhs 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-jGkyy1M6o9Nwzvhs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jGkyy1M6o9Nwzvhs rect.text{fill:none;stroke-width:0;}#mermaid-svg-jGkyy1M6o9Nwzvhs .icon-shape,#mermaid-svg-jGkyy1M6o9Nwzvhs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jGkyy1M6o9Nwzvhs .icon-shape p,#mermaid-svg-jGkyy1M6o9Nwzvhs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jGkyy1M6o9Nwzvhs .icon-shape .label rect,#mermaid-svg-jGkyy1M6o9Nwzvhs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jGkyy1M6o9Nwzvhs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jGkyy1M6o9Nwzvhs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jGkyy1M6o9Nwzvhs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 查询请求
服务端过滤/排序/统计
小页预览
摘要/聚合
异步导出任务
Agent
taskId / resource URI
短期授权下载或继续读取
常用返回策略
| 需求 | 推荐返回 |
|---|---|
| 用户只问结论 | 聚合指标、少量关键行、统计口径 |
| 用户要列表 | 服务端分页,返回 total 与 continuation |
| 用户要某条详情 | 用稳定 ID 调 get_detail |
| 用户要完整文件 | 异步导出 Task,返回 taskId/状态/短期授权下载 |
| Agent 需要分析大量数据 | 服务端先聚合/过滤,或在受限代码执行环境内处理 |
分页设计
业务工具返回结果的分页不是 MCP 协议强制统一字段,通常需自行定义:
json
{
"rows": [],
"total": 128493,
"paging": {
"pageSize": 50,
"hasMore": true,
"nextCursor": "opaque-signed-cursor",
"resultCompleteness": "CURRENT_PAGE_ONLY"
}
}
生产 cursor 建议绑定:
text
queryHash + permissionVersion + sort keys + snapshot watermark
+ expiry + signature
不要只编码页号;底层数据变化时 OFFSET 深分页会导致重复、漏行和性能下降。
13. 模式十:读写分离、确认与 Saga
核心思想
读操作和写操作应当有不同的风险模型。
#mermaid-svg-Dm3ffzkwdPwl6fDZ{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-Dm3ffzkwdPwl6fDZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .error-icon{fill:#552222;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .marker.cross{stroke:#333333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ p{margin:0;}#mermaid-svg-Dm3ffzkwdPwl6fDZ defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-Dm3ffzkwdPwl6fDZ g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Dm3ffzkwdPwl6fDZ g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Dm3ffzkwdPwl6fDZ .edgeLabel .label text{fill:#333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .label div .edgeLabel{color:#333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ #statediagram-barbEnd{fill:#333333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .cluster-label,#mermaid-svg-Dm3ffzkwdPwl6fDZ .nodeLabel{color:#131300;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .note-edge{stroke-dasharray:5;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-note text{fill:black;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram-note .nodeLabel{color:black;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagram .edgeLabel{color:red;}#mermaid-svg-Dm3ffzkwdPwl6fDZ #dependencyStart,#mermaid-svg-Dm3ffzkwdPwl6fDZ #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-Dm3ffzkwdPwl6fDZ .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Dm3ffzkwdPwl6fDZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Schema / 权限 / 业务校验
高风险写操作
用户拒绝/超时
用户确认
写入成功
部分失败
补偿失败/人工介入
补偿成功
Draft
Validated
AwaitingConfirmation
Rejected
Executing
Succeeded
Compensating
Failed
写工具的标准设计
| 控制 | 说明 |
|---|---|
| 显式动词 | create_、update_、cancel_、approve_,不能伪装成 query_ |
| 幂等键 | 防止 Agent 重试造成重复下单/重复创建 |
| 预检 | validate_* 或 dry-run,返回影响范围 |
| 人工确认 | 金额、删除、审批、外发、权限变更等高风险操作必须确认 |
| 审批 | 按金额、角色、数据级别接入工作流 |
| 状态查询 | get_task_status / get_operation_status |
| 补偿 | 跨系统非事务操作使用 Saga/补偿,而非假设分布式事务 |
| 审计 | 记录 actor、理由、请求摘要、审批、幂等键、结果和 traceId |
常见工具组合
text
validate_payment → preview_payment → confirm_payment → submit_payment
↘ get_payment_status
不要让一个 pay() 工具同时"猜金额、查余额、创建付款、自动确认并提交"。
14. 模式十一:异步任务(Tasks / Job Handle)
适用场景
- 大文件导入/导出;
- 批量写入;
- 长时间报表生成;
- 数据同步、代码扫描、视频/文档处理;
- 需要中途补充信息或人工审批的流程。
Worker / Workflow MCP Server Agent Worker / Workflow MCP Server Agent #mermaid-svg-2dSMzAnTgcfkbXIm{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-2dSMzAnTgcfkbXIm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2dSMzAnTgcfkbXIm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2dSMzAnTgcfkbXIm .error-icon{fill:#552222;}#mermaid-svg-2dSMzAnTgcfkbXIm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2dSMzAnTgcfkbXIm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2dSMzAnTgcfkbXIm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2dSMzAnTgcfkbXIm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2dSMzAnTgcfkbXIm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2dSMzAnTgcfkbXIm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2dSMzAnTgcfkbXIm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2dSMzAnTgcfkbXIm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2dSMzAnTgcfkbXIm .marker.cross{stroke:#333333;}#mermaid-svg-2dSMzAnTgcfkbXIm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2dSMzAnTgcfkbXIm p{margin:0;}#mermaid-svg-2dSMzAnTgcfkbXIm .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-2dSMzAnTgcfkbXIm text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-2dSMzAnTgcfkbXIm .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-2dSMzAnTgcfkbXIm .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-2dSMzAnTgcfkbXIm .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-2dSMzAnTgcfkbXIm .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-2dSMzAnTgcfkbXIm #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-2dSMzAnTgcfkbXIm .sequenceNumber{fill:white;}#mermaid-svg-2dSMzAnTgcfkbXIm #sequencenumber{fill:#333;}#mermaid-svg-2dSMzAnTgcfkbXIm #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-2dSMzAnTgcfkbXIm .messageText{fill:#333;stroke:none;}#mermaid-svg-2dSMzAnTgcfkbXIm .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-2dSMzAnTgcfkbXIm .labelText,#mermaid-svg-2dSMzAnTgcfkbXIm .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-2dSMzAnTgcfkbXIm .loopText,#mermaid-svg-2dSMzAnTgcfkbXIm .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-2dSMzAnTgcfkbXIm .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-2dSMzAnTgcfkbXIm .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-2dSMzAnTgcfkbXIm .noteText,#mermaid-svg-2dSMzAnTgcfkbXIm .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-2dSMzAnTgcfkbXIm .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-2dSMzAnTgcfkbXIm .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-2dSMzAnTgcfkbXIm .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-2dSMzAnTgcfkbXIm .actorPopupMenu{position:absolute;}#mermaid-svg-2dSMzAnTgcfkbXIm .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-2dSMzAnTgcfkbXIm .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-2dSMzAnTgcfkbXIm .actor-man circle,#mermaid-svg-2dSMzAnTgcfkbXIm line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-2dSMzAnTgcfkbXIm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} loop 轮询或通知 start_export(filters) 创建异步任务 taskId + status=queued get_task(taskId) running / needs_input / succeeded / failed get_export_result(taskId) 短期授权 Resource / 下载链接
必须做到:
- taskId 不是授权能力本身;每次读取任务仍重新鉴权;
- 任务有租户、创建者、权限版本、过期时间和最大输出大小;
- 失败返回可操作错误码,不能只说"失败";
- 导出文件有 TTL、访问审计、敏感字段策略;
- 可重试的任务必须有幂等/去重策略。
15. 模式十二:工具发现、命名空间与按需加载
问题
工具达到几十、几百甚至上千个时,把全部 schema 放入模型上下文会增加成本、延迟并降低选择准确性。
常用做法
#mermaid-svg-wp7JAalcFrlTybHN{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-wp7JAalcFrlTybHN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wp7JAalcFrlTybHN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wp7JAalcFrlTybHN .error-icon{fill:#552222;}#mermaid-svg-wp7JAalcFrlTybHN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wp7JAalcFrlTybHN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wp7JAalcFrlTybHN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wp7JAalcFrlTybHN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wp7JAalcFrlTybHN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wp7JAalcFrlTybHN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wp7JAalcFrlTybHN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wp7JAalcFrlTybHN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wp7JAalcFrlTybHN .marker.cross{stroke:#333333;}#mermaid-svg-wp7JAalcFrlTybHN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wp7JAalcFrlTybHN p{margin:0;}#mermaid-svg-wp7JAalcFrlTybHN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wp7JAalcFrlTybHN .cluster-label text{fill:#333;}#mermaid-svg-wp7JAalcFrlTybHN .cluster-label span{color:#333;}#mermaid-svg-wp7JAalcFrlTybHN .cluster-label span p{background-color:transparent;}#mermaid-svg-wp7JAalcFrlTybHN .label text,#mermaid-svg-wp7JAalcFrlTybHN span{fill:#333;color:#333;}#mermaid-svg-wp7JAalcFrlTybHN .node rect,#mermaid-svg-wp7JAalcFrlTybHN .node circle,#mermaid-svg-wp7JAalcFrlTybHN .node ellipse,#mermaid-svg-wp7JAalcFrlTybHN .node polygon,#mermaid-svg-wp7JAalcFrlTybHN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wp7JAalcFrlTybHN .rough-node .label text,#mermaid-svg-wp7JAalcFrlTybHN .node .label text,#mermaid-svg-wp7JAalcFrlTybHN .image-shape .label,#mermaid-svg-wp7JAalcFrlTybHN .icon-shape .label{text-anchor:middle;}#mermaid-svg-wp7JAalcFrlTybHN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wp7JAalcFrlTybHN .rough-node .label,#mermaid-svg-wp7JAalcFrlTybHN .node .label,#mermaid-svg-wp7JAalcFrlTybHN .image-shape .label,#mermaid-svg-wp7JAalcFrlTybHN .icon-shape .label{text-align:center;}#mermaid-svg-wp7JAalcFrlTybHN .node.clickable{cursor:pointer;}#mermaid-svg-wp7JAalcFrlTybHN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wp7JAalcFrlTybHN .arrowheadPath{fill:#333333;}#mermaid-svg-wp7JAalcFrlTybHN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wp7JAalcFrlTybHN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wp7JAalcFrlTybHN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wp7JAalcFrlTybHN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wp7JAalcFrlTybHN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wp7JAalcFrlTybHN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wp7JAalcFrlTybHN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wp7JAalcFrlTybHN .cluster text{fill:#333;}#mermaid-svg-wp7JAalcFrlTybHN .cluster span{color:#333;}#mermaid-svg-wp7JAalcFrlTybHN 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-wp7JAalcFrlTybHN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wp7JAalcFrlTybHN rect.text{fill:none;stroke-width:0;}#mermaid-svg-wp7JAalcFrlTybHN .icon-shape,#mermaid-svg-wp7JAalcFrlTybHN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wp7JAalcFrlTybHN .icon-shape p,#mermaid-svg-wp7JAalcFrlTybHN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wp7JAalcFrlTybHN .icon-shape .label rect,#mermaid-svg-wp7JAalcFrlTybHN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wp7JAalcFrlTybHN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wp7JAalcFrlTybHN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wp7JAalcFrlTybHN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户意图
工具目录 / 搜索
按领域加载少量候选工具
调用最合适的工具
结果
| 做法 | 说明 |
|---|---|
| 命名空间 | crm_search_customer、oms_get_order,让边界可读 |
| 工具套餐 | 按角色、部门、产品、环境返回不同工具集合 |
preferredFor |
描述推荐场景 |
notPreferredFor |
明确相邻工具的边界 |
| 延迟加载/工具搜索 | 仅在需要时加载完整 Schema |
| 热门工具常驻 | 将高频、低风险工具保留在初始上下文 |
| 原子工具下沉 | 默认暴露 Compose 工具,原子工具作为内部实现或低优先级候选 |
工具名称应稳定、动作导向、避免歧义:
text
推荐:search_customer, get_customer_profile, list_customer_orders
不推荐:customer, query_data, execute, process
16. 模式十三:输入/输出契约与上下文预算
16.1 输入 Schema
每个参数应回答:
- 它表示什么;
- 是否必填;
- 类型和可选枚举;
- 默认值与上限;
- 是否可由用户输入,还是只能由服务端上下文注入;
- 缺失或歧义时如何处理。
不好的参数:
json
{"user": "?"}
更好的参数:
json
{
"customerId": "稳定业务标识,仅可使用服务端实体解析结果",
"timeRange": {"startDate": "2026-08-01", "endDate": "2026-08-20"},
"pageSize": "默认 20,最大 100"
}
16.2 输出三通道
| 通道 | 放什么 | 不放什么 |
|---|---|---|
structuredContent |
紧凑、稳定、机器可读的业务结果 | prompt、内部规则、完整大对象 |
content |
用户可读摘要、说明、引用 | 重复的大 JSON、内部 SQL/堆栈 |
_meta |
UI 专用、Agent 指引、隐藏字段、内部辅助信息 | 应展示给用户的业务结果 |
一个典型结果:
json
{
"structuredContent": {
"total": 320,
"rows": [{"id": "o_123", "status": "PAID", "amount": 98.5}],
"paging": {"hasMore": true, "nextCursor": "..."}
},
"content": [
{"type": "text", "text": "查询到 320 笔订单,当前返回前 20 笔。"}
],
"_meta": {
"displayLabels": {"amount": "订单金额"},
"hiddenFields": ["internalRiskCode"]
}
}
16.3 稳定 ID 优先
列表工具应返回稳定 ID / 引用句柄,后续详情、更新、下钻都使用该 ID,而不是让 Agent 从展示名称中猜内部 Key。
17. 模式十四:可观测性、评测与审计
17.1 一次调用应可回答的问题
#mermaid-svg-rURiI7Hxvu4EmUFq{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-rURiI7Hxvu4EmUFq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rURiI7Hxvu4EmUFq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rURiI7Hxvu4EmUFq .error-icon{fill:#552222;}#mermaid-svg-rURiI7Hxvu4EmUFq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rURiI7Hxvu4EmUFq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rURiI7Hxvu4EmUFq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rURiI7Hxvu4EmUFq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rURiI7Hxvu4EmUFq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rURiI7Hxvu4EmUFq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rURiI7Hxvu4EmUFq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rURiI7Hxvu4EmUFq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rURiI7Hxvu4EmUFq .marker.cross{stroke:#333333;}#mermaid-svg-rURiI7Hxvu4EmUFq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rURiI7Hxvu4EmUFq p{margin:0;}#mermaid-svg-rURiI7Hxvu4EmUFq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rURiI7Hxvu4EmUFq .cluster-label text{fill:#333;}#mermaid-svg-rURiI7Hxvu4EmUFq .cluster-label span{color:#333;}#mermaid-svg-rURiI7Hxvu4EmUFq .cluster-label span p{background-color:transparent;}#mermaid-svg-rURiI7Hxvu4EmUFq .label text,#mermaid-svg-rURiI7Hxvu4EmUFq span{fill:#333;color:#333;}#mermaid-svg-rURiI7Hxvu4EmUFq .node rect,#mermaid-svg-rURiI7Hxvu4EmUFq .node circle,#mermaid-svg-rURiI7Hxvu4EmUFq .node ellipse,#mermaid-svg-rURiI7Hxvu4EmUFq .node polygon,#mermaid-svg-rURiI7Hxvu4EmUFq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rURiI7Hxvu4EmUFq .rough-node .label text,#mermaid-svg-rURiI7Hxvu4EmUFq .node .label text,#mermaid-svg-rURiI7Hxvu4EmUFq .image-shape .label,#mermaid-svg-rURiI7Hxvu4EmUFq .icon-shape .label{text-anchor:middle;}#mermaid-svg-rURiI7Hxvu4EmUFq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rURiI7Hxvu4EmUFq .rough-node .label,#mermaid-svg-rURiI7Hxvu4EmUFq .node .label,#mermaid-svg-rURiI7Hxvu4EmUFq .image-shape .label,#mermaid-svg-rURiI7Hxvu4EmUFq .icon-shape .label{text-align:center;}#mermaid-svg-rURiI7Hxvu4EmUFq .node.clickable{cursor:pointer;}#mermaid-svg-rURiI7Hxvu4EmUFq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rURiI7Hxvu4EmUFq .arrowheadPath{fill:#333333;}#mermaid-svg-rURiI7Hxvu4EmUFq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rURiI7Hxvu4EmUFq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rURiI7Hxvu4EmUFq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rURiI7Hxvu4EmUFq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rURiI7Hxvu4EmUFq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rURiI7Hxvu4EmUFq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rURiI7Hxvu4EmUFq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rURiI7Hxvu4EmUFq .cluster text{fill:#333;}#mermaid-svg-rURiI7Hxvu4EmUFq .cluster span{color:#333;}#mermaid-svg-rURiI7Hxvu4EmUFq 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-rURiI7Hxvu4EmUFq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rURiI7Hxvu4EmUFq rect.text{fill:none;stroke-width:0;}#mermaid-svg-rURiI7Hxvu4EmUFq .icon-shape,#mermaid-svg-rURiI7Hxvu4EmUFq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rURiI7Hxvu4EmUFq .icon-shape p,#mermaid-svg-rURiI7Hxvu4EmUFq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rURiI7Hxvu4EmUFq .icon-shape .label rect,#mermaid-svg-rURiI7Hxvu4EmUFq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rURiI7Hxvu4EmUFq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rURiI7Hxvu4EmUFq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rURiI7Hxvu4EmUFq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} traceId
谁调用?
调用哪个工具/版本?
使用什么权限范围?
调用哪个上游?
结果、耗时、错误码?
是否有用户确认/审批?
建议最少记录:
| 类别 | 字段 |
|---|---|
| 身份 | tenant、user、client、role、授权 scope |
| 契约 | tool name、tool version、schema version、registry revision |
| 请求 | 已脱敏参数摘要、idempotency key、query hash |
| 权限 | permission version、授权范围计数、策略命中 |
| 执行 | traceId、上游、耗时、重试、资源消耗 |
| 结果 | 成功/失败、稳定错误码、返回行数、是否截断 |
| 写操作 | 确认人、审批单、前后状态、补偿结果 |
17.2 Agent 评测
工具上线前不能只测 HTTP 200。应构建用例集:
- 正常意图;
- 相似工具选择;
- 缺失参数;
- 多候选实体;
- 越权范围;
- 大数据分页;
- 上游超时;
- 写操作重复提交;
- 提示注入文本;
- 工具描述变更后的回归。
衡量指标:
text
工具选择正确率
参数一次成功率
澄清问题正确率
权限拒绝正确率
端到端任务成功率
平均调用轮数
Token / 延迟 / 上游成本
人工接管率
18. 安全模式与反模式
18.1 推荐安全架构
#mermaid-svg-ziBlgTqqyIzvg5mX{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-ziBlgTqqyIzvg5mX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ziBlgTqqyIzvg5mX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ziBlgTqqyIzvg5mX .error-icon{fill:#552222;}#mermaid-svg-ziBlgTqqyIzvg5mX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ziBlgTqqyIzvg5mX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ziBlgTqqyIzvg5mX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ziBlgTqqyIzvg5mX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ziBlgTqqyIzvg5mX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ziBlgTqqyIzvg5mX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ziBlgTqqyIzvg5mX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ziBlgTqqyIzvg5mX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ziBlgTqqyIzvg5mX .marker.cross{stroke:#333333;}#mermaid-svg-ziBlgTqqyIzvg5mX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ziBlgTqqyIzvg5mX p{margin:0;}#mermaid-svg-ziBlgTqqyIzvg5mX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ziBlgTqqyIzvg5mX .cluster-label text{fill:#333;}#mermaid-svg-ziBlgTqqyIzvg5mX .cluster-label span{color:#333;}#mermaid-svg-ziBlgTqqyIzvg5mX .cluster-label span p{background-color:transparent;}#mermaid-svg-ziBlgTqqyIzvg5mX .label text,#mermaid-svg-ziBlgTqqyIzvg5mX span{fill:#333;color:#333;}#mermaid-svg-ziBlgTqqyIzvg5mX .node rect,#mermaid-svg-ziBlgTqqyIzvg5mX .node circle,#mermaid-svg-ziBlgTqqyIzvg5mX .node ellipse,#mermaid-svg-ziBlgTqqyIzvg5mX .node polygon,#mermaid-svg-ziBlgTqqyIzvg5mX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ziBlgTqqyIzvg5mX .rough-node .label text,#mermaid-svg-ziBlgTqqyIzvg5mX .node .label text,#mermaid-svg-ziBlgTqqyIzvg5mX .image-shape .label,#mermaid-svg-ziBlgTqqyIzvg5mX .icon-shape .label{text-anchor:middle;}#mermaid-svg-ziBlgTqqyIzvg5mX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ziBlgTqqyIzvg5mX .rough-node .label,#mermaid-svg-ziBlgTqqyIzvg5mX .node .label,#mermaid-svg-ziBlgTqqyIzvg5mX .image-shape .label,#mermaid-svg-ziBlgTqqyIzvg5mX .icon-shape .label{text-align:center;}#mermaid-svg-ziBlgTqqyIzvg5mX .node.clickable{cursor:pointer;}#mermaid-svg-ziBlgTqqyIzvg5mX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ziBlgTqqyIzvg5mX .arrowheadPath{fill:#333333;}#mermaid-svg-ziBlgTqqyIzvg5mX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ziBlgTqqyIzvg5mX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ziBlgTqqyIzvg5mX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ziBlgTqqyIzvg5mX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ziBlgTqqyIzvg5mX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ziBlgTqqyIzvg5mX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ziBlgTqqyIzvg5mX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ziBlgTqqyIzvg5mX .cluster text{fill:#333;}#mermaid-svg-ziBlgTqqyIzvg5mX .cluster span{color:#333;}#mermaid-svg-ziBlgTqqyIzvg5mX 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-ziBlgTqqyIzvg5mX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ziBlgTqqyIzvg5mX rect.text{fill:none;stroke-width:0;}#mermaid-svg-ziBlgTqqyIzvg5mX .icon-shape,#mermaid-svg-ziBlgTqqyIzvg5mX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ziBlgTqqyIzvg5mX .icon-shape p,#mermaid-svg-ziBlgTqqyIzvg5mX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ziBlgTqqyIzvg5mX .icon-shape .label rect,#mermaid-svg-ziBlgTqqyIzvg5mX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ziBlgTqqyIzvg5mX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ziBlgTqqyIzvg5mX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ziBlgTqqyIzvg5mX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent
Gateway
认证 / OAuth
权限 / ABAC / 数据范围
风险/合规/确认
Tool
受控出网代理
Vault / 短期凭证
不可抵赖审计
18.2 高风险反模式
| 反模式 | 后果 | 正确替代 |
|---|---|---|
execute_sql(sql) |
越权、注入、资源耗尽、口径失控 | 语义模型/查询 DSL |
proxy(url, method, headers, body) |
SSRF、Token 外泄、任意内网访问 | 白名单原子适配器 |
| Agent 入参指定 tenant/account | 横向越权 | Gateway 从身份服务注入可信范围 |
| 任意 shell 工具 | 本机持久化、凭证泄漏、供应链攻击 | 命令白名单、沙箱、明确确认 |
| 将 Token 原样转发下游 | confused deputy、Token 盗用 | audience 绑定/受控服务身份 |
| 返回完整数据库行 | 敏感字段泄漏、上下文膨胀 | 字段投影、分页、导出任务 |
| 写工具自动执行 | 错误下单、误删、不可逆影响 | preview + confirm + idempotency |
| RAG 命中即展示 | 知识/租户/菜单越权 | 检索后权限过滤和输出投影 |
| 把所有工具初始暴露 | 工具选择混乱、Token 成本高 | 套餐/搜索/按需加载 |
18.3 提示注入的正确认识
工具描述、资源内容、RAG 文档、Issue、README 和上游 API 返回的文本,都可能包含恶意指令。它们是不可信数据,不能改变:
- 系统安全策略;
- 认证/权限边界;
- 用户确认要求;
- 数据导出规则;
- 工具调用的审批条件。
应将"文本内容"和"可执行授权"分离:文本只影响回答或澄清,不能直接获得执行权。
19. 企业落地的参考蓝图
#mermaid-svg-qlVDAl7iRBZoVWVU{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-qlVDAl7iRBZoVWVU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qlVDAl7iRBZoVWVU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qlVDAl7iRBZoVWVU .error-icon{fill:#552222;}#mermaid-svg-qlVDAl7iRBZoVWVU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qlVDAl7iRBZoVWVU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qlVDAl7iRBZoVWVU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qlVDAl7iRBZoVWVU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qlVDAl7iRBZoVWVU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qlVDAl7iRBZoVWVU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qlVDAl7iRBZoVWVU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qlVDAl7iRBZoVWVU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qlVDAl7iRBZoVWVU .marker.cross{stroke:#333333;}#mermaid-svg-qlVDAl7iRBZoVWVU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qlVDAl7iRBZoVWVU p{margin:0;}#mermaid-svg-qlVDAl7iRBZoVWVU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qlVDAl7iRBZoVWVU .cluster-label text{fill:#333;}#mermaid-svg-qlVDAl7iRBZoVWVU .cluster-label span{color:#333;}#mermaid-svg-qlVDAl7iRBZoVWVU .cluster-label span p{background-color:transparent;}#mermaid-svg-qlVDAl7iRBZoVWVU .label text,#mermaid-svg-qlVDAl7iRBZoVWVU span{fill:#333;color:#333;}#mermaid-svg-qlVDAl7iRBZoVWVU .node rect,#mermaid-svg-qlVDAl7iRBZoVWVU .node circle,#mermaid-svg-qlVDAl7iRBZoVWVU .node ellipse,#mermaid-svg-qlVDAl7iRBZoVWVU .node polygon,#mermaid-svg-qlVDAl7iRBZoVWVU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qlVDAl7iRBZoVWVU .rough-node .label text,#mermaid-svg-qlVDAl7iRBZoVWVU .node .label text,#mermaid-svg-qlVDAl7iRBZoVWVU .image-shape .label,#mermaid-svg-qlVDAl7iRBZoVWVU .icon-shape .label{text-anchor:middle;}#mermaid-svg-qlVDAl7iRBZoVWVU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qlVDAl7iRBZoVWVU .rough-node .label,#mermaid-svg-qlVDAl7iRBZoVWVU .node .label,#mermaid-svg-qlVDAl7iRBZoVWVU .image-shape .label,#mermaid-svg-qlVDAl7iRBZoVWVU .icon-shape .label{text-align:center;}#mermaid-svg-qlVDAl7iRBZoVWVU .node.clickable{cursor:pointer;}#mermaid-svg-qlVDAl7iRBZoVWVU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qlVDAl7iRBZoVWVU .arrowheadPath{fill:#333333;}#mermaid-svg-qlVDAl7iRBZoVWVU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qlVDAl7iRBZoVWVU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qlVDAl7iRBZoVWVU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qlVDAl7iRBZoVWVU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qlVDAl7iRBZoVWVU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qlVDAl7iRBZoVWVU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qlVDAl7iRBZoVWVU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qlVDAl7iRBZoVWVU .cluster text{fill:#333;}#mermaid-svg-qlVDAl7iRBZoVWVU .cluster span{color:#333;}#mermaid-svg-qlVDAl7iRBZoVWVU 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-qlVDAl7iRBZoVWVU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qlVDAl7iRBZoVWVU rect.text{fill:none;stroke-width:0;}#mermaid-svg-qlVDAl7iRBZoVWVU .icon-shape,#mermaid-svg-qlVDAl7iRBZoVWVU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qlVDAl7iRBZoVWVU .icon-shape p,#mermaid-svg-qlVDAl7iRBZoVWVU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qlVDAl7iRBZoVWVU .icon-shape .label rect,#mermaid-svg-qlVDAl7iRBZoVWVU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qlVDAl7iRBZoVWVU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qlVDAl7iRBZoVWVU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qlVDAl7iRBZoVWVU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数据与上游
领域能力层
MCP 平台
边缘层
客户端 / Host
Agent UI
MCP Client
WAF / API Gateway
OAuth 2.1 / IAM
MCP Gateway
Registry / Tool Catalog
Policy Engine
Audit / Trace
Task / Job Service
Compose Tools
Atomic Adapters
RAG Retrieval
Export Service
内部/外部 API
业务数据库
分析数据库
向量库
对象存储
最小可行版本
小团队不需要一开始部署所有组件。可从以下开始:
text
单一远程 MCP Server
→ 明确 Tools + 严格 Schema
→ OAuth/企业 SSO
→ 服务端权限校验
→ 结构化日志 + traceId
→ 分页与字段投影
当工具/团队增多后再引入:
text
Gateway → Registry → Compose → Task/Export → 策略与评测平台