Files
xiaoqu_mcp_service/xiaoqu-agent-service/doc/crm-integration-guide.md
T

7.3 KiB
Raw Blame History

CRM 接入小趣 MCP 手册

适用版本:REQ-20260911-0013(增量同步框架)交付后 端点:https://agent.ququclean.com/mcp(生产)/ http://192.168.4.236:8088/mcp(内网) 协议:MCP Streamable HTTP(JSON-RPC),所有响应为 SSE,取 data: 行

当前生产可用性、阻塞项和下一步以对接进度为准;本手册描述目标调用方式,不代表发布门禁已经通过。

0. 边界(先读这段)

小趣 MCP 只做三件事:供数据、供身份、守权限。 到期规则计算、AI 决策、推送、通知负责人、经营事项流转——全部是 CRM / 小趣 AI 系统的职责,MCP 不提供也不预留任何相关字段。

1. 一次性开通

步骤 操作方 说明
1 小趣管理员 登录 https://agent.ququclean.com/,进入「服务密钥」→「创建服务密钥」
2 小趣管理员 调用方名称填 crm,勾选 sync 作用域,保存并立即复制只展示一次的 X-Open-Key
3 CRM 后端 用下面的请求换取长期服务 Token(xqak-...),安全保管
curl -X POST 'https://agent.ququclean.com/api/open/token/ensure' \
  -H 'X-Open-Key: <管理后台创建后显示的服务密钥>' \
  -H 'Content-Type: application/json' \
  -d '{"scopeCode":"sync","principalType":"service","serviceName":"crm"}'

响应的 token 就是后续放进 MCP Authorization: Bearer <token> 的服务 Token。X-Open-Key 不是 MCP Token,不能直接放进 Authorization 头。

完成后 CRM 持有两样东西:服务 Token(后台扫描用)、服务密钥(重新 ensure 获取 Token 或给销售换个人 Token 用)。若还需要给销售换 QUERY 个人 Token,创建/编辑服务密钥时还要勾选对应 QUERY 作用域;只绑定 sync 的密钥不能跨域签发个人 Token。

密钥泄露时,管理员在同一页面点「轮换」(旧密钥立即失效)或「吊销」。数据库只保存密钥哈希,关闭创建/轮换结果弹窗后无法找回明文。

2. 每次调用前的身份自检

tools/call integration.context.get

返回 principal_type / scopes / capability_levels / data_scope_version。

  • 后台扫描任务启动时必须确认 principal_type=tenant_service 且 capability 含 SYNC;拿错 Token(user_delegated)时拒绝执行扫描,防止串权。
  • data_scope_version 变化说明管理员改了授权范围,建议触发一次全量重建。

3. 后台通道:每日定时扫描(增量同步)

三个变化流工具:users.changes.list / properties.changes.list / contracts.changes.list。

入参只有三个(禁止传 tenant_id/scope,传了直接 PERMISSION_DENIED):

{ "syncToken": null, "cursor": null, "limit": 200 }

协议语义

  • 快照:每轮同步签发 snapshot_id + data_cutoff_at,同一快照内翻页结果稳定,页间不会有数据漂移。
  • 游标:页内按 (modify_time, id) 复合游标推进;has_more=true 时用 next_cursor 翻下一页。
  • 续传:只有最后一页(has_more=false)才签发 next_sync_token。中断/宕机后从本地保存的 sync_token + cursor 继续,不重不漏。
  • tombstone:deleted_at 非空的条目是被删除的数据,CRM 本地镜像应标记删除,不进 AI。
  • limit:上限 200,传更大会被截断到 200 并带 notice。

CRM 侧定时任务伪代码

token, cursor = load_local()          # 首次均为 null → 全量
loop:
    resp = call("contracts.changes.list", {syncToken: token, cursor: cursor, limit: 200})
    for item in resp.items:
        if item.deleted_at: 本地镜像标记删除(item.contract_id)
        else:               本地镜像 upsert(item)
    save_local(token, resp.next_cursor)          # 每页都存,断点恢复
    if resp.has_more: cursor = resp.next_cursor; continue
    save_local(resp.next_sync_token, null)       # 本轮结束,钉死新游标
    break

错误分支(必须实现)

错误码 含义 CRM 动作
SYNC_CURSOR_EXPIRED 快照/游标过期或被篡改 清空本地镜像,syncToken=null 全量重建
RATE_LIMITED 触发 SYNC 限流档 指数退避重试(建议 1s/2s/4s…上限 60s)
UNAUTHENTICATED Token 被吊销/人员停用 重新 ensure 取 Token,仍失败则告警人工介入

两个错误用法

  • 不要拿 version 字段做并发控制——它由 modify_time 派生,只用于调试核对。
  • 不要把扫描任务和销售在线查询混用同一个 Token——服务 Token 调 QUERY 工具会被拒(scope 白名单),这是设计如此。

发送前复核(不能省略)

日同步只负责发现候选。CRM 在晨报、午报或日结真正入推送队列前,必须使用同一个服务 Token 批量调用:

tools/call contracts.current.batch_get
arguments: {"contractIds":["1001","1002"]}
  • 每批 1—200 个稳定合同 ID,返回 checked_at/count/items/not_found_ids。
  • items 使用与合同变化流相同的公开字段;软删合同返回删除标记,查无记录进入 not_found_ids。
  • CRM 必须逐项复核状态、到期日、负责人、客户归属、提醒配置和续约结果。任一变化、缺失、删除、响应不完整、证据时间异常或服务不可用,对应合同本次都不得发送。
  • 该工具属于 SYNC 能力和限流档,调用方传 tenant_id/tenantId/scope 会被拒绝;数据域只能来自服务 Token。

4. 前台通道:销售在线查询(实时 ACL)

1. 销售登录 CRM → CRM 后端调 /api/open/token/ensure {mobile: 销售手机号}
   幂等,同一人永远拿到同一个个人 Token;缓存 "CRM用户 ↔ xqak ↔ userId" 映射。
2. 销售查合同时,带他的个人 Token 调:
   - contract.list.query   (列表,12 字段,自动按实时 ACL 行过滤)
   - contract.detail.query (详情,含 version、files、processes)
3. 个人 Token 调 SYNC 工具直接被 scope 白名单拦截——销售永远扫不到全量数据。

个人 Token 缓存在 CRM 侧即可;收到 UNAUTHENTICATED(如人员被停用,60 秒内生效)时清缓存重取。

5. 两条通道速查

前台(销售点查) 后台(定时扫描)
Token 类型 user_delegated tenant_service
可用工具 contract.list/detail.query 等 QUERY *.changes.list + contracts.current.batch_get + context.get
数据范围 实时 ACL 行过滤 管理员授权的 sync scope
限流 常规档 SYNC 独立档,互不占配额
tenant_id 入参 不允许 不允许,从 Token 推导

6. 通用输出规范

所有工具返回统一信封 structuredContent:

{ "schema_version": 2, "request_id": "...", "data": { ... } }
  • 请求头 X-Mcp-Schema-Version: 2 启用新信封;不带则返回老结构(v1,兼容期内有效)。
  • 所有请求把 request_id 记入 CRM 日志,排查时两边对得上。
  • Token 和手机号明文不要落日志(MCP 侧已对手机号打码,CRM 侧请同样处理)。

7. 后续扩展

同步协议是通用框架:以后新增设备/订单/工单同步,CRM 侧代码不变,只是多调一个 xxx.changes.list、多存一对 sync_token/cursor。输出信封与错误码也不变。