Files
xiaoqu_mcp_service/xiaoqu-agent-service/doc/xiaoqu-operations-ai-mcp-integration-design.md
T

9.2 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 必填。operation 已存在于 xiaoqu-mcp dev 种子;development、test、staging、production 均须分别核对真实 scope 和工具绑定。凭证只由部署 Secret 注入。

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_count mcp.xiaoqu.agent_count.v1 agent.count read
xiaoqu.agent_list mcp.xiaoqu.agent_list.v1 agent.list.query read
xiaoqu.property_list mcp.xiaoqu.property_list.v1 property.list.query read

每项必须在 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、三项工具绑定和用户映射数据源。
  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 或共享用户数据库。
  • 不在首期引入写工具;写工具需另行审批幂等、确认和补偿协议。