ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MCP跨系统集成实战:共享Agent能力的架构设计与治理

MCP跨系统集成实战:共享Agent能力的架构设计与治理

我去年接手了一个跨系统集成项目,当时公司里有三个业务系统——一套订单中心、一套库存管理、一套客服工作台——同时想上 AI Agent。起初大家的选择很一致:每个系统各自接大模型 API,各自设计提示词,各自封装工具。两个月后问题就冒出来了,同样的“查订单状态”逻辑在三个系统里三种写法,结果三种口径;客服想跨系统调库存数据,得靠人工复制粘贴。后来我们引入 MCP(模型上下文协议),在一层统一的 Agent 能力共享底座上把所有系统能力以标准接口暴露出来。这一改,连接打通了,但新的麻烦也跟着来了:会话怎么隔离?权限怎么收敛?一个系统升级工具,另一个系统直接调失败,这种问题怎么防?这篇文章就把这段实践完整拆开,讲讲多系统共享 Agent 能力时到底会发生什么。

适合正在做多系统集成、平台化 AI 能力、或者准备把所有业务系统接进 Agent 的架构师和开发者。如果你以为 MCP 只是“一个协议让 AI 调用工具”,那读完你会明白:跨系统共享时,MCP 真正改写的是一整套集成边界。

1. 多系统共享 Agent 能力的核心命题

1.1 从孤岛到共享:为什么要做跨系统集成

先说清楚“跨系统集成”到底想解决什么问题。企业内部很少只有一个系统,客户数据在 CRM,订单在交易系统,库存和物流又分别在两套平台,客服在处理问题时天然需要同时看这些数据。过去没有 Agent 时,这种跨系统查数主要靠接口对接或者干脆人工搬运。有了 Agent 后,各系统产生了自己的想法:让人工智能直接帮用户查,让大模型自己决定调哪个工具。

但每个系统各接各的,就是一个“Agent 孤岛”。

每个系统维护自己的大模型配置、提示词、工具调用逻辑,能力重复建设;同一个业务实体在不同系统里名字都不一样,模型容易被搞糊涂;更重要的是,跨系统的流程依然跑不起来——客服机器人能查订单,但查完没法自动帮你改地址,因为改地址的工具在另外一套系统里,两边根本没打通。

我们当时的目标很简单:一套 Agent 能力,所有系统都能用。不是给每个系统配一个智能体,而是把智能体当成一个可复用的公共组件,让订单、库存、客服这些系统都通过它对外提供服务。这才把问题从“单个系统怎么接入 AI”变成了“多个系统怎么共享同一套 Agent 能力”。

1.2 MCP 在共享链路中的位置

为什么偏偏是 MCP?你可以把 MCP 理解成一个标准“插座”:Agent 是插头,业务系统的工具和数据能力是插座。只要双方都遵守这个协议,插上就能用,不需要为每一对公司定制双头线。

在单点接入场景里,MCP 的便利性已经够明显了。但在跨系统共享场景里,MCP 的价值远不止“协议统一”这么简单。它最大的贡献是让所有系统在能力暴露这一层达成了公共约定:每个系统只要实现一个 MCP Server,把自己内部的查询、操作封装成标准工具,就可以注册到共享底座里;中心的 Agent 作为一个 MCP Client,不用关心对方到底是 Java 写的还是 Go 写的,也不用关心数据库长什么样,只要按协议去发现工具、调用工具就行。

共享链路里,MCP 处在这样的位置:它既是工具接入的标准层,也是能力路由的寻址层。每个 MCP Server 启动后通过 tools/list 把自己能提供的工具列出来,Agent 运行时向网关要一份过滤后的工具清单,再通过 tools/call 触发具体调用。整个链路里,MCP 管的是“能力和调用”这一层,至于会话归属谁、权限带什么身份、流量怎么控制,这些并不在协议范围内,恰恰是跨系统集成时要额外设计的部分。

1.3 共享带来的收益和隐性成本

共享 Agent 能力后的收益,最直接的是体验一致性。我们接入三个系统后,用户不管在客服工作台还是订单后台发起提问,得到的回答格式、术语、操作按钮都是同一套,不再出现“订单系统叫‘工单’,客服系统叫‘问题单’”这种笑话。

第二个收益是管控集中。模型版本升级、提示词优化、工具权限调整,只需要在共享底座上做一次,所有接进来的系统同时生效。之前那种“给某个系统单独换模型版本,结果另两个系统还在用旧版本跑”的问题直接消失了。

第三个收益是流程打通。Agent 可以在一个请求里串联多个系统的工具,先查订单、再查库存、然后生成处理建议,跨系统编排变成了现实。

但收益背后藏着隐性成本,这部分我在实践中体会特别深。共享意味着所有系统都依赖同一套运行时,一旦底座出问题,所有接入方一起挂,这就是典型的单点放大风险。权限和数据的边界也因为共享变得模糊,工具不再只属于某个系统,而是公共资源,怎么避免越权访问就需要重新设计。排查链路也变长了,一个问题从外部系统一路追到 Agent 运行时再到具体业务系统,中间任何一层日志缺失都可能导致定位困难。

我的结论是:能不能共享,关键不是看技术难度,而是看有没有把“会话隔离、权限隔离、版本治理”这三件事从第一天就当成一等公民来设计。如果这三件事在方案阶段回避了,后面上线一定会在生产环境里还回来。

2. 共享链路的边界划分与关键矛盾

2.1 协议层、传输层、会话层的边界

MCP 底层跑的是 JSON-RPC 2.0,协议本身很干净,但“跨系统共享”决定了你不能只在一个进程里玩。MCP 支持多种传输方式:stdio 适合本地的子进程通信,HTTP+SSE 适合跨网络调用。在跨系统集成里,每个 MCP Server 大概率在各自的服务器上,如果直接用 stdio 让 Agent 运行时拉起一堆子进程,管理和隔离都是灾难。我们选择的做法是引入一层网关,Agent 运行时作为客户端只连网关,网关再把请求转发给各个 MCP Server,相当于把“连接管理”统一收口。

这个分层很关键。协议层管的是消息格式是否正确,传输层管的是连接是否可达,会话层管的是“这个请求属于谁”。很多人在做共享时只解决了前两层,忘了会话层,导致所有系统共享同一个上下文,互相干扰。

2.2 会话管理与能力路由:最容易被忽略的矛盾

共享之后你很快会遇到一个问题:Agent 的会话状态放在哪里?每个系统都希望有自己的对话上下文,同一个用户可能在客服系统里问订单,又去库存系统里查库存,这两个上下文不能混在一起。

我们最终采用了“双维度会话隔离”方案:每个会话都绑定 system_id + user_id 两把钥匙。网关收到请求后,根据这两个字段找到对应的 session,而不是把所有会话都堆在一个全局上下文里。这样订单系统的用户和客服系统的用户即便同时提问,也能做到互无感知。实现上并不复杂,但需要所有对接方遵守约定,在调用 Agent 的请求头里显式带上这两个字段。

另一个矛盾是能力路由。当接进来的 MCP Server 越来越多,工具数量会迅速膨胀。我们后期注册了 47 个工具,如果一次性把所有工具的 schema 都丢给模型,不仅浪费 token,还会增加模型选错工具的概率。所以我们在网关层做了一个能力目录,按“系统 + 工具类型”打标签。比如库存系统的工具只能被库存相关的会话看到,客服系统会话访问不到财务结账工具。模型看到的工具列表永远是被过滤后的子集,准确率和响应速度都有明显提升。

2.3 身份、权限与资源隔离

共享链路上最敏感的就是权限。单系统时代,用户直接登录业务系统,权限由业务系统自己控制;共享之后,请求链路变成了“用户 → 外部系统 → 网关 → MCP Server → 业务系统”,每一步都要知道“谁在调用”和“这个调用者有没有权限”。

直接透传外部系统身份是不行的。某客服系统的人可能同时拥有订单系统的只读权限,但共享 Agent 如果把这个身份透传给库存系统,库存系统的接口就会误认为这是合法请求,甚至可能执行本不该允许的写操作。我们当时的做法是:网关统一签发中间凭证,凭证里包含调用方系统标识、用户标识和一组授权范围;MCP Server 在执行业务逻辑前,先拿着这个凭证通过内部权限服务校验,确定当前调用者只能访问哪些工具、哪些参数。

资源隔离同样不能省。共享底座一旦被某个系统的大批量请求拖垮,所有系统都会受影响。我们给每个接入方分配了独立的并发配额、超时时间和优先级。实时性要求高的客服系统优先级最高,批处理类系统走低优先级队列,从而避免某个系统把公共资源打满导致其他系统雪崩。

3. 实操拆解:搭建一个支撑多业务系统的 Agent 共享底座

3.1 最小可用架构与目录设计

以我们当时的场景为例:三个业务系统(订单、库存、客服)要共享一套 Agent 能力。我们最终落地的架构包含四个核心组件:

  • Agent Runtime:统一编排入口,负责接收请求、调用大模型、决定调用哪些工具、汇总结果。
  • MCP Gateway:负责维持与所有 MCP Server 的长连接,做会话路由、身份校验、能力过滤和数据转发。
  • MCP Server 簇:每个业务系统一套,把自己内部的查询和操作封装成工具,对外只暴露 MCP 协议接口。
  • 能力注册中心:记录工具声明、版本号、所属系统、权限标签,供网关做路由决策。

目录设计上,我们为每个 MCP Server 单独建目录,约定工具命名规范为系统名_动作_对象,例如order_query_detail、inventory_query_stock、customer_update_contact。这个名字看起来简单,实际排查问题的时候非常有用,一眼就能从调用链日志里看出工具归属哪个系统。

3.2 核心实现步骤:从零接通共享链路

第一步,定义统一的能力声明格式。每个 MCP Server 在注册时都要返回一份 JSON Schema,描述工具名、入参、出参、权限标签。我们当时把 schema 放在独立配置中心统一管理,避免每次发版都改代码。下面是一个简化版示例:

{ "name": "order_query_detail", "system": "order_system", "version": "1.2.0", "tags": ["read", "customer_service"], "inputSchema": { "type": "object", "properties": { "order_id": {"type": "string", "description": "订单编号"} }, "required": ["order_id"] } }

第二步,各业务系统实现 MCP Server。这里我们选的是各系统自己维护 SDK 接入,最核心的部分是保持 Server 独立性,不要为了快速接入把逻辑揉进共享进程。

第三步,网关启动后,主动向能力注册中心拉取全量工具清单,并维护到内存里。每次 Agent Runtime 请求工具列表时,网关根据 system_id 和 user_id 生成过滤后的子集返回。

第四步,客户端接入不用管 MCP 细节,我们的 SDK 只暴露两个方法:sendMessage和listCapabilities。业务系统只需要在请求头里带上系统标识和用户标识。

核心调用路径并不复杂:请求进入 Agent Runtime,Runtime 先调用大模型做意图识别,再向网关要一份可用工具列表,模型从列表里挑出工具后,Runtime 通过网关转发到目标 MCP Server,拿到结果再组织自然语言返回。整个过程是同步的,但工具调用可以按依赖关系做并行,比如同时查订单和库存,能减少一半延迟。

3.3 一条共享调用的链路走查

我们用一个具体例子说明。客服系统里,用户问“订单 12345 到哪儿了,缺货的话能不能改别的颜色”。这个请求先进入 Agent Runtime,带着系统标识customer_service和用户 ID。Runtime 拿到的工具列表经过网关过滤后,只包含客服系统允许访问的工具,比如订单查询、库存查询、商品变体查询,不包含订单创建、价格修改这类敏感操作。

模型决定先调order_query_detail查订单状态,再调inventory_query_stock查对应商品的库存。两个调用并行发出,网关把第一个请求路由到订单系统的 MCP Server,把第二个请求路由到库存系统的 MCP Server。结果回来后,模型整合出结论:订单已发货,商品颜色不可改,但同款黑色有库存,如需换货建议联系客服。这样一条指令完成了跨两个系统的数据联动,用户无感,底层链路清晰。

3.4 实测效果与观察指标

三个系统全部接入后,我们做了一轮压测。工具注册数量 47 个,会话并发峰值 200,网关吞吐稳定在每秒 120 个请求左右,P95 响应时间在 2.6 秒以内。这 2.6 秒大部分花在模型推理上,工具调用本身基本是毫秒级。启用能力路由过滤后,单次请求进入大模型的工具 schema 从 47 个降到平均 8 个左右,上下文体积压缩了将近一半,响应时间和 token 成本都有明显下降。

需要特别说明的是,压测中发现瓶颈不在 MCP 网关,而在模型调用量和下游系统的数据库连接池。这提醒我们,共享底座不是把网关做大就完了,下游系统的承受能力才是真正的上限,必须配合配额和熔断一起使用。

4. 踩坑实录:共享后最常见的五类问题

4.1 会话串号:用户 A 看到用户 B 的上下文

我们上线第一周就遇到一次严重事故。两个用户同时在客服系统提问,结果第一个用户看到的回答里带有第二个用户的订单信息。定位后发现,网关在从请求头读取 session 时,只用了 user_id,没有结合 system_id;两个系统里可能出现相同的内部用户编号,会话直接被复用了。修复后我们将 session 键改成system_id + user_id,同时加了会话创建时间的碰撞检测,才彻底解决。

4.2 session 超时与空转偶发

MCP 的会话也有生命周期,调用频率低的系统连接会被空闲回收。某个系统五分钟没调用,再发请求时网关要重新握手建连,导致第一请求多出 300 毫秒延迟。这本身不是错误,但用户体验明显变差。我们最后的处理是给核心系统配置了保活链接,非核心系统则允许冷启动延迟,用超时时间换连接资源。

4.3 工具 schema 版本不一致导致静默失败

这是最隐蔽的坑。某个 MCP Server 升级了订单查询工具的入参,从order_id改为order_no,但没有同步更新注册中心。Agent Runtime 缓存里还是旧 schema,调用时传的是order_id,服务端解析失败,却因为兼容层把异常吞掉了,只返回一个空结果。大模型看到空结果后以为订单不存在,直接告诉用户“查不到”。这个事故的教训是:工具接口变更必须走版本管理,schema 升级后先注册再发布,不能跳过注册中心直接改代码。

4.4 下游数据库连接池被打满

共享底座放量后,订单系统的 MCP Server 因为要处理来自客服、管理后台、批处理三个来源的请求,数据库连接池瞬间打满,导致订单系统整体变慢。排查下来,MCP Server 层没有做任何并发限制,所有请求都直接打到数据库连接池上。我们在网关层按系统加配额,客服系统高优先级,批处理系统低优先级,同时在 MCP Server 内部增加信号量控制并发度,问题才缓解。

4.5 权限放大:客服系统差点拿到财务数据

能力路由做得不够细时,会出现权限放大风险。我们最初只按“系统能否调用某工具”粗粒度控制,结果客服系统的会话能看到财务系统的对账工具。没有真正的恶意操作,但一旦被误触发,影响面不可控。后来我们把权限控制细化到“工具 + 参数 + 数据范围”,比如客服能查订单但不能查成本价,能看库存数量但不能看采购供应商信息。权限模型越细,配置成本越高,但跨系统共享这种场景,粗粒度就是定时炸弹。

下面是问题速查表,方便团队排查时对照:

现象可能根因快速处理
用户看到其他用户的上下文session 键不够唯一改为 system_id + user_id 组合键
首次请求明显变慢会话被空闲回收核心系统启用保活连接
工具返回空结果schema 版本不一致检查注册中心版本,强制同步
下游系统响应突然变慢并发未限制,连接池打满网关配额 + MCP Server 信号量
访问到不该访问的数据权限模型过粗细化到参数级权限标签

5. 运维与治理:让共享能力长期稳定

5.1 可观测性设计:全链路追踪必须做

跨系统共享最怕定位问题找半天。我们的做法是,每个请求从外部系统进入网关时生成一个 trace_id,这个 id 贯穿 Agent Runtime、MCP 转发、业务系统调用全过程。日志行统一带上系统标识、工具名、耗时、状态码。这样一旦用户报“查询失败”,我们可以直接从网关日志里拉出整条链路,看到底是哪一步出了问题。排查多系统集成问题就是查日志、拉链路、对比版本,缺一不可。

5.2 灰度发布与降级策略

MCP Server 升级工具、改模型配置,不能一把梭切全线。我们做了简单的灰度机制:能力注册中心给每个工具加一个“灰度组”字段,网关在路由时优先将灰度组的流量打到新版本 Server 上,稳定后再全量切换。某个 MCP Server 出现故障时,网关侧可以一键下线该系统的全部工具,避免 Agent 把它当成可用能力去调用。这个降级开关在出事故时价值巨大,就算所有下游都挂了,客服系统还能至少给出兜底话术,而不是报错给用户。

5.3 成本与配额治理

共享底座另一大问题是成本归属。大模型的 token 费用是公共池子,如果不区分系统,月底对账会发现某系统消耗了大头,但它带来的业务价值却说不清楚。我们在网关层对每次请求按系统维度打标,模型调用 token 数和工具调用次数分别记录,月底按系统汇总。这样既能看到哪个系统的调用量在涨,也能防止某个系统用共享底座跑批处理任务,挤占实时业务的份额。

配额的设定建议先按峰值流量的两倍预留,随后观察实际使用量逐步下调。不要一开始就卡得很死,否则临时活动带来的流量尖峰会把正常业务一起挡掉。

5.4 一个非常受用的小细节

最后分享一个我们从事故里总结出来的细节。在 MCP Server 返回工具列表时,尽量带上版本号,网关保存一份调用方“最近一次成功调用的版本”绑定关系。当 MCP Server 端工具升级后,网关在路由时优先使用调用方历史验证过的版本,而不是立刻切到新版本。这样即使服务端发布了不兼容变更,受影响的范围也只会是新接入方,而不是所有下游一起崩。我们后来把这条写进了团队的工作手册,遇到工具变更就按这个规则操作,新版本先在灰度组跑三天,再切默认路由。

跨系统共享 Agent 能力这件事,技术上不难理解,难的是把边界意识贯穿到每一个设计决策里。我个人的体会是,MCP 给了我们一个很好的起点,但它不会替你做会话隔离,不会替你做权限控制,也不会替你处理版本兼容。真正让“共享”成立的,是围绕它搭起来的那一整套治理机制。每次有人问我“我们也要搞 Agent 共享吗”,我会建议先回答这三个问题:会话能否隔离?权限能否独立?升级能否灰度?如果三个答案都是肯定的,那就可以放手去接;如果有任何一个含糊,那还是先把地基打好,再上共享底座。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进