# NS3：MCP Server 扩展 — mcp-server-ai-extension

> 优先级：中（可与 NS1/NS2 并行，批次 A 无前置依赖）
> 预估工作量：中等
> 前置条件：批次 A 无依赖；批次 B 依赖 P5-A（biz 表已建）；批次 C 依赖批次 B
> 参考基准：`docs/prd/specs/P5.1-mcp-server-ai-extension.md`

---

## 一、背景与目标

当前 MCP Server（`apps/mcp-server/server.py`）仅连接 `etl_feiqiu` 数据仓库，提供 4 个工具（list_tables、describe_table、describe_schemas、query_sql），schema 白名单为 ods/dwd/dws/core/meta/app。SQL 安全通过正则禁词检测实现只读保护。

查库手册（`docs/mcp/AI-DATABASE-QUERY-MANUAL.md`）内容陈旧，DWS 层 34 张表缺少完整字段说明，业务库（zqyy_app）完全未覆盖。

本 SPEC 目标：
1. MCP Server 新增 `zqyy_app` 业务库连接，支持多数据库路由
2. 实现业务库敏感字段脱敏策略
3. 重写查库手册（ETL 全字段 + 业务库全字段 + 常用查询模式）
4. 手册上传百炼平台验证 AI 引用效果

### 当前 MCP Server 能力

| 工具 | 功能 | 限制 |
|------|------|------|
| `list_tables` | 列出指定 schema 下的表 | 仅 etl_feiqiu |
| `describe_table` | 查看表结构（列名、类型、注释） | 仅 etl_feiqiu |
| `describe_schemas` | 列出可用 schema 及表数量 | 仅 ods/dwd/dws/core/meta/app |
| `query_sql` | 执行只读 SQL 查询 | 正则禁词检测，单 schema 限制 |

---

## 二、技术架构

### 2.1 多数据库连接

```
apps/mcp-server/
├── server.py              🔧 扩展：多连接池 + schema 路由
├── db_pool.py             🆕 新建：连接池管理（etl_feiqiu + zqyy_app）
├── security.py            🆕 新建：敏感字段脱敏策略
└── config.py              🆕 新建：数据库配置（DSN、schema 白名单）
```

### 2.2 连接池设计

```python
# db_pool.py
class DatabasePool:
    """管理两个数据库的连接池。"""

    pools = {
        "etl": {
            "dsn_env": "PG_DSN",           # etl_feiqiu / test_etl_feiqiu
            "schemas": ["ods", "dwd", "dws", "core", "meta", "app"],
            "readonly": True,
        },
        "biz": {
            "dsn_env": "APP_DB_DSN",       # zqyy_app / test_zqyy_app
            "schemas": ["auth", "biz", "public"],
            "readonly": True,              # MCP 只读，写操作走后端 API
        },
    }
```

### 2.3 Schema 自动路由

工具参数中不再需要显式指定 `database`，而是根据 schema 名称自动路由：

| Schema | 路由目标 | 说明 |
|--------|---------|------|
| `ods` / `dwd` / `dws` / `core` / `meta` / `app` | etl_feiqiu | ETL 数据仓库 |
| `auth` / `biz` / `public` | zqyy_app | 业务库 |

路由逻辑：
```python
def resolve_database(schema: str) -> str:
    ETL_SCHEMAS = {"ods", "dwd", "dws", "core", "meta", "app"}
    BIZ_SCHEMAS = {"auth", "biz", "public"}
    if schema in ETL_SCHEMAS:
        return "etl"
    elif schema in BIZ_SCHEMAS:
        return "biz"
    else:
        raise ValueError(f"未知 schema: {schema}")
```

### 2.4 工具扩展

4 个现有工具的参数不变，内部根据 schema 参数自动选择连接池：

| 工具 | 变更 |
|------|------|
| `list_tables(schema)` | schema 参数扩展接受 auth/biz/public |
| `describe_table(table, schema)` | 同上 |
| `describe_schemas()` | 返回结果增加 auth/biz/public 三个 schema |
| `query_sql(schema, sql)` | 根据 schema 路由到对应连接池 |

### 2.5 跨库查询限制

- 单次 `query_sql` 调用只能查询单个数据库（由 schema 参数决定）
- 禁止在 SQL 中引用其他数据库的 schema（现有 `_reject_cross_schema` 逻辑扩展）
- 如需跨库关联，AI 应分两次查询后在应用层组合

---

## 三、敏感字段脱敏策略

### 3.1 脱敏规则

| Schema | 表 | 敏感字段 | 脱敏方式 |
|--------|-----|---------|---------|
| `auth` | `users` | `wx_openid` | 前 4 后 4 保留，中间 `***` |
| `auth` | `users` | `phone` | 前 3 后 4 保留，中间 `****` |
| `auth` | `users` | `wx_session_key` | 完全隐藏，返回 `[REDACTED]` |
| `biz` | `ai_messages` | `content`（role=user） | 不脱敏（AI 需要理解对话内容） |
| `biz` | `ai_conversations` | — | 无敏感字段 |
| `public` | `member_retention_clue` | `recorded_by_assistant_id` | 不脱敏（非 PII） |

### 3.2 实现方式

在 `query_sql` 返回结果时，对命中脱敏规则的列进行后处理：

```python
# security.py
MASKING_RULES = {
    "auth.users": {
        "wx_openid": lambda v: f"{v[:4]}***{v[-4:]}" if v and len(v) > 8 else "[REDACTED]",
        "phone": lambda v: f"{v[:3]}****{v[-4:]}" if v and len(v) >= 11 else "[REDACTED]",
        "wx_session_key": lambda v: "[REDACTED]",
    },
}

def mask_row(schema: str, table: str, columns: list[str], row: tuple) -> tuple:
    """对查询结果行应用脱敏规则。"""
```

### 3.3 脱敏绕过防护

- `SELECT *` 查询 auth.users 时自动应用脱敏
- 禁止通过 `CAST`、`CONCAT`、子查询等方式绕过脱敏（在 SQL 解析阶段检测）
- 对 auth.users 的查询结果始终应用列级脱敏，无论 SQL 写法

---

## 四、查库手册重写

### 4.1 手册结构

重写后的手册分为两个文件，便于维护和上传：

```
docs/mcp/
├── AI-DATABASE-QUERY-MANUAL.md          🔧 重写（总览 + ETL 库）
└── AI-DATABASE-QUERY-MANUAL-BIZ.md      🆕 新建（业务库）
```

### 4.2 ETL 库手册内容（重写）

保留现有架构流程和工具说明，重点补充：

1. **DWS 层完整表清单**（34 张表按业务域分组）
   - 每张表列出全部字段（字段名、类型、中文说明）
   - 标注关键字段的业务含义和使用注意事项
   - 按业务域分组：会员域、助教域、财务域、配置域

2. **金额口径专章**
   - `consume_money` 三种历史口径说明（A/B/C），明确标注"禁止直接使用"
   - `items_sum` 定义和计算公式
   - settle_type 枚举映射表（1=台桌结账 78.6%、3=商城订单 21.4%、5=充值、7=充值退款、6=结算退款）
   - 助教费用拆分规则（assistant_pd_money 陪打 / assistant_cx_money 超休）
   - 支付渠道恒等式（balance_amount = recharge_card_amount + gift_card_amount）

3. **会员字段断档说明**
   - DQ-6：member_phone/member_name 自 2025-12 起 NULL，需 JOIN dim_member
   - DQ-7：member_card_type_name 自 2025-07-21 起 NULL，需 JOIN dim_member_card_account

4. **常用查询模式**（ETL 侧）
   - 客户消费汇总查询
   - 助教绩效查询
   - 财务日报查询
   - 指数排名查询

5. **数据量统计与性能建议**
   - 各表的大致数据量级
   - 推荐的 WHERE 条件（时间范围、site_id）
   - 避免全表扫描的建议

### 4.3 业务库手册内容（新建）

1. **Schema 概览**
   - `auth`：用户认证（users、user_applications、site_code_mapping、user_assistant_binding）
   - `biz`：业务数据（coach_tasks、notes、ai_conversations、ai_messages、ai_cache、trigger_jobs、salary_adjustments、excel_upload_log）
   - `public`：共享数据（member_retention_clue）

2. **每张表完整字段说明**
   - 字段名、类型、是否可空、默认值、中文说明
   - 关键枚举值说明（如 coach_tasks.task_type、notes.type、ai_cache.cache_type）
   - 外键关系和关联查询建议

3. **常用查询模式**（业务侧）
   - 维客线索查询（按客户、按来源、按标签）
   - 任务系统查询（按助教、按状态、按类型）
   - 备注查询（按客户、按助教、含星星评分）
   - AI 缓存查询（按应用类型、按 target_id）
   - Excel 上传记录查询

4. **跨库关联指南**
   - 业务库 member_id → ETL 库 dim_member 的关联方式
   - 业务库 assistant_id → ETL 库 dim_assistant 的关联方式
   - 注意：MCP 不支持单次跨库 JOIN，需分两次查询

### 4.4 数据字段权威参考

手册中涉及的 DWD/DWS 层字段来源、金额口径、业务逻辑，以 `docs/reports/DWD-DOC/` 校准文档为准（数据快照 2026-03-06）。

---

## 五、百炼平台上传与验证

### 5.1 上传方式

- 将重写后的手册作为知识库文档上传至百炼平台
- 关联到应用 1（通用对话），使 AI 在回答数据查询问题时可引用手册

### 5.2 验证场景

| 测试场景 | 预期行为 |
|---------|---------|
| "查询本月营业额" | AI 引用手册中的 dws_finance_daily_summary 表，使用 items_sum 口径 |
| "查看客户王先生的消费记录" | AI 引用 dim_member + dwd_settlement_head，通过 member_id 关联 |
| "助教张三的本月绩效" | AI 引用 dws_assistant_salary_calc，正确使用 assistant_pd_money 拆分 |
| "查看维客线索" | AI 引用业务库 member_retention_clue 表 |
| "查看用户申请列表" | AI 引用 auth.user_applications，对 phone 字段脱敏 |

### 5.3 验证标准

- AI 不再频繁调用 `describe_table`（手册已提供完整字段信息）
- AI 生成的 SQL 使用正确的金额口径（items_sum 而非 consume_money）
- AI 查询 auth.users 时返回结果中敏感字段已脱敏
- AI 能正确区分 ETL 库和业务库的查询路由

---

## 六、参考文档

| 文档 | 路径 | 用途 |
|------|------|------|
| P5.1 原始 spec | `docs/prd/specs/P5.1-mcp-server-ai-extension.md` | 需求定义基准 |
| 现有 MCP Server | `apps/mcp-server/server.py` | 当前实现参考 |
| 现有查库手册 | `docs/mcp/AI-DATABASE-QUERY-MANUAL.md` | 重写基础 |
| DWD-DOC 标杆 | `docs/reports/DWD-DOC/` | 字段语义、金额口径权威参考 |
| BD 手册-业务表 | `docs/database/BD_Manual_biz_tables.md` | biz schema 表结构 |
| BD 手册-认证表 | `docs/database/BD_Manual_auth_tables.md` | auth schema 表结构 |
| ETL BD 手册 | `apps/etl/connectors/feiqiu/docs/database/` | DWD/DWS 表结构 |

---

## 七、预审查清单（SPEC 启动前确认）

### 7.1 多数据库连接

1. **连接池大小**：zqyy_app 连接池的 min/max 连接数？与 etl_feiqiu 共享还是独立？MCP Server 的并发查询量预估？
2. **DSN 环境变量**：MCP Server 运行环境中 `APP_DB_DSN` 是否已配置？测试环境使用 `test_zqyy_app` 还是 `zqyy_app`？
3. **RLS 隔离**：MCP 查询 zqyy_app 时是否需要 `SET LOCAL app.current_site_id`？如果需要，site_id 从哪里获取（MCP 调用方传入？固定值？）？
4. **连接超时**：FDW 查询和业务库查询的超时时间是否需要不同设置？

### 7.2 安全与脱敏

5. **脱敏范围确认**：除 auth.users 外，还有哪些表/字段需要脱敏？biz.notes 的备注内容是否需要脱敏？
6. **脱敏粒度**：是否需要根据 MCP 调用方身份区分脱敏级别？（如管理员可看完整数据，AI 应用只看脱敏数据）
7. **SQL 注入防护**：现有正则禁词检测是否足够？是否需要升级为 SQL 解析器（如 sqlparse）？
8. **审计日志**：MCP 查询是否需要记录审计日志（谁查了什么表、什么时间）？

### 7.3 查库手册

9. **手册格式**：百炼平台对知识库文档的格式要求？Markdown 是否直接支持？是否需要转换为 PDF/TXT？
10. **手册拆分**：ETL 库和业务库是否拆分为两个知识库文档？还是合并为一个？
11. **手册更新机制**：表结构变更后，手册如何同步更新？是否需要自动化脚本从数据库 DDL 生成手册？
12. **DWD 层覆盖**：手册是否需要覆盖 DWD 层全部表的完整字段？还是只覆盖 DWS + 常用 DWD 表？

### 7.4 部署与运维

13. **MCP Server 重启**：新增连接池后，MCP Server 是否需要重启？是否支持热加载配置？
14. **监控指标**：是否需要监控 MCP 查询的响应时间、错误率、查询频次？
15. **降级策略**：zqyy_app 连接失败时，是否影响 etl_feiqiu 的查询？两个连接池是否需要独立故障隔离？

---

## 八、任务清单（草案，SPEC 细化后调整）

### 批次 A：查库手册 — ETL 库（无前置依赖）
- [ ] T1：重写 `AI-DATABASE-QUERY-MANUAL.md` — DWS 层 34 张表全字段说明（按业务域分组）
- [ ] T2：补充金额口径专章（consume_money 禁用说明 + items_sum 定义 + settle_type 映射）
- [ ] T3：补充会员字段断档说明（DQ-6/DQ-7）+ 常用 ETL 查询模式

### 批次 B：MCP Server 扩展 + 业务库手册（依赖 P5-A）
- [ ] T4：创建 `db_pool.py` — 双连接池管理（etl_feiqiu + zqyy_app）
- [ ] T5：扩展 `server.py` — 4 个工具支持 schema 自动路由
- [ ] T6：创建 `security.py` — 敏感字段脱敏策略实现
- [ ] T7：创建 `AI-DATABASE-QUERY-MANUAL-BIZ.md` — 业务库全字段说明 + 常用查询模式

### 批次 C：百炼平台验证
- [ ] T8：手册上传百炼平台并关联 AI 应用
- [ ] T9：执行验证场景测试（5 个场景），确认 AI 引用效果
