企业里几乎没有"从零开始"的 AI 项目。真实情况是:客户、订单、产品这些数据早就在一堆 RESTful 内部系统里跑着,销售和运营每天用它们查单、查价、查库存。现在要把大模型接进来,最自然的想法是"让 Agent 直接调这些接口"——但真这么干,安全、权限、输出质量三件事会同时出问题。这篇文章记录我们把已有 RESTful 系统 MCP 化、再接到 Agent 层的完整工程路径:工具怎么拆、认证怎么透传、check Agent 怎么设、Text2SQL 怎么接、前端怎么动态渲染。数字按"实测案例口径"标注,不点名任何公司和内部系统。
先把问题钉死。企业内部系统已经是 RESTful 形态:有客户查询接口、订单查询接口、价格查询接口,前端页面调了很多年,权限体系、审计日志都在。现在要接 AI,最省事的做法是让大模型直接拿一串 API key 去调这些接口。这条路有两个硬伤,跑不通:
第一,安全失控。 大模型拿到的是"一把万能钥匙"——它能调哪个接口、不能调哪个,完全取决于 prompt 怎么写。而 prompt 是会变长、会被用户诱导、会在多轮对话里漂移的。销售小李问"我这个月的业绩",模型可能顺手把别人的订单也查了;更糟的是,一个 API key 背后是整个人的数据权限,出了问题无法定位到具体哪一步越权。
第二,输出不可控。 即使接口调通了,大模型拿到的是 JSON,它自己组织语言回答。同一个数据,这一轮说"订单已发货",下一轮可能说成"订单在路上"——没有格式约束,没有二次校验,业务侧不敢直接拿来用。
MCP(Model Context Protocol)的价值就在这里:它把已有系统"工具化"——不是把接口直接暴露给模型,而是包一层标准协议,让 Agent 以"调用工具"的方式访问。工具的输入输出有 schema、有权限上下文、有审计。模型从"直接碰数据库"变成"按菜单点菜",这是工程上的可控与不可控的分界线。推断:MCP 本身不解决幻觉,它只解决"访问通道的标准化",幻觉治理要靠后面的 Agent 设计。
第一个工程决策是"一个 MCP server 暴露多少工具"。常见的错误是按技术接口拆:有一个 /api/customer 就做一个 customer 工具,有一个 /api/order 就做一个 order 工具。看起来合理,实际调度时会出问题——模型面对十几个技术接口,不知道该调哪个,或者调了一串无关的。
我们的原则是按业务域拆:
三个工具背后可能调用的是同一套内部系统,但对 Agent 来说,它们是三件"业务上清楚的事"。这样拆的好处有两个:一是调度准确率高——用户问"这个客户上次下单多少钱",Agent 一眼知道要调订单工具而不是客户工具;二是权限边界清晰——价格工具可以单独加一道审批,不影响其他两个。反过来,如果做成一个"万能查询 Agent",它会倾向于一次调所有接口,把不相关的数据也塞进回答,既浪费 token,又增加越权风险。
经验法则:一个工具对应一个业务意图。如果一个工具的描述里要写三种以上的"如果你想查 X 就……",就说明该拆了。待验证:当工具数量超过 20 个,调度准确率是否会因工具描述膨胀而下降。
这是安全的关键一步,也是最容易被偷懒的一步。
很多团队的做法是:AI 后端拿一个固定的服务账号 token,所有用户的查询都用这个身份去调内部系统。这等于把系统现有权限体系架空了——销售小李能看到的客户,和销售老王能看到的客户,在 AI 眼里没有区别。一旦数据泄露,日志里全是同一个服务账号,根本查不到是谁问的。
正确的做法是把用户的权限 token 透传到 MCP endpoint:
这样做的本质是:AI 不新增权限,只是把用户已经有的权限"代理"给 Agent 用。销售小李通过 AI 能查到的客户,和他自己登录系统能查到的客户,范围完全一致。审计日志里也是小李的 token,出了问题能定位到人。这一步没有技术难度,难的是观念——不要为了"让 AI 查得更全"而开超级账号,那个口子一开,后面收不住。
工具拆好之后,怎么让模型用起来?我们没有走"写死 workflow"的老路(那种一个节点调一个接口的固定流程,只能答预演过的问题),而是走 Agentic 路线:用户输入进来,主 Agent 动态决定调哪个工具、调几次,再组织回答。
但纯动态调度有个问题:模型会"过度自信"——拿到数据后,它可能自己脑补一段没查到的内容,或者把输出格式搞得乱七八糟。所以我们在主 Agent 之外设了一个 check Agent,职责只有两个:
整个闭环是:用户输入 → 主 Agent 动态调度工具与子 Agent → 拿到结果组织回答 → check Agent 校验答案和格式 → 通过则返回给前端,不通过则打回重生成。循环的终止条件有两个:一是 check Agent 判定拿到了理想答案,二是主 Agent 判断继续问也没用、主动结束。这层兜底把"能聊"和"能用"拉开了差距——实测里,没有 check Agent 的版本,回答看着流畅但偶尔夹带编造的金额;加上之后,这类问题基本消失。推断:check Agent 会增加一轮 LLM 调用,延迟和成本都上升约 30%,换来的是业务可信度。
工具覆盖了常见查询,但业务里总有一些"长尾问题"——"华东区这个月退货率最高的三个产品是什么",这种没有现成接口。我们的解法是 Text2SQL:让模型直接生成 SQL,查只读库。
Text2SQL 最容易翻车的地方是模型不知道表结构。它会猜表名(比如把 t_order_item 猜成 order_detail)、猜字段名(把"含税金额"猜成 tax_amount 而实际是 amount_with_tax),生成的 SQL 一跑就报错。我们的做法是把"取 schema"做成流水线的第一步:
五个环节串起来,本质是把"让模型一次写对 SQL"这件难事,拆成"取结构、写语法、查安全、跑结果"四件相对简单的事。实测观察:没有 schema 先行时,一次成功率大概一半;把 schema 喂进去之后,长尾查询的可用率明显提升。关键不是模型多聪明,是先把"它可能猜错的东西"摆到台面上。待验证:复杂多表 JOIN、窗口函数这类查询,当前流水线的成功率。
后端能答了,前端怎么接?我们没有做一个独立的聊天窗口塞到系统里,而是让后端返回组件指令,前端动态渲染——衔接已有功能,而不是另起炉灶。
具体说:主 Agent 返回的不只是一段文字,而是一个结构化的"组件描述"(这是一张客户卡片、那是一张订单表格、再附一段说明)。前端拿到后,调用已有的组件库渲染——客户卡片组件本来就在系统里用了很多年,只是这次是由 AI 触发的。好处是:用户看到的界面风格、交互逻辑和原系统一致,没有"这是个外挂聊天框"的割裂感;而且 AI 渲染出来的卡片,用户可以直接点进去看详情,等于把问答和原有功能打通了。
另一个细节是对话 ID 存储。用户在 A 页面问了几个问题,点进一个订单详情页,再返回对话——上下文不能丢。我们的做法是把对话 ID 和会话历史存在后端,前端页面跳转时带上同一个对话 ID,返回后直接恢复。这一步看似小,但决定了用户体验是"每次都从头问"还是"接着上次聊"。实测里,销售反馈"像用自己的系统,不是在用一个新工具",这个评价主要来自这两点:组件是熟的,上下文是连的。
以上路径跑通后,我们在一个约 100 人以内的销售用户群里试用。按实测案例口径,几个观察:
这个反馈闭环是整个工程里最让我们意外的部分:不是 AI 多强,而是工具拆得细 + 权限透传 + 前端组件化这三件事合起来,让"接一个新问题"变成了"改一个工具",而不是"改一整个系统"。
Q:MCP 和直接调 RESTful 接口有什么区别?是不是多包一层?
A:多包一层,但这层是"标准化的工具层"。直接调接口,模型要面对一堆技术 endpoint 和 JSON;包成 MCP 工具后,模型面对的是有名字、有输入输出 schema、有权限上下文的"业务动作"。区别不在技术,在模型能不能用对。
Q:为什么不让一个 Agent 把所有工具都管了?
A:工具一多,模型调度准确率会下降,而且容易"顺手"调不该调的接口。按业务域拆成独立工具、让主 Agent 动态选,比一个万能 Agent 更可控。拆得越细,权限边界越清楚。
Q:权限 token 透传,那 AI 后端能拿到用户的明文 token 吗?安全吗?
A:透传的目的是复用用户已有权限,而不是新造一个万能账号。AI 后端本身不存这个 token,调用时从请求上下文里取、用完即弃。这比给 AI 开一个超级账号安全得多——因为它能访问的范围,和用户自己登录完全一致。
Q:check Agent 会不会让回答变慢?
A:会多一轮调用,延迟和成本上升约三成。但这是"能用"和"能聊"的差距——没有 check,回答偶尔夹带编造的金额,业务不敢用;有了,可信度上一个台阶。对企业场景,这个交换是值的。
Q:Text2SQL 会不会被用来删库?
A:流水线里有专门的 SQL 检查 Agent,只允许只读查询,禁止 UPDATE/DELETE/DROP,并且限制返回行数。即使模型生成了危险 SQL,也过不了检查这一关。这是设计上的硬约束,不是靠 prompt 提醒。
Q:100 人试用就说"有帮助",样本是不是太小?
A:是,这是早期试用的反馈,不是大规模验证。我们标注为"实测案例口径"——它说明方向可行,不代表可规模化。更大范围的稳定性、并发、长尾问题覆盖率,还在继续观察。
三点说明:① 本文所有工程路径来自约 100 人以内销售团队的早期试用(2026 年前后),数字按"实测案例口径"标注,未做大规模并发和压力测试;② 为遵守合规要求,文中不写具体公司名、不写内部系统名,涉及客户/订单/价格的描述均为通用业务域抽象;③ 文中"推断/待验证"标签已逐项标注,如"工具数超 20 个后的调度准确率""复杂多表 JOIN 的 Text2SQL 成功率"等,均为本文未实测项,不构成工程承诺。