13 KiB
13 KiB
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 目标:
- MCP Server 新增
zqyy_app业务库连接,支持多数据库路由 - 实现业务库敏感字段脱敏策略
- 重写查库手册(ETL 全字段 + 业务库全字段 + 常用查询模式)
- 手册上传百炼平台验证 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 连接池设计
# 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 | 业务库 |
路由逻辑:
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 返回结果时,对命中脱敏规则的列进行后处理:
# 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 库手册内容(重写)
保留现有架构流程和工具说明,重点补充:
-
DWS 层完整表清单(34 张表按业务域分组)
- 每张表列出全部字段(字段名、类型、中文说明)
- 标注关键字段的业务含义和使用注意事项
- 按业务域分组:会员域、助教域、财务域、配置域
-
金额口径专章
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)
-
会员字段断档说明
- 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
-
常用查询模式(ETL 侧)
- 客户消费汇总查询
- 助教绩效查询
- 财务日报查询
- 指数排名查询
-
数据量统计与性能建议
- 各表的大致数据量级
- 推荐的 WHERE 条件(时间范围、site_id)
- 避免全表扫描的建议
4.3 业务库手册内容(新建)
-
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)
-
每张表完整字段说明
- 字段名、类型、是否可空、默认值、中文说明
- 关键枚举值说明(如 coach_tasks.task_type、notes.type、ai_cache.cache_type)
- 外键关系和关联查询建议
-
常用查询模式(业务侧)
- 维客线索查询(按客户、按来源、按标签)
- 任务系统查询(按助教、按状态、按类型)
- 备注查询(按客户、按助教、含星星评分)
- AI 缓存查询(按应用类型、按 target_id)
- Excel 上传记录查询
-
跨库关联指南
- 业务库 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 多数据库连接
- 连接池大小:zqyy_app 连接池的 min/max 连接数?与 etl_feiqiu 共享还是独立?MCP Server 的并发查询量预估?
- DSN 环境变量:MCP Server 运行环境中
APP_DB_DSN是否已配置?测试环境使用test_zqyy_app还是zqyy_app? - RLS 隔离:MCP 查询 zqyy_app 时是否需要
SET LOCAL app.current_site_id?如果需要,site_id 从哪里获取(MCP 调用方传入?固定值?)? - 连接超时:FDW 查询和业务库查询的超时时间是否需要不同设置?
7.2 安全与脱敏
- 脱敏范围确认:除 auth.users 外,还有哪些表/字段需要脱敏?biz.notes 的备注内容是否需要脱敏?
- 脱敏粒度:是否需要根据 MCP 调用方身份区分脱敏级别?(如管理员可看完整数据,AI 应用只看脱敏数据)
- SQL 注入防护:现有正则禁词检测是否足够?是否需要升级为 SQL 解析器(如 sqlparse)?
- 审计日志:MCP 查询是否需要记录审计日志(谁查了什么表、什么时间)?
7.3 查库手册
- 手册格式:百炼平台对知识库文档的格式要求?Markdown 是否直接支持?是否需要转换为 PDF/TXT?
- 手册拆分:ETL 库和业务库是否拆分为两个知识库文档?还是合并为一个?
- 手册更新机制:表结构变更后,手册如何同步更新?是否需要自动化脚本从数据库 DDL 生成手册?
- DWD 层覆盖:手册是否需要覆盖 DWD 层全部表的完整字段?还是只覆盖 DWS + 常用 DWD 表?
7.4 部署与运维
- MCP Server 重启:新增连接池后,MCP Server 是否需要重启?是否支持热加载配置?
- 监控指标:是否需要监控 MCP 查询的响应时间、错误率、查询频次?
- 降级策略: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 引用效果