Files
xiaoqu_mcp_service/xiaoqu-agent-service/doc/xiaoqu-operations-ai-mcp-integration-design.md
T
my_local_kimi_dev2 4e5ee541e3 docs(mcp): update ops/ai integration docs with prod scope facts
- 新增 4.1 生产环境对接现状(MCP 入口、ensure 换签、握手流程)
- operation scope(id=2) 当前绑定 24 个工具;移除未绑定的 agent.count
- xiaoqu-ai scope(id=3) 当前绑定 12 个工具;代理域工具改为实际可用映射
- 开发顺序改为按 4.1 清单对照核验
2026-09-16 18:30:07 +08:00

12 KiB
Raw Blame History

xiaoqu-operations-ai 接入 xiaoqu-mcp 详细设计

1. 目标与边界

本文是 xiaoqu 多产品 Agent 统一接入 xiaoqu-mcp 总体设计 的运营项目落地设计,代码基线为 /Users/tonylai/wangheng/xiaoqu-operations-ai。

运营 iOS、Android、Web 共用 ops-assistant-service 中的一套 MCP Client:

iOS / Android / Web
        │ 产品登录 Token
        ▼
ops-assistant-service REST
        │
        ▼
Router → Resolver → Planner → Executor → Answer
                              │
                              ▼
                    Capability Registry
                              │ 固定 adapter_id
                              ▼
                    xiaoqu-mcp Adapter
                              │ 用户 MCP Token(仅服务端持有)
                              ▼
                    xiaoqu-agent-service /mcp

WebSocket 只负责会话进度和完成通知,不承载 MCP 调用。客户端不新增 MCP 代码,不保存用户 MCP Token、MCP Session ID 或 X-Open-Key。

2. 当前代码依据

  • web/ops-assistant/src/api.ts 通过 /api/v1/ops-assistant/* REST 提交消息和读取业务数据。
  • web/ops-assistant/src/ConversationPage.tsx 使用 WebSocket 订阅会话进度,消息提交仍走 REST。
  • services/ops-assistant-service 是 FastAPI + Python 3.12 服务,现有 httpx 足够实现 MCP HTTP Client。
  • worker.py 同时运行旧流水线和 contextual_fulfillment_v2;新流水线包含 Router、Resolver、Planner、Recovery、Executor、Answer。
  • capability_registry.py 维护静态 CAPABILITY_REGISTRY、冻结的 Capability Contract 和 adapter_id 白名单。
  • 旧 executor.py 与新 contextual_execution.py 最终都调用 execute_registered_tool()。
  • 当前 Registry 包含 customer_issues.*、vision_analyze、work_items.list、read_only_todos.list、knowledge_entries.search,已不包含 smartclean.query。
  • Gateway JWT 在入口解析为共享身份,再通过 ops_identity_mappings 映射为运营 tenant_id、user_id 和 DataScope;后台 Worker 执行时使用运营 UUID。

因此不在 Web、路由层或某一条流水线中增加专用 MCP 分支。唯一接入点是两套流水线共用的 Capability Adapter 执行边界。

3. 设计决策

3.1 统一 Adapter

在 CAPABILITY_REGISTRY 中注册稳定的本地 Capability 和固定 adapter_id,由 execute_registered_tool() 将 MCP Adapter ID 路由到 XiaoquMcpAdapter。

Planner 选择本地 Capability
  → 校验冻结的 Capability Contract
  → 校验输入 schema、scope_tags、DataScope
  → execute_registered_tool(adapter_id)
  → XiaoquMcpAdapter
  → MCP tools/call

不得把远端 tools/list 原样注册给 Planner。tools/list 只用于启动或联调时验证远端工具是否与本地冻结契约一致。

3.2 显式依赖传递

XiaoquMcpRuntime 由 worker.build_pipeline_runtime() 创建,并通过显式参数传给旧 run_executor_tick 和新 run_contextual_executor_tick。禁止用模块级全局变量或从请求上下文隐式读取用户。

PipelineRuntime.close() 负责关闭 MCP HTTP Client 和清理进程内 Session 缓存。未启用 MCP 时传入 None,现有本地 Capability 保持原行为。

4. 配置设计

在 src/ops_assistant_service/config.py 的 Settings 增加以下 OPS_ASSISTANT_ 配置:

变量 默认值 说明
XQ_MCP_ENABLED false 是否启用 MCP Capability
XQ_MCP_URL unset xiaoqu-mcp 内网地址
XQ_MCP_OPEN_KEY unset Token 初始化凭证,使用 SecretStr
XQ_MCP_SCOPE_CODE operation 服务端固定 scope,禁止由客户端或模型选择
XQ_MCP_TIMEOUT_SECONDS 10 MCP 请求超时

启用时 URL、Open Key 和 scope 必填。凭证只由部署 Secret 注入。

4.1 生产环境对接现状(2026-09-16 在 prod svc 库核验)

项 生产实际值
MCP 入口 https://agent.ququclean.com/mcp(Streamable HTTP,POST)
Token 换取 POST https://agent.ququclean.com/api/open/token/ensure,header X-Open-Key
本系统 scope operation(scope id=2,名称「运营app」),服务端固定,禁止客户端或模型选择
服务密钥要求 运营专用服务密钥只绑定了 operation;密钥未绑 scope 时 ensure 返回 403

重要勘误:dev 种子数据与生产不一致——生产承载全量工具的作用域是 code='test'(id=1),operation(id=2)是独立的运营作用域,两域绑定各自维护。上线核对时必须以 prod svc 库 agent_scope / scope_tool 为准。

operation scope 当前绑定的工具(24 个):

  • 代理/物业/站点/设备:agent.list.query(2)、agent.detail.query(3)、district.list.query(4)、district.detail.get(5)、property.list.query(6)、property.detail.query(7)、hardware.list.query(14)、hardware.detail.query(15)
  • 商城订单:mall.order.list.query(9)、mall.order.detail.query(10)、mall.order.logistics.query(11)
  • 合同:contract.list.query(12)、contract.detail.query(13)
  • 仓库:warehouse.out.list.query(20)、warehouse.out.detail.query(21)、warehouse.in.list.query(22)、warehouse.in.detail.query(23)、warehouse.stock.list.query(26)、warehouse.todo.list.query(24)
  • 工单:delivery.order.list.query(27)、delivery.order.detail.query(28)、install.order.list.query(29)、install.order.detail.query(30)
  • 自检:integration.context.get(19)

未绑定到 operation 的工具:agent.count(1)、sys.ping(8)、*.changes.list(16-18,数据同步专用)、contracts.current.batch_get(25,sync 专用)。首期 Capability 选择须以上表为准。

Token 换取与 MCP 握手流程:

  1. 服务端持 X-Open-Key 调 ensure:{"mobile":"<企业账号手机号>","scopeCode":"operation"} → 返回 xqak_...(长期有效,幂等,created=false 表示复用已有)
  2. POST /mcp 发 initialize,从响应头取 mcp-session-id
  3. 发 notifications/initialized,之后 tools/list / tools/call 必须带 Mcp-Session-Id 头
  4. Authorization: Bearer xqak_...(Bearer 前缀只拼一次;库中存的令牌值本身不含前缀)

5. 最小模块

5.1 mcp_token_provider.py

输入为 Worker 已持有的运营 tenant_id、user_id 和固定 scope:

  1. 从 ops_identity_mappings 反查可信的 shared_tenant_id、shared_user_id。
  2. 通过现有只读共享用户 Port 获取权威 mobile;权威数据源存在 email 时可作为备用。
  3. 使用固定 scopeCode 调用 /api/open/token/ensure。
  4. 按运营租户、运营用户、共享用户和 scope 缓存 Token。

现有 SharedUserPort 尚未暴露 mobile/email,需要最小扩展其只读 DTO 和 PostgreSQL Adapter;不得复制用户表,也不得使用 Web、Planner、工具参数或模型输出中的身份字段。

5.2 mcp_client.py

使用现有 httpx.Client 管理:

  • initialize、notifications/initialized、tools/list、tools/call。
  • Bearer Header、Mcp-Session-Id、JSON-RPC ID 和响应校验。
  • 连接、读取、写入和总超时。
  • 按运营租户、运营用户和 scope 隔离 Session。
  • 关闭时释放 HTTP Client,不持久化 MCP Session。

5.3 mcp_adapter.py

XiaoquMcpAdapter 只接收已经验证的 Capability Contract、运营身份和参数:

  • 根据固定映射选择远端 MCP 工具。
  • 调用 Token Provider 和 MCP Client。
  • 校验远端响应并执行字段白名单投影。
  • 返回现有 Executor/Answer 可消费的字典,不返回 Token、Header 或原始未授权字段。

不引入通用 MCP 框架或第二套 Agent 编排器。

6. Capability 映射

首期只注册只读 Capability:

本地 Capability adapter_id MCP 工具 权限
xiaoqu.agent_list mcp.xiaoqu.agent_list.v1 agent.list.query read
xiaoqu.property_list mcp.xiaoqu.property_list.v1 property.list.query read

勘误(2026-09-16):原首期清单中的 agent.count 未绑定到生产 operation scope(该工具只绑在 test 全量域,见 4.1 节),已从首期 Capability 移除;如需使用须先在管理后台为 operation 补绑该工具。

后续批次可按 4.1 节已绑定的清单扩展 Capability(仓库、工单、合同、商城物流等),每项必须在 CAPABILITY_REGISTRY 中声明输入/输出 schema、风险、审批、超时重试、审计事件和结果模板,并将精确 adapter_id 加入 EXECUTION_ADAPTER_IDS。已有本地 Capability 不改名、不改 Adapter、不改变执行语义。

7. 身份与权限

最终授权取交集:

本地 Capability allowlist
  ∩ 当前运营用户 scope_tags / DataScope
  ∩ MCP Token scope
  ∩ xiaoqu-mcp 用户、租户和行级数据范围
  • REST 和 WebSocket 只负责验证产品登录态并建立运营身份。
  • Planner 只能选择 Registry 中的 Capability,不决定用户、租户或 scope。
  • Worker 必须在每次执行前确认 ops_identity_mappings 仍有效,不能仅依赖消息入库时的旧快照。
  • tools/list 与 tools/call 使用同一用户 Token 和 MCP Session;服务端在两个入口都强制鉴权。

8. 异步执行与生命周期

Web、iOS、Android 提交消息后获得 202;Worker 在后台完成 Agent 和工具执行,再由消息查询或 WebSocket 返回进度与结果。

  • build_pipeline_runtime() 创建一个进程级 XiaoquMcpRuntime,但 Token 和 Session 按用户隔离。
  • Worker 重启后 Session 不恢复;首次调用重新 ensure 和 initialize。
  • 用户映射失效、scope 版本变化或 MCP 401 时,只清理该用户缓存。
  • MCP 401:重新 ensure 和连接一次;只读调用最多重试一次。
  • MCP 403:直接返回权限不足,不刷新 Token。
  • 超时、协议错误或服务不可用:映射为稳定的 TOOL_UNAVAILABLE,并让当前 Execution Attempt 进入可审计失败状态。
  • 不自动重放写操作;首期不接写工具。

9. 开发顺序

  1. 核对各环境 operation scope 和工具绑定(prod 已于 2026-09-16 核验,见 4.1 节;新环境上线时按 4.1 清单对照)和用户映射数据源。
  2. 扩展只读 SharedUser Port,完成运营 UUID 到 mobile/email 的可信解析测试。
  3. 增加 Settings 配置、启用校验和 XiaoquMcpRuntime 生命周期。
  4. 实现 Token Provider、MCP Client 和 Adapter 的协议单元测试。
  5. 注册三项本地 Capability,并让旧 Executor 与 contextual v2 共用同一 Adapter。
  6. 覆盖用户隔离、租户隔离、scope 拒绝、401、403、超时、脱敏和 Worker 重启测试。
  7. 分别从 iOS、Android、Web 提交对话请求,验证异步进度和最终结果一致。

10. 项目验收

  • iOS、Android、Web 均只调用 ops-assistant-service,客户端没有 MCP Token、Session ID 或 Open Key。
  • Web 消息走 REST,WebSocket 仅订阅进度/完成通知。
  • 旧流水线和 contextual_fulfillment_v2 对同一 MCP Capability 使用同一个 Adapter。
  • 用户 A/B、不同租户和 scope 的 Token 与 MCP Session 不互用。
  • Planner 不能选择未注册工具;冻结 Contract、scope_tags、DataScope 或 MCP scope 任一不满足即拒绝。
  • 现有七项本地 Capability 的契约和行为不受影响。
  • MCP 401 只刷新当前用户;MCP 不可用时不回退公共 Token、数据库直连或 xiaoqu-ai Agent。
  • 测试、日志、trace、配置和 Git 历史中无凭证明文。

11. 当前不做

  • 不在运营 iOS、Android、Web 中实现 MCP Client。
  • 不动态注册全部远程工具。
  • 不恢复或假定已删除的 smartclean.query。
  • 不复制 xiaoqu-mcp 或共享用户数据库。
  • 不在首期引入写工具;写工具需另行审批幂等、确认和补偿协议。