
如果你所在的企业已经开始尝试让大模型通过MCP协议去调ERP/MES你大概率会撞上同一件事技术Demo跑得飞快真到了生产验证阶段业务部门第一个问题不是“能不能连”而是“它在我系统里到底算谁改坏了算谁的”。这篇博文不打算讲MCP怎么注册、怎么配置工具也不聊大模型选型只讲工程边界——也就是MCP接入ERP/MES时用户映射、二次鉴权、人机确认这三条线怎么定、怎么落地、怎么排障。内容基于我在离散制造企业集成项目里的真实实施经历涉及Oracle EBS和自研MES两类系统适合正在做MCP网关、负责ERP/MES接口集成、或者在企业AI中台里踩坑的工程师参考。读完你至少能回答三个问题AI调用ERP时的操作身份怎么定哪些动作必须二次鉴权人机确认到底该做在哪一层1. MCP连接ERP/MES的核心矛盾与工程边界定位1.1 为什么会有人想把MCP接到ERP/MES上很多人第一次听说MCP是在AI编程工具或者知识库场景里。但真正让制造业IT团队兴奋的是另一件事把MCP做成ERP/MES的统一接口面让自然语言变成业务操作。比如产线班组长问一句“今天A线还有多少未完工工单”过去要打开MES查半天现在模型通过MCP工具直接查出来再比如“帮我把这张销售订单转成生产订单”如果MCP工具链齐全理论上也能自动完成。我见过不止一个项目PoC阶段用MCP连接器把ERP的物料、BOM、库存查询全部接好演示效果非常震撼。可一旦进入准生产环境业务部门、IT审计、甚至是ERP运维团队都会提出同一个问题模型是以谁的身份在查数据如果AI误操作把工单状态改了责任算谁的这个问题的本质是ERP/MES是强管控系统而MCP默认的模型调用是去中心化的、上下文驱动的两者信任模型完全不一样。1.2 ERP/MES的稳定性要求与MCP的开放模型冲突在哪ERP和MES这类系统的设计前提是“操作可追溯、权限可管控、流程可回滚”。它们有严格的用户体系、功能权限、数据权限、审批流每一笔过账、发料、报工都要落到具体人头。而MCP协议的设计初衷是让大模型可以调用任意工具工具之间还可以互相组合。模型是“自由身”它本身没有企业身份也不理解“这个操作会触发物料账移动”。这两者放在一起冲突就非常明显ERP认为必须有明确的操作人MCP请求默认没有身份。ERP认为关键动作必须走审批MCP模型的调用链条很短一个自然语言指令可能直接触发写操作。ERP的审计要求“谁在什么时间改了什么”而MCP会话里只有模型会话ID和工具调用记录。所以MCP连接ERP/MES技术上不难难的是在两者之间加一层“翻译”把MCP的开放请求翻译成ERP/MES能接受的身份、权限和流程。这一层翻译的规则就是工程边界。1.3 工程边界到底画在哪三条线的判定标准我在这个项目里把边界拆成三条线每条线解决一个问题身份边界用户映射MCP请求进入ERP/MES时以哪个系统用户身份执行。核心问题是“AI是谁”。操作边界二次鉴权哪些工具调用属于高风险操作必须在普通校验之外再做一次权限确认。核心问题是“AI有没有资格做这件事”。确认边界人机确认哪些操作必须由真实人类在环确认模型不能自主完成。核心问题是“这件事AI能不能自己拍板”。判定标准我建议用两维矩阵操作影响范围、回滚难度。查询类、只读类操作走普通用户映射即可不需要二次鉴权。影响单个单据、但可逆的操作需要二次鉴权。影响批次数据、库存账、成本账或者跨系统联动的操作必须人机确认。举一个我在项目里定的规则凡是会改动ERP库存、成本、财务账目的MCP工具默认全部走人机确认凡是会改动MES工单状态、报工数量、排产结果的工具默认全部二次鉴权加人机确认。这条规则一开始被业务吐槽“太严格”但上线三个月后业务部门反过来要求把所有写操作全部加上人机确认。原因后面会讲。2. 用户映射AI在人家的系统里到底“以谁之名”行事2.1 三种用户映射模式服务账号独占、用户透传、角色代理MCP网关接到一个请求首先要回答的问题就是这个请求该映射到ERP/MES的哪个用户我总结下来有三种模式各有适用场景。第一种服务账号独占模式。所有MCP调用统一使用一个专用服务账号比如MCP_INTEGRATION。这种模式最简单但风险最大——因为所有AI操作都算到同一个账号头上没法区分具体是谁发起的审计等于白做。我见过有项目图省事这么干结果AI误操作之后业务部门追责时发现连“当时是哪个用户让AI干的”都查不出来非常被动。第二种用户透传模式。MCP网关从上层应用比如企业微信、钉钉、自研Portal拿到当前登录用户直接把用户身份透传给ERP/MES。这种模式最符合审计要求但要求MCP调用必须由人类用户发起AI不能独立访问。适合“人类主导、AI辅助”的场景比如用户问AI“帮我查一下我负责的订单”然后AI以这个用户的身份去查。第三种角色代理模式。当AI是主动发起方比如定时任务、自动异常检测没有具体用户上下文时网关把请求映射到一个预配置的代理角色比如MCP_AI_AGENT该角色在ERP/MES里只拥有最小必要权限。这种模式适合后台自动化场景但权限要给得很克制。实际项目中我推荐混合使用有用户上下文时用透传没有用户上下文时用角色代理坚决不用单一服务账号通吃。2.2 映射的具体落地OAuth2与JWT Claims在MCP网关里的应用用户映射不是写个if-else这么简单关键是要在MCP协议层和ERP连接器层都做对。我的做法是在MCP网关中维护一个用户映射上下文结构大致如下# MCP网关中的用户映射伪代码 def map_request_to_erp_user(mcp_session, target_system): # 1. 从MCP会话中取出身份上下文 id_context mcp_session.context.get(identity) or {} # 2. 如果是用户透传场景直接映射原用户 if id_context.get(type) user: erp_user id_context[erp_user_code] erp_role fetch_user_role(erp_user, target_system) mapping_mode user-passthrough else: # 3. AI独立发起时走角色代理模式 proxy_config get_proxy_config(target_system) erp_user proxy_config[proxy_user] erp_role proxy_config[proxy_role] # 例如 MCP_READONLY mapping_mode role-proxy # 4. 生成审计记录 audit_payload { mcp_session_id: mcp_session.session_id, mapping_mode: mapping_mode, mapped_user: erp_user, mapped_role: erp_role, original_caller: id_context.get(caller, AI), } return erp_user, erp_role, audit_payload在ERP连接器层面建议用OAuth2的JWT令牌来承载映射信息。ERP系统如果支持JWT就把sub字段填成映射后的ERP用户把aud字段填成目标系统再附带一个employee_id、department之类的扩展Claim。有个细节容易漏JWT令牌的失效时间不要设太长。我一开始设了24小时结果AI会话挂在那儿第二天ERP侧令牌还在但用户的岗位权限已经变了导致越权操作。后来统一改成1小时MCP网关每次调用前重新确认用户权限。2.3 用户映射最容易踩的坑四个真实工作里踩过的雷映射看似简单实际落地时坑不少我挑四个典型的说。坑一ERP的用户名和MCP上层应用的用户名对不上。比如企业微信里叫“张三”Oracle EBS里叫“ZHANGSAN”自研MES里叫“10032”。不做映射表的话透传就是空谈。我的做法是建一张统一身份映射表用员工工号做主键维护企业微信ID、AD账号、ERP用户、MES用户多列。坑二把AI代理角色的权限给大了。有人图省事给MCP_AI_AGENT角色配了和普通计划员一样的权限。表面上看AI能查能改实际上AI一旦抽风批量刷新工单状态、批量改库存后果不堪设想。我给这个角色配的权限是所有查询功能全开所有写操作全部拒绝。AI要写操作必须降级为“生成待办任务”而不是“直接执行任务”。坑三用户映射之后没有做二次权限检查。网关映射了用户不代表用户真的有权限操作某个工厂、某类物料。我遇到过MCP工具传进来的工厂参数和映射用户的工厂数据权限不匹配网关没拦结果ERP返回权限错误AI再把错误信息解释成“系统故障”非常误导。后来我在网关里加了规则MCP工具参数里的组织/工厂维度必须先和映射用户的权限维度做交集校验不匹配就返回明确错误。坑四审计日志里丢了原始调用者。很多MCP Client只暴露会话ID不暴露具体用户。如果网关只记录“MCP会话ID”后面查“是哪位同事让AI发起这笔操作”就抓瞎。我的做法是在MCP工具的第一个参数位置强制要求调用方携带caller_user_id虽然有些模型会漏传但至少审计有依据。3. 二次鉴权给MCP的“关键动作”加一道人肉闸门3.1 哪些MCP工具必须二次鉴权不是所有MCP工具都要二次鉴权。只读查询、数据统计、报表生成这些工具即使参数错了顶多查询结果不对不会破坏业务数据。真正需要二次鉴权的是会产生业务副作用的工具。我按系统分类列一张参考表系统必须二次鉴权的操作原因ERP库存过账、物料发料、成本核算、销售订单冲销、采购收货直接变更财务和库存账目影响成本核算ERP价格主数据修改、BOM版本替换影响后续所有订单和成本核算MES工单状态推进、完工报工、返工单创建、设备参数下发影响产线执行数据牵动排产和绩效MES批次号修改、SN绑定关系变更涉及产品追溯一旦错误难以追溯判定逻辑很简单如果这个操作的结果不能被一键删除或红冲就必须二次鉴权。比如库存过账之后生成了会计凭证你不能直接删只能冲销成本核算跑完之后月度账都锁了更没法改。这类操作模型连发起都不应该被允许至少要在网关层面拦一道。3.2 二次鉴权的四种实现形态二次鉴权具体怎么实现我见过四种形态按安全强度从低到高排列。第一种参数唤醒式。在MCP工具的InputSchema里增加一个confirm_token字段调用方必须携带网关签发的确认令牌。这个令牌可以来自用户在门户上的一个“确认执行”按钮也可以来自审批流回传的审批单号。成本最低但依赖业务系统配合提供令牌。第二种独立审批API式。MCP网关在工具执行前调用独立的权限服务接口比如“检查操作人是否有当前工厂的报工权限”。有权限就放行没权限就拒绝。这种方式的优点是权限规则集中管理不散落在MCP工具定义里。第三种短时令牌式。网关收到高风险MCP调用时下发一个一次性短时令牌同时推送给对应的审批人比如企业微信审批卡片审批人同意后令牌生效模型需要在5分钟内携带该令牌再调用一次工具。这是我最推荐的方式后面细讲。第四种双因子式。在MCP工具执行前要求调用者输入动态验证码或二次扫码。安全等级最高但对业务连续性和模型体验影响很大只适合极少数超高权限操作比如财务月结、成本重算。3.3 一个实操示例MCP工具定义里怎么加鉴权参数我拿一个真实的MCP工具定义片段举例。这是我们给MES做的“完工报工”工具{ name: production_order_report_complete, description: 对生产订单执行完工报工。此操作会触发物料消耗、工时结算、库存回冲必须由拥有报工资格的人工用户确认后才可执行。调用方必须提供二次鉴权令牌。, inputSchema: { type: object, properties: { order_id: { type: string, description: 生产订单号例如MO202506001 }, quantity: { type: number, description: 实际完工数量必须大于0 }, operation_seq: { type: integer, description: 工序序号来自工艺路线 }, confirm_token: { type: string, description: 由MCP网关签发的二次鉴权令牌有效期5分钟单次有效必须从人机确认页面获取 } }, required: [order_id, quantity, operation_seq, confirm_token] } }注意我把confirm_token放进了required这样模型无论如何都必须提供。如果不提供工具直接返回错误模型会认为“缺少参数”而不是“系统拒绝了”。在MCP网关层面收到这个请求后做三步校验校验令牌是否存在、是否在有效期内。校验令牌是否一次性防止重放攻击。校验令牌绑定的用户和操作类型是否和本次MCP调用一致。这三步缺一不可。我一开始只做了前两步结果有好事者把A用户拿到的令牌改用到B用户的请求上虽然没造成实质问题但审计时非常难看。3.4 二次鉴权在超时、并发和回滚面前的表现二次鉴权看起来简单一进生产环境就暴露问题。超时问题是最常见的。人工审批经常要等几分钟甚至几小时而短时令牌有效期我不能设太长。设长了容易被人滥用设短了审批慢一步就失效。我最终的做法是拆成两个步骤第一步AI调用预检接口生成待确认单据第二步审批人在确认页面点“同意”后网关立即下发一个“执行令牌”这个令牌有效期只有5分钟但从点击同意到模型执行之间的时间窗口几乎不会超时。并发问题同样棘手。如果模型并行发起五个高风险操作网关不能只发一个令牌让五个操作共用。每个操作必须独立令牌、独立确认这在实现时要特别注意令牌和操作ID的绑定关系。回滚问题容易被忽略。二次鉴权放行不代表操作一定成功。MCP工具调用成功后ERP/MES侧可能因为后续流程失败比如库存不足、物料锁单而需要回滚。我的建议是MCP工具在返回结果时把ERP侧的“事务ID”或“批号”带回来方便后续人工介入时定位和冲销。4. 人机确认让AI止步于“建议”而不是“执行”4.1 三种操作粒度的设计只读、建议待确认、直接执行加审计人机确认的粒度我把它分成三档。只读级模型只能调用查询工具输出分析结果不存在业务副作用。比如“对比上月和本月OEE趋势”“查询某订单的物料齐套率”。这一档不需要人机确认。建议级模型可以生成操作建议但不能直接执行。比如“建议将MO202506001工单状态从未开始改为已下达”“建议对A物料做批次冻结”。模型输出建议后必须由用户在界面上点“采纳”网关才把建议翻译成真实的ERP/MES调用。这一档是人机确认的核心应用场景。执行级模型在获得临时授权后可以直接执行但执行过程全程录屏、全链路审计、事后可回滚。这一档适合那些“用户已经明确表达意图AI只是代操作”的场景比如用户说“帮我把这张单子过账”人工确认一次后放行。我强烈建议在项目初期把绝大多数写操作都放在“建议级”。等跑了两三个月、积累足够多的调用日志和故障案例后再挑出那些“人工确认只是走形式”的操作降级到执行级。4.2 两阶段工具设计模式预检与执行分离人机确认在MCP工具层面最可靠的做法是“两阶段工具设计模式”。第一阶段是预检工具比如material_issue_precheck模型先调用它获取操作摘要、影响范围、风险提示和待确认码。这个工具是只读的不产生任何副作用。第二阶段是执行工具比如material_issue_confirm模型必须携带第一阶段拿到的确认码同时这个确认码已在人机确认页面被用户点击通过执行工具才允许调用。我拿物料发料举例{ name: material_issue_precheck, description: 物料发料预检。模型必须先调用本工具生成发料预检单获取确认码。预检单会显示物料、数量、库存批次、成本中心等信息供用户在确认页面核验。, inputSchema: { type: object, properties: { order_id: {type: string}, material_code: {type: string}, quantity: {type: number} }, required: [order_id, material_code, quantity] } }{ name: material_issue_execute, description: 物料发料执行。携带预检确认码和人工审批结果执行发料。未获得人工确认前调用将被拒绝。, inputSchema: { type: object, properties: { precheck_code: {type: string}, approval_id: {type: string} }, required: [precheck_code, approval_id] } }这里有一个关键设计material_issue_execute的输入参数里面没有物料、数量这些业务参数只有precheck_code和approval_id。这样做的目的是防止模型在第二阶段“自由发挥”改了业务参数。执行时网关拿precheck_code查出第一阶段锁定的参数完全复用不允许再传一遍。这套模式上线后效果立竿见影。之前模型偶尔会“编造”一个不存在的订单号去查数据现在预检阶段就把订单号校验住了执行阶段根本碰不到原始参数。4.3 用MCP的Sampling实现动态人工确认聊到人机确认很多人会提MCP协议里的Sampling特性。根据MCP规范模型在无法自行生成某个值时可以向客户端发起Sampling请求由客户端负责收集用户输入。这里有个很妙的用途当模型认为接下来需要一个关键参数比如确认工单报工数量时客户端弹出一个窗口让用户填写确认信息再把这个信息喂回给模型。我实测下来这个特性在自研MCP Client里很好用。客户端可以在Sampling回调里展示一个自定义确认页面页面显示当前工具上下文、预期影响、确认按钮。用户点了确认系统再把“用户已确认”作为Sampling结果返回给模型模型继续执行工具调用。但要注意的是市面上很多现成的MCP Client对这个特性的支持并不统一有些客户端直接把Sampling请求透传给用户聊天框人工确认的界面不可控。所以我的建议是方案上保留Sampling交互实际落地时用自研Client或网关内置确认页兜底。4.4 弱网、黑屏、误点人机确认在车间现场的退化策略人机确认在办公室Demo里很顺到了车间一线就变味了。车间环境有几个现实问题现场网络不稳定MES终端可能老旧卡顿操作人员可能戴着手套不方便点确认按钮。如果人机确认设计得太重一线人员就会想办法绕过它比如让IT把确认页面直接设成自动通过这是最危险的。我的经验是做“分级退化策略”默认情况下高风险操作必须有确认页点击记录。如果网络异常允许审批人在管理端远程确认但需要额外的短信验证码。如果确认页连续超时MCP工具直接返回“操作已取消”绝不自动放行。所有退化操作都给运维侧发告警第二天业务例会复盘。事实证明越是设计得严格的系统越要在“严格”和“可用”之间留出合规的缓冲通道否则一线总会有办法破坏流程。5. 从测试到生产实施过程中的坑与排查实录5.1 会话粘连与连接池MCP无状态请求撞上ERP有状态会话ERP系统普遍是会话制用户登录后拿到一个Session后续操作必须复用这个Session。而MCP模型调用天然是无状态的每一次工具调用都像第一次见面。我在集成Oracle EBS时遇到一个经典问题映射用户后MCP连接器替用户连ERP结果多个模型会话复用了同一个ERP连接导致不同用户的操作串在同一个ERP会话里。表象是A用户查到的数据带上了B用户的操作痕迹严重时出现权限串号。解决方式是不要直接让MCP连接器去连ERP而是在网关层建立会话池按映射用户维度维护连接。每个用户一个连接空闲时间超过阈值就释放。连接复用要有锁同一时刻一个ERP会话只能被一个MCP请求占用。这块实现不复杂但坑非常多尤其是并发高的场景一定要给连接池加监控。5.2 上下文窗口被ERP返回的大报文挤爆MCP工具调用后ERP/MES返回的数据会作为一个工具结果塞回模型上下文。问题来了一张复杂的生产订单Oracle EBS返回的XML报文可能有几百个字段MES的工单详细页更是恨不得把每个工序都列出来。模型上下文窗口有限大报文一进来轻则上下文被挤占重则模型直接截断、丢失信息、产生幻觉。我的处理原则是三句话查询类工具优先返回摘要只给模型常用的20个字段原始报文存网关日志。列表类工具强制分页每页不超过50条记录并告诉模型“如需下一页请调用page参数”。详情类工具提供两个版本一个是模型友好的精简版一个是业务系统原始的完整版只有在模型明确需要时才返回完整版。经常有模型因为工具返回的字段名不直观理解错我会在工具描述里显式告诉模型“返回的wip_entity字段即生产订单号qty_completed为已完工数量。”这点看似啰嗦但能明显减少模型误读。5.3 审计日志设计从MCP层到ERP账套内部连成一体审计是MCP连接ERP/MES项目里最容易被拖延、上线后最被重视的模块。很多项目一开始只记录MCP调用日志、工具名、参数、返回结果真出了事故业务方问“这一笔操作对应的ERP凭证号是多少”IT直接傻眼。我的设计思路是形成一条完整的调用链MCP层记录会话ID、模型名称、工具名、输入参数、输出摘要、调用时间。网关层记录映射前用户、映射后ERP用户、映射模式、鉴权结果、令牌ID。连接器层记录ERP/MES内部实际调用的API方法、事务ID、返回的业务单据号。业务层在ERP/MES侧写入扩展字段比如把MCP会话ID写到单据的备注字段或自定义属性里。前两层用网关的统一日志中间件处理后两层要嵌入连接器代码。三层日志用同一个trace_id串联起来排障时一条命令就能拉通全链路。5.4 常见问题速查表我把实施期间遇到过的高频问题整理成一张表方便团队自查现象典型原因处理方案ERP会话频繁掉线映射用户之后连接被其他请求抢占网关层按用户维度建立会话池加锁串行模型调用写操作被网关拦截后重试缺少确认令牌模型反复尝试工具Schema把confirm_token设为必填并给出明确错误码返回报文超出上下文ERP原始报文过大MCP工具加字段裁剪、分页、摘要模式二次鉴权令牌超时人工确认耗时超过令牌有效期拆成预检确认两个阶段确认后单独下发执行令牌用户映射后权限还是不对ERP用户的职责与MCP调用场景不匹配使用独立职责通过数据权限范围过滤工厂/组织维度审计日志查不到原始调用人上层应用未传递用户信息在MCP工具入参中强制要求caller_user_id模型把订单号编错自由文本参数导致幻觉用枚举、订单搜索接口替代自由文本允许模型先查询再传值5.5 关于权限最小化的额外心得最后再分享一个我在项目里体会很深的事。很多人在做MCP集成时会把重心放在“怎么把功能接得多、接得全”上我建议反过来先定义“哪些操作绝不接”。我定的原则是财务月结、成本重算、价格主数据批量更新、工艺路线整体替换、批次追溯信息修改这五类操作在MCP工具库中直接不存在。不是“不开放”而是“根本不做这个工具”。模型再聪明也调用不了不存在的工具。这个思路帮我们挡掉了很多潜在风险。如果你问我对这个项目后续扩展的看法我会把精力放在两件事上一是积累模型调用日志用真实数据训练一个“MCP操作风险评分”模型根据调用链判断哪些自然语言指令容易引发错误操作二是把二次鉴权的能力前置到MCP Server端做成一个通用组件让任何企业接入MCP时都能直接复用。工程边界这事最怕的不是边界画得严而是边界画了之后没人维护、没人迭代。