上线第3天,销售VP收到了6条一模一样的周报。这不是测试环境的bug,是生产环境里MCP Server与企业微信API之间的消息去重机制被静默绕过了。
过去一个月,我们在企业微信和飞书中跑了7个基于MCP协议的自动周报工作流。最初的教程讲的是“怎么接”,这篇文章讲的是“接上去之后会坏在哪里”。以下故障全部来自2026年5月至7月的真实运行日志,每一个都有具体的触发条件和回滚步骤。
权限令牌:看起来有效,实际已经死了
最隐蔽的一类故障。企业微信和飞书的access_token都有有效期,但MCP Server通常会在内存中缓存令牌,只在返回401时才去刷新。问题在于:部分接口返回的不是标准401,而是200 OK加空body,或者企业微信的40001错误码被MCP Server的HTTP客户端当作文本响应吞掉了。
结果就是:工作流表面正常运行,实际所有消息都没发出去。我们遇到的一次典型事故是飞书tenant_access_token在企业后台被手动吊销后,MCP Server仍用旧token跑了整整3天,期间生成的47份周报全部投递失败,没有任何告警。
排查路径很直接:在MCP Server的日志里加一条token校验心跳,每次调用前先用/auth/check(飞书)或/cgi-bin/get_api_domain_ip(企业微信)做一次轻量探活。如果探活失败,立即触发强制刷新并写入告警日志。
回滚方案:在飞书开放平台后台的“安全设置”里,把token有效期从默认的2小时缩短到1小时,配合MCP Server侧5分钟一次的心跳校验。企业微信则建议启用“IP白名单+回调URL”双因子校验,据企业微信官方开发文档(2026年7月版本)说明,双因子模式下即使token泄露,非白名单IP也无法调用接口。
消息去重:飞书的幂等键不是你想的那样
回到开头那个销售VP收到6条周报的场景。飞书消息推送API支持uuid参数做幂等控制,但它的去重窗口只有24小时,且仅对“完全相同的uuid”生效。我们的工作流最初用userId+日期生成uuid,问题出在一个销售同时属于3个部门群,MCP Server按群维度生成uuid,导致同一个人的同一条周报被当成3条不同的消息发出去了。
企业微信的应用消息接口根本没有原生的幂等机制。它的去重只能靠业务侧自己维护“已发送记录表”。我们用Redis存了msg_id+receiver_id的哈希值,TTL设72小时。但上线第二周就发现Redis内存占用暴涨——一个200人的团队,每周生成的去重记录超过4万条,因为MCP Server每次重试都会生成新的哈希写入。
最终收敛方案:把去重逻辑从MCP Server侧移到消息队列层。用RabbitMQ的Message Deduplication Plugin在broker层做去重,窗口设7天,key取corp_id+user_id+report_date。这个方案上线后,重复推送率从12%降到了0.3%以下。
表格写回冲突:多人同时写同一格
自动周报的最后一环是把汇总数据写回飞书多维表格或企业微信智能表格。问题出在MCP协议的批量写入机制上。
飞书多维表格的批量更新API一次最多处理500行,但它用的是“全量覆盖”语义,不是“增量合并”。如果两个MCP工作流同时对一个表格做批量更新——比如财务周报和销售周报同时写“本周总收入”那个单元格——后到达的请求会把先到达的数据直接覆盖掉,没有任何冲突提示。
我们实际损失过一次:Q2季末的财务汇总表里,“应收账款”字段被销售周报的空值覆盖了,因为销售工作流在那个字段上没有数据,MCP Server按模板填充了null,飞书API把null当作合法值写进了表格。财务团队直到月底对账才发现数字对不上。
临时修复:在MCP Server的写入逻辑里加了字段级锁检查。写表格前先GET一次当前值,如果目标单元格已有数据且MCP Server准备写入的值与现有值差异超过阈值(比如金额差异大于1000元),就挂起写入并往企业微信推送一条人工确认消息。
长期方案还在跟飞书ISV团队沟通。飞书多维表格的“记录级乐观锁”(基于version字段)已经在2026年6月的API更新中进入灰度测试,但正式文档尚未发布。企业微信智能表格目前没有官方并发控制机制,只能靠业务侧自己维护写入队列。
消息模板变量脱落:@人名变成空字符串
企业微信的Markdown消息支持<@userid>语法,飞书支持<at user_id="">。MCP工作流从多维表格里取员工ID填充模板时,经常遇到ID字段为空的情况——有员工离职后ID被禁用、有外包人员用企业微信但不在主通讯录里。
模板引擎不会报错,它只会把空ID渲染成一段空白文本。接收方看到的消息就是“本周完成需求——来自”,后面什么都没有。这种故障没有异常日志,因为MCP Server认为“空字符串是合法输入”。
排查靠抽样:每周一早上手动检查前10条发出的周报,看@人名是否完整显示。自动化方案是在MCP Server侧加一个模板渲染后的正则校验——如果发现<@>或<at user_id="">后面紧跟空字符串,就触发告警并回退到不带@的纯文本版本。
飞书审批与周报联动:回调超时导致流程断裂
我们把周报里的异常指标(比如“客户投诉数>5”)自动触发飞书审批流。MCP Server调用飞书审批API创建实例后,需要等待审批结果回调才能更新周报状态。
飞书的事件回调有3秒超时限制。审批流程一旦超过3秒没返回,回调就会断开,MCP Server侧收不到结果,周报里的异常标记就永远停留在“待审批”。我们有一个客服周报的投诉升级流程,平均审批链路涉及3个人,耗时40分钟起步,回调超时率高达67%。
解决方案是改成长轮询模式:MCP Server不再等待回调,而是每5分钟主动调用飞书审批实例查询API拉取最新状态。这个改动牺牲了一点实时性,但把流程断裂率从67%降到了2%以下。代价是API调用量翻了4倍,好在飞书审批查询接口的QPS限制是100次/秒,暂时没触发限流。
企业微信会话存档:MCP读取历史消息的合规陷阱
有些团队的自动周报需要拉取企业微信群里的讨论记录做摘要。企业微信的会话存档API允许服务商拉取消息,但有三条硬性限制:必须企业购买会话存档服务、必须员工签署存档同意书、存档范围只能覆盖购买日期之后的消息。
我们踩的坑是第三条。一个销售团队在7月1日购买了会话存档,MCP工作流尝试拉取6月的群消息做Q2周报汇总,API直接返回空数据集,没有任何错误提示。MCP Server以为群聊就是空的,生成了一份“本周无讨论内容”的周报。
这个问题的根子在MCP协议的设计假定上。MCP把工具调用抽象成“输入→输出”,但企业微信会话存档的“输出”受合规边界约束,这个约束信息不会出现在MCP的工具描述里。据安全内参在2026年4月发表的《模型上下文协议(MCP):现状剖析、安全威胁与未来研究方向》中分析,MCP的安全威胁之一正是工具描述与实际能力的偏差,攻击者可能利用这种偏差绕过权限控制。在我们的场景里,这不是攻击,是合规边界被协议抽象层吞掉了。
当前修复方式:在MCP Server的工具配置里显式声明“此工具只能读取YYYY-MM-DD之后的消息”,日期从企业微信后台的“会话存档生效日期”字段动态获取。每次工作流启动前做一次生效日期校验,避免拉取边界之外的数据。
上线一个月后的判断
MCP接入企业微信和飞书做自动周报,技术上是跑得通的。但“跑得通”和“跑得稳”之间的差距,不是代码量,是对两个平台API行为细节的理解深度。
权限令牌的失效模式、消息去重的窗口边界、表格写入的并发语义、审批回调的超时限制——这些都不是MCP协议本身能解决的。协议只定义了工具发现和调用格式,不定义工具的实际行为约束。
如果你正在搭类似的工作流,建议先把本文提到的六类故障做成checklist,上线前逐项压测一遍。尤其是表格写回冲突和消息去重,这两类问题在生产环境里几乎必现。
之前我们写过《企业微信接上 AI Agent,先别急着放开审批权》,讨论了合同审批场景下的权限校验和人工兜底。自动周报的教训是类似的:别让自动化流程替你做“静默覆盖”的决策。每次写入、每次推送,都应该留一条人工可回溯的痕迹。
MCP协议还在快速迭代。截至2026年7月,官方规范中对并发写入、幂等保证、合规边界声明等问题尚未给出标准解决方案。这些空白目前只能靠业务侧自己填。