【AI编程系列】MCP 常用设计模式解读

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

成熟度的关键不在"工具数量",而在于是否做到:

  1. 工具契约稳定、边界清晰、Agent 易于选择;
  2. 身份、数据权限和审批来自可信服务端上下文;
  3. 大结果不灌入模型上下文;
  4. 写操作可确认、可幂等、可审计、可恢复;
  5. 远程 MCP 的 OAuth、Token、SSRF 与提示注入风险可控;
  6. 每一次 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_orderscreate_ticketquery_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、环境变量和凭证可见性,危害面反而很大。

必须落实:

  1. 不把未知 MCP Server 当作"普通插件"安装;
  2. Agent 运行身份不使用管理员/root;
  3. 工具按目录、命令和网络最小授权;
  4. 不让工具静默读取 SSH Key、浏览器 Token、.env 或系统凭证;
  5. 对安装脚本、依赖生命周期、子进程和外联进行审计;
  6. 高风险项目在隔离 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 工具提供可复用的基础能力。

设计准则

  1. 一个工具只访问一个权威上游;
  2. 工具名以动词和资源表达用户目标,例如 get_customer_profile
  3. 输入 Schema 只保留必要参数;
  4. 上游字段不是默认全部暴露;需要字段投影和显示标签;
  5. 工具描述应标明何时使用、何时不用,以及与相似工具的边界;
  6. 上游错误转换为稳定的 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,再分页;
  • 输出带 totalhasMoreresultCompleteness
  • 多币种、时间快照、数据权限必须由服务端明确披露。

这也是金融、订单、风控、医疗等高口径/高权限领域更可靠的模式。


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_customeroms_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 → 策略与评测平台

20. 参考资料

  1. MCP 规范总览(2026-07-28)
  2. MCP 架构
  3. MCP Tools 规范
  4. MCP 分页规范
  5. MCP Authorization 规范
  6. MCP Authorization Security Considerations
  7. Anthropic:Writing effective tools for AI agents
  8. Anthropic:Effective context engineering for AI agents
  9. OpenAI:Define tools
  10. OpenAI:Build an MCP server
相关推荐
VIP_CQCRE2 小时前
把 OpenCode 接入 Ace Data Cloud:让 AI 编程能力真正进入 IDE 工作流
大模型·ai编程·开发工具·opencode·acedatacloud
亦暖筑序2 小时前
AgentScope Java 实战:@Tool 方法里到底该不该写业务逻辑?
java·agent·ai编程
geovindu3 小时前
java: Strategy Pattern
java·开发语言·后端·设计模式·策略模式·行为模式
vibecoding7713 小时前
一文搞懂企业级 API 网关选型:12 个维度、4 类企业、7 步落地
人工智能·大模型·ai编程
码匠许师傅14 小时前
【设计模式精讲】29.行为型模式总结与对比(Behavioral Patterns Summary)
c++·设计模式·uml
geovindu17 小时前
CSharp: Observer Pattern
开发语言·后端·观察者模式·设计模式·c#·.netcore·行为模式
旋生万物19 小时前
量子纠错容错率87%?螺旋拓扑码用“相位保护“给量子比特上保险(附Python)
python·ai编程·量子计算·量子纠错·螺旋计算
kyriewen19 小时前
我用 AI 写完一个需求后才发现,最难的不是 prompt,而是验收
前端·程序员·ai编程