8.7 KiB
SaaS MCP → 小趣 AI 经营系统对接进度
MCP 系统独立进度入口。最后核对:2026-09-15;代码基线:
76d461a。本文只记录
xiaoqu_mcp_service的责任和状态。小趣 AI / CRM 的规则、事项、AI、页面与推送进度,以其仓库PROJECT.md为准。
1. 两个系统的边界
| 系统 | 必须负责 | 明确不负责 |
|---|---|---|
| SaaS MCP | 服务身份、源租户/数据域、工具授权、源系统行级权限、用户/物业/合同标准变化流、稳定游标、审计与标准错误 | 到期规则、经营优先级、AI决策、经营事项状态机、销售页面、APNs推送 |
| 小趣 AI / CRM | 租户连接、数据镜像、身份与客户映射、确定性规则、仅把命中数据交给AI、事项生成/流转、展示、操作、反馈、推送前复核 | 猜测源租户、绕过MCP权限、兼容不符合冻结Schema的错误字段 |
双方唯一连接面是版本化接口契约:integration.context.get、三条 *.changes.list、统一错误信封,以及真实端到端验收。任何一侧内部实现都不能成为另一侧的隐式依赖。
2. 当前结论
当前状态:协议可连接,业务契约未通过,不能用于真实销售合同到期推送。
已经具备:
- MCP Streamable HTTP 会话、SSE响应和Schema v2信封。
X-Open-Key管理、服务Token签发、Token作用域、工具白名单、审计和限流。integration.context.get。users.changes.list、properties.changes.list、contracts.changes.list及统一分页框架。- 基于
(modify_time, id)的分页、软删标记、错误码和基础单元测试。
尚未通过的不是“小趣AI页面问题”,而是MCP公开数据契约与可靠同步语义。小趣AI侧不得通过放宽校验来掩盖这些问题。
3. 已确认问题与处理顺序
P0-1 服务身份没有绑定真实源租户
现状:integration.context.get.tenant_id由作用域编码拼接得到,sync被当成租户;服务Token又按serviceName + scope全局复用,创建它的Open Client身份没有进入Token。作用域代表“能用什么工具”,不是“属于哪个租户/数据域”。
影响:不能证明某个小趣租户连接的是哪个SaaS数据域,也不能可靠阻止不同接入方复用同一服务身份。
标准改造:
- 为Open Client建立不可变的
source_tenant_id(或等价数据域ID)绑定,不从请求体、scope或名称推断。 - 服务Token持久化
open_client_id + source_tenant_id + subject_name,ensure按该组合幂等签发。 integration.context.get.tenant_id返回真实source_tenant_id;subject_id返回稳定服务主体ID。- 每条SYNC查询都从鉴权上下文取得该数据域并强制过滤;若当前源库确实只有单一数据域,也必须以明确配置和测试证明,不能用“user为空即查全库”表达。
验收:两个Open Client即使使用相同serviceName=crm也得到不同服务Token和租户上下文;跨租户数据为零;吊销其中一个不影响另一个。
P0-2 三条变化流不符合冻结字段Schema
现状与冻结契约的差异:
| 流 | 当前输出 | 必须输出 |
|---|---|---|
| users | mobile;数值型user_id/organization_ids |
verified_mobile;字符串型稳定ID;状态使用公开枚举 |
| properties | 数值型property_id |
字符串型稳定ID;状态使用公开枚举 |
| contracts | 数值型contract_id/property_id/owner_user_id、数值状态0..4、数值expire_remind,缺remind_days |
字符串型稳定ID、PENDING/REJECTED/ACTIVE/EXPIRED/TERMINATED/VOID、布尔提醒标记、实际提醒天数 |
影响:小趣Gateway的严格Schema校验会正确拒绝当前users和contracts数据;合同不会进入镜像、规则和推送链路。
标准改造:在MCP边界使用独立DTO/枚举映射,将老库字段一次性转换成公开Schema;公开契约不得直接泄漏数据库整数状态和Java实体类型。没有权威来源的可选字段保持空,不伪造。
验收:用真实样例对三条流执行消费者契约测试;Gateway无需兼容代码即可全部通过,未知字段、未知状态和错误类型必须失败。
P0-3 当前“快照”不能保证重放稳定
现状:令牌只保存cutoff,每页仍直接查询持续变化的业务表。分页期间,cutoff之前的记录被修改、删除或权限变化时,相同sync_token + cursor + limit可能得到不同结果;秒级modify_time也可能漏掉同一行在边界秒内的再次修改。
影响:合同规模扩大或同步期间发生业务写入时,存在漏数、重复、记录消失和重放不一致风险,达不到文档声称的“不重不漏”。
标准改造:建立通用变更日志/Outbox(每次变更拥有单调递增change_seq,保存实体ID、操作类型、版本和必要投影),同步窗口按change_seq冻结;游标按change_seq推进。若使用CDC,也必须落成可保留、可重放的变化流,不能直接分页扫活表冒充快照。
验收:同步中并发更新、删除、负责人变更、权限变更以及相同请求重放时,旧快照结果不变,新变化只进入下一轮;压测覆盖成千上万合同。
P0-4 交接Token错误复用了24小时快照TTL
现状:轮内快照Token、页游标和已完成轮的next_sync_token统一执行24小时TTL。
影响:每日任务只要稍晚、停机或积压,就可能被迫全量重建;数据量增大后会形成周期性全量压力。
标准改造:只给轮内快照/游标设置短TTL;交接Token按变更日志保留期校验,或保存持久化消费位点。过期时返回可观测的最早可用位置及标准错误,消费者执行受控重建。
验收:间隔超过24小时仍可正常增量;只有位点早于服务端保留期才触发重建。
P0-5 数据权限版本不能覆盖真实权限变化
现状:data_scope_version仅取token_scope关系的修改时间;Open Client租户绑定、scope-tool变化、源数据域ACL变化不会稳定反映。
影响:权限变化后旧同步位点可能继续使用,消费者无法判断需要重建或停止派发。
标准改造:维护数据域授权版本,任何租户绑定、工具授权、行级ACL语义变更都原子递增;上下文与同步Token使用同一个版本。
验收:修改任一影响可见数据的授权后,旧轮立即失败关闭,新轮在新数据域版本下重建。
4. 依赖顺序
- 冻结真实
source_tenant_id来源、数据域范围和合同状态/提醒字段字典。 - 完成服务身份与源租户持久化模型,补迁移、后台配置、ensure和上下文测试。
- 建立通用变更日志/Outbox与保留策略,再迁移三条变化流;不继续强化活表分页方案。
- 使用独立公开DTO完成三条流字段映射和消费者契约测试。
- 修正交接Token生命周期与统一数据权限版本。
- 在测试环境用真实用户、物业、合同及变更/删除数据完成MCP侧验收。
- 交付Open Client、真实源租户ID和凭证给小趣AI侧,联合验证“同步→映射→规则→事项→展示→推送前复核”。
5. 状态看板
| 工作项 | 状态 | 责任系统 | 下一步 |
|---|---|---|---|
| MCP协议与工具发现 | 已完成 | MCP | 保持兼容并纳入回归 |
| 服务密钥与Token基础生命周期 | 已完成 | MCP | 在租户模型完成后升级幂等键 |
| 真实源租户与服务主体隔离 | 未完成,P0阻塞 | MCP | 明确权威租户来源并设计迁移 |
| 三流公开字段Schema | 未完成,P0阻塞 | MCP | 建立DTO和状态字典,跑消费者契约测试 |
| 可靠变化日志与稳定快照 | 未完成,P0阻塞 | MCP | 设计Outbox/CDC及保留策略 |
| 权限版本与交接位点生命周期 | 未完成,P0阻塞 | MCP | 与租户/变化日志模型一起实现 |
| 小趣AI连接与消费代码 | 已完成,待部署联调 | 小趣AI | 见小趣AI仓库PROJECT.md |
| 真实销售合同到期推送 | 未开放 | 双方联合验收 | 所有P0通过后才允许从Shadow转Live |
6. 发布门禁
以下条件全部满足前,不得把MCP同步标记为生产可用,也不得向真实销售发送合同提醒:
- 真实源租户隔离、服务主体隔离和跨租户反向用例通过。
- 三条变化流通过冻结Schema及真实数据样例校验。
- 并发写入、删除、断点续传、超过24小时续传和权限变化测试通过。
- 凭证不入库明文、不入日志;轮换和吊销测试通过。
- 小趣AI侧完成负责人、客户双映射和发送前实时复核。
- 完整链路具有
request_id/snapshot_id/source_tenant_id审计证据,可定位每条事项和推送的数据来源。