我把管理系统接给AI,它改条数据都要先问我
上篇文章写了 ForgeAdmin 的企业集成与能力开放平台------把系统能力包装成受控接口开放给外部系统。有朋友留言问:现在 AI Agent 这么火,能不能让 AI 直接操作后台?
我试了。结论先说:能,而且每动一条数据,它都得先过我这关。
一、起因:一句"帮我处理下审批"引发的血案幻想
前几天用 Claude 处理一堆杂事,顺手让它帮我看几个系统里的待办。它列得头头是道,我突然冒出个念头:能不能让它直接把那些待办办了?
然后我后背一凉。
想象一下这个场景:你给 AI 开了个接口,权限是管理员。你说"把过期的测试数据清一下",它理解的"过期"和你理解的"过期"是一个东西吗?它要是把 WHERE create_time < xxx 写成 WHERE id < xxx 呢?更别提大模型抽风式的幻觉------它可能会特别自信地、批量地、删除你的生产数据。
所以让 AI 操作企业后台,难点从来不是"连不上"------Spring AI 官方 starter 五分钟就能把 MCP 端点跑起来。难点是"不敢让它动"。
裸接的 MCP Server 有三个大坑:
- 没有认证:默认配置下,任何能访问端点的人都能列出工具、发起调用
- 身份丢失:工具异步执行时,AI 用谁的身份删的数据?查无此人
- 工具失控:每个业务接口都注册成工具,大模型面前摆着 800 个工具,重名冲突、越权调用、重复执行,没人管
ForgeAdmin 新出的 MCP 插件,就是冲着这三个坑去的。
二、实测:AI 想干活,得先"看菜单"
先把后台跑起来,加一个依赖、开一个开关:
然后我在 AI 客户端(支持 MCP 的那种)里配置了服务地址和 Bearer Token。连上之后,AI 看到的不是几百个业务工具,而是固定的 4 个"元工具" :
capability.search------ 搜索当前调用方能用的能力
capability.describe------ 查看某个能力的输入输出规范
capability.invoke------ 执行某个能力
capability.approval.get------ 查询高危操作的审批进度
这个设计我第一次看到的时候愣了一下,然后拍大腿:妙啊。
一般人的思路是"一个接口注册一个 MCP 工具",系统里 500 张表 3000 个接口,工具列表直接爆炸。大模型的注意力是有限的,工具一多,它选错的概率直线上升------这跟给人一本 800 页的菜单点菜一个道理。
ForgeAdmin 的思路是反过来:给 AI 一本只有 4 页的目录,让它自己翻。
实测对话长这样:
我:帮我查下系统里有什么跟订单有关的能力
AI:(调
capability.search,query="订单")找到 3 个能力:订单查询(只读,低风险)、订单发货(中风险)、订单作废(高风险,需人工确认)......
注意 AI 拿到的每个能力都自带 riskLevel(风险等级)和 confirmationRequired(是否需要人工确认)标签。AI 在动手之前,就知道这个动作有多危险。
三、重头戏:AI 想改数据,弹窗先弹到我脸上
我让它执行一个中风险的"订单发货"。它的调用流程是这样的:
第一步,必须自带幂等键。 调用参数里 idempotencyKey 是必填项(16-128位)。为什么?大模型最爱干的事就是"我重试一下"------网络卡了重试、结果不满意重试、用户多问了一句它重试。幂等键保证同一个键的重复调用只会执行一次。返回结果里还有 idempotentHit: true/false 告诉你这次是不是命中了幂等。
第二步,字段白名单校验。 AI 传的参数里只要有一个不在授权字段列表里的 key,直接拒绝。它想偷偷加个 status: "deleted"?想都别想。
第三步,弹窗确认。 这是整个设计里我最想吹的部分。执行之前,服务端不自己决定,而是通过 MCP 协议原生的 Elicitation 机制,反向弹了一个确认框到用户界面上:
确认执行「订单发货」;对象=trade_order,记录=1024,请求指纹=a3f8...
我点了确认,它才继续执行。我点拒绝,AI 收到 CONFIRMATION_DECLINED,还得跟我解释为什么没执行。
如果客户端不支持弹窗?直接返回 409 CONFIRMATION_REQUIRED,宁可执行不了,也不静默放行。
这个"请求指纹"也有讲究------它把整个调用参数做了摘要,弹窗里展示的是指纹而不是全部参数。我确认的是"这一次确切的调用",AI 中途偷换参数?指纹对不上。
四、更狠的:高危操作,AI 说了不算,人也说了不算
订单作废这种高风险能力,就算我在弹窗里点了确认,也不会立刻执行------它会转成一个审批单 ,走系统里的人工审批流。AI 拿到的是 PENDING_APPROVAL 状态,然后可以用 capability.approval.get 轮询审批进度,审批通过后才真正执行。
也就是说整个权限体系是四层漏斗:
| 层级 | 拦什么 | 怎么拦 |
|---|---|---|
| 传输层 | 没身份的调用 | Bearer Token 认证过滤器,只挂在 /mcp 端点 |
| 授权层 | 没被授权的能力 | 能力必须先授权给这个调用方才能被搜到 |
| 确认层 | 没经过用户确认的动作 | MCP Elicitation 弹窗 + 请求指纹 |
| 审批层 | 高危操作 | 转人工审批流,审批过了才执行 |
还有一个细节让我印象很深:AI 客户端自己的身份是不够的。所有写操作都要求"用户委托"------调用上下文里必须有具体的登录用户,AI 是代表某个用户在操作,而不是以系统身份为所欲为。出错时返回的错误码是 USER_DELEGATION_REQUIRED,翻译过来就是:"你想借谁的手?先说清楚。"
每次调用,审计日志里记的是:谁、用什么身份、调了什么能力、请求指纹、耗时、成功还是失败。事后追责,一条不缺。
五、跟裸接 MCP 比,到底值不值
我算笔账。假设你要自己给一个 Spring Boot 后台接 MCP,并且做到同等安全水位:
| 工作项 | 自己写 | ForgeAdmin |
|---|---|---|
| MCP 端点 + Streamable 传输 | 用官方 starter,半天 | 一个依赖+一个开关 |
| 认证过滤器 + 上下文传递 | 2-3 天(含异步上下文丢失的坑) | 内置 |
| 工具治理(防爆炸、防重名) | 一直没好办法 | 固定元工具模式 |
| 幂等控制 | 自己写 | 必填幂等键 |
| 人工确认 | 自己接 UI,2 天+ | MCP Elicitation 原生 |
| 高危审批 | 自己对接审批流 | 内置,自动转审批单 |
| 审计日志 | 自己埋点 | 全链路自动记录 |
自己干,保守估计两周起步,而且大概率漏掉几个坑(比如异步上下文丢失、大模型重试风暴)。用框架,这些是默认行为。
更关键的是架构上的干净:MCP 插件只做协议和传输,授权、幂等、审计全部收口在能力注册中心。REST 网关走的也是同一个能力注册中心------意味着一个能力注册一次,网页端、开放 API、AI Agent 三个渠道共享同一套授权和审计规则。不用为 AI 单独维护一套权限。
六、客观说不足
吹了这么多,问题也得摆出来:
- 生态还早 。MCP 客户端里支持 Elicitation 弹窗的还不多,Claude Desktop 这类客户端遇到
CONFIRMATION_REQUIRED只能干瞪眼。体验完全体需要一个支持完整 MCP 能力的客户端。
- 元工具有学习成本。让 AI 先 search 再 describe 再 invoke,比直接调用多两步,token 消耗略高,对弱一点的模型,多步推理出错率也会上来。
- 能力需要预先治理。哪些接口能开放给 AI、风险等级怎么定,得人工标。这是好事(安全),但前期确实要花时间。
写在最后
做 AI 应用这一年我最大的感受:能力不值钱,约束才值钱。让 AI 调接口 demo 一晚上就能跑通,但"让它能干活、又不能闯祸"这件事,没有捷径。
ForgeAdmin 的这套设计核心就一句话:AI 拿到的不是万能钥匙,是一份带风险标签的菜单,和一道必须由人把守的门。
项目开源,感兴趣的可以自己跑一遍试试(演示环境:www.dlforgelab.com:8084/forge/login... 接入这块的文档在项目仓库里。
你们觉得"AI 改数据前弹窗确认"这个设计是贴心还是啰嗦?愿意把后台接给 AI 的扣 1,暂时不敢的扣 2,说说理由。