# 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 引用效果