From f95de7eceb4c8fbc50326e0163ca06d05f481216 Mon Sep 17 00:00:00 2001 From: wangheng Date: Mon, 14 Sep 2026 12:21:26 +0800 Subject: [PATCH] =?UTF-8?q?docs(mcp):=20CRM=20=E6=8E=A5=E5=85=A5=E6=89=8B?= =?UTF-8?q?=E5=86=8C=20(REQ-20260911-0013)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../doc/crm-integration-guide.md | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 xiaoqu-agent-service/doc/crm-integration-guide.md diff --git a/xiaoqu-agent-service/doc/crm-integration-guide.md b/xiaoqu-agent-service/doc/crm-integration-guide.md new file mode 100644 index 0000000..8457175 --- /dev/null +++ b/xiaoqu-agent-service/doc/crm-integration-guide.md @@ -0,0 +1,116 @@ +# 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 | 小趣管理员 | 为 CRM 开通服务密钥(X-Open-Key,一系统一密钥) | +| 2 | 小趣管理员 | 给 CRM 的服务主体绑定 `sync` 作用域(含 `integration.context.get` + 三个 changes 工具) | +| 3 | CRM 后端 | 调 `POST /api/open/token/ensure`(principal=服务主体)拿**长期服务 Token**(`xqak-...`),安全保管 | + +完成后 CRM 持有两样东西:**服务 Token**(后台扫描用)、**服务密钥**(给销售换个人 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): + +```json +{ "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 白名单),这是设计如此。 + +## 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 + context.get | +| 数据范围 | 实时 ACL 行过滤 | 管理员授权的 sync scope | +| 限流 | 常规档 | SYNC 独立档,互不占配额 | +| tenant_id 入参 | 不允许 | 不允许,从 Token 推导 | + +## 6. 通用输出规范 + +所有工具返回统一信封 `structuredContent`: + +```json +{ "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`。输出信封与错误码也不变。 -- 2.54.0