--- name: lzwcai-agile-db description: AgileDB 数据库管理平台的 MCP 技能。为 AI Agent 提供完整的数据库操作工作流指导,适合零基础用户。 metadata: version: 0.4.4 --- # lzwcai-agile-db AgileDB 数据库管理平台的 MCP 技能。为 AI Agent 提供完整的数据库操作工作流指导,适合零基础用户。 ## 完整工具清单(57 个工具) 本 skill 基于 `lzwcai_mcp_agile_db` MCP Server,共提供 57 个工具,分为 12 大类。 > **⚠️ 契约提示(2026-06 真机验证)**:以下契约文档曾写错、已按真机修正,调用时务必遵守: > - **`target` 默认 `test`**(不是 prod)。写线上库必须显式传 `target="prod"`。 > - **`alter_table` 的 operation 只有 3 种**:`ADD_COLUMN` / `MODIFY_COLUMN` / `DROP_COLUMN`。其余(RENAME_COLUMN/ALTER_COLUMN_TYPE/SET_NOT_NULL...)后端**不支持**。 > - **`alter_database` 改名字段是 `newName`**(不是 newDatabaseName)。 > - **`generate_table_by_description` 是异步**:返回 taskId,需用 `get_ai_training_detail` 轮询。 > - **`list_tables_with_ai` 的 `datasourceId` 实为「库/配置 ID」**(list_databases 返回的 config id),不是连接 ID。 ### 一、数据源管理(10 个工具) | 工具 | 功能 | 危险等级 | |------|------|----------| | `list_datasources` | 获取数据源列表 | 安全 | | `get_datasource_detail` | 获取数据源详情(含数据库、表结构) | 安全 | | `create_datasource` | 创建外部数据源连接(可选先测连接) | 安全 | | `update_datasource` | 更新数据源连接信息 | 中等 | | `toggle_datasource_status` | 启用/停用数据源 | 中等 | | `delete_datasource` | 删除数据源 | **危险** | | `test_connection` | 测试外部数据库连接(不创建) | 安全 | | `get_realtime_structure` | 实时探测远端库表结构 | 安全 | | `create_builtin_datasource` | 创建内置 PostgreSQL 连接(建库表链路第一步) | 安全 | | `update_builtin_datasource` | 修改内置 PostgreSQL 连接 | 中等 | ### 二、数据库与表管理(9 个工具) | 工具 | 功能 | 危险等级 | |------|------|----------| | `list_databases` | 获取数据源下的数据库列表 | 安全 | | `list_tables` | 获取数据源下的表列表(基础) | 安全 | | `list_tables_with_ai` | 获取表元数据列表(含 AI 训练描述,内置库主列表) | 安全 | | `get_table_detail` | 获取表结构详情(字段、类型、主键) | 安全 | | `create_database` | 在内置源下创建数据库(建表前置) | **危险** | | `create_table` | 在指定库创建新表 | **危险** | | `create_database_table` | 一次性建库+表(合并接口) | **危险** | | `alter_table` | 修改表结构(仅 ADD/MODIFY/DROP_COLUMN) | **危险** | | `alter_database` | 修改数据库(改名,字段 newName) | **危险** | ### 三、AI 训练与生成(4 个工具) | 工具 | 功能 | 危险等级 | |------|------|----------| | `generate_table_by_description` | AI 自然语言生成表结构(异步,返回 taskId) | 安全(仅生成,不创建) | | `get_ai_training_detail` | 查询/轮询 AI 训练任务详情 | 安全 | | `list_ai_trainings` | AI 补全训练任务列表 | 安全 | | `create_ai_training_by_selected` | 按选中表创建 AI 补全训练 | 中等 | ### 四、表数据 CRUD(5 个工具,target 默认 test) | 工具 | 功能 | 危险等级 | |------|------|----------| | `query_table_data` | 查询表数据(分页) | 安全 | | `insert_table_row` | 插入一行数据 | 中等 | | `update_table_row` | 更新一行数据 | 中等 | | `delete_table_rows` | 删除数据行(按主键) | **危险** | | `export_table_excel` | 导出表数据为 Excel(base64) | 安全 | ### 五、SQL 执行(1 个工具) | 工具 | 功能 | 危险等级 | |------|------|----------| | `execute_sql` | 执行原生 SQL 查询(入参 `sql`,target 默认 prod) | 中等/危险 | ### 六、数据导入(2 个工具) | 工具 | 功能 | 危险等级 | |------|------|----------| | `preview_import_data` | 从 URL 下载 Excel 文件,AI 智能识别并预览 | 安全 | | `confirm_import_data` | 确认导入(需传 databaseName,自动组装结构) | **危险** | ### 七、表订阅(1 个工具) | 工具 | 功能 | 危险等级 | |------|------|----------| | `toggle_table_subscription` | 切换表的订阅状态(configId+tableName+subscribe) | 中等 | ### 八、API 密钥管理(7 个工具) | 工具 | 功能 | 危险等级 | |------|------|----------| | `list_api_keys` | 获取 API 密钥列表 | 安全 | | `create_api_key` | 创建新的 API 密钥 | 中等 | | `toggle_api_key_status` | 启用/禁用 API 密钥 | 中等 | | `delete_api_key` | 删除 API 密钥 | **危险** | | `get_api_key_permissions` | 查看指定密钥的权限配置 | 安全 | | `grant_api_key_permissions` | 批量为 API 密钥授予权限(仅追加,不可撤销) | **危险** | ### 九、技能与工具管理(7 个工具) | 工具 | 功能 | 危险等级 | |------|------|----------| | `add_sql_tool_to_datasource` | 把 SQL 沉淀为工具(一步到位,自动建技能+配模板+建工具,去重幂等)**唯一推荐入口** | 中等 | | `get_skill_by_datasource` | 根据数据源获取技能信息 | 安全 | | `get_skill_tools` | 获取技能下的工具列表 | 安全 | | `create_sql_tool` | 将 SQL 创建为可复用工具(底层积木,需技能已存在) | 中等 | | `delete_skill_tool` | 删除技能下的工具 | **危险** | | `update_skill_config` | 更新技能配置(名称/描述/模板) | 中等 | | `update_skill_tool` | 修改技能工具(id+description+uniqueName) | 中等 | ### 十、库表关联配置(3 个工具,外置源纳管/内置删库) | 工具 | 功能 | 危险等级 | |------|------|----------| | `create_connection_config` | 建库表关联(外置源建连后选库选表的最后一步) | 中等 | | `update_connection_config` | 改库表关联范围 | 中等 | | `delete_connection_config` | 删库表关联(也是「删内置库」的实现) | **危险** | ### 十一、MQTT 字段关联同步(8 个工具,内置源专属) | 工具 | 功能 | 危险等级 | |------|------|----------| | `list_mqtt_configs` | MQTT 同步配置列表 | 安全 | | `get_mqtt_config_detail` | 配置详情 | 安全 | | `list_mqtt_target_tables` | 可同步目标表列表 | 安全 | | `list_mqtt_target_table_columns` | 目标表字段列表 | 安全 | | `create_mqtt_config` | 新增同步配置 | 中等 | | `update_mqtt_config` | 修改同步配置 | 中等 | | `delete_mqtt_config` | 删除同步配置 | **危险** | | `refresh_mqtt_config_cache` | 刷新配置缓存 | 安全 | --- ## 核心概念说明 ### 数据源是什么? 数据源 = 一个数据库连接。它可以是: - `builtin`:内置 PostgreSQL 数据库(系统自带) - `external`:外部数据库(MySQL、PostgreSQL、Oracle、SQL Server、达梦等) ### 数据源状态 - `0` = 运行中(正常) - `1` = 已停止(不可用) ### 环境参数 `target` - `prod` = 生产环境(正式数据) - `test` = 测试环境(调试数据) > **重要**:表数据 CRUD(query/insert/update/delete/export)的 `target` **默认 `test`**(安全优先)。要操作正式数据必须**显式传 `target="prod"`**。 > 例外:`execute_sql` 的 target 默认 `prod`(沿用原行为)。 ### 主键 `primaryKey` 主键是唯一标识一行数据的字段。例如 `{"id": 1}` 表示删除/更新 id=1 的那行数据。 ### `connectionId` vs `datasourceId` - `datasourceId`:用于数据源列表、数据库列表、表列表等浏览类操作 - `connectionId`:用于创建表、修改表、数据导入等需要直接操作连接的操作 - 两者通常指向同一个东西,但 API 设计不同,请按照工具说明使用 --- ## ⚠️ 安全确认原则(必须遵守) ### 〇、目标资源不得擅自选择(最高优先级铁律) 定位操作目标的参数(`datasourceId` / `connectionId` / `databaseName` / `tableId` / `tableName` / `apiKeyId` / `skillId` 等),**永远不得猜测、编造或"随手挑一个"**: - **多个候选** → 列出全部,让用户选;严禁默认第一个或自认为"最合理"的那个。 - **唯一候选** → 先声明"我将使用 XXX",给用户否决机会;创建/写入/删除类仍需用户确认后执行。 - **没有候选 / 信息不足** → 直接问用户,不得编造。 > 当你发现自己正在"替用户决定用哪个数据源/数据库/表"时,立刻停下来改成提问。 **创建类操作**(`create_table` / `create_datasource` 等)执行前必须逐项确认落点,绝不"随便找个数据源就建"。例如建表须确认:数据源(`connectionId`)+ 数据库(`databaseName`)+ 表名(`tableName`),三者都要用户点头。 --- ### 一、执行工具前的风险评估 当执行以下类型的操作时,**必须先询问用户确认**,不得擅作主张: 1. **数据写操作(增 / 删 / 改)**:插入数据(`insert_table_row`)、更新数据(`update_table_row`)、删除数据(`delete_table_rows`)、导入数据(`confirm_import_data`)等 - 说明:写操作会改变库中数据,**执行前必须把将要写入/修改/删除的具体内容预览给用户,等待用户明确确认后才执行**;删除不可恢复 2. **删除操作**:删除数据源、删除表数据、删除 API 密钥、删除技能工具等 - 说明:此操作不可恢复,数据将永久丢失 3. **泄密风险操作**:导出包含敏感数据的表、创建 API 密钥、查看密钥详情等 - 说明:可能导致敏感信息泄露,需确认用户授权 4. **政治敏感操作**:涉及政治相关数据的查询、修改、删除等 - 说明:可能涉及合规风险,需确认用户意图 5. **疑似违规内容**:涉及色情、暴力、违法等内容的操作 - 说明:可能违反法律法规,必须拒绝执行并告知用户 #### 确认格式 执行上述操作前,必须使用以下格式向用户确认: ``` ⚠️ 安全提醒:此操作存在 [具体风险类型] 风险。 具体说明:[说明可能的后果] 请确认是否继续?(回复"确认"继续,或取消操作) ``` **只有在用户明确确认后才能继续执行。** --- ### 二、多步骤场景必须逐步确认 当完成任务需要调用多个工具时(如:先查询表结构 → 插入数据 → 确认结果),**不得一次性自动连续执行**: 1. **每完成一步后暂停**,向用户展示当前步骤的结果 2. **询问用户是否继续下一步**,等待确认后再执行 3. **不要假设用户的意图**,即使用户的请求看似明确,也需要分步确认 **示例**: ``` 用户:"帮我新增一个用户" ❌ 错误做法:自动调用 get_table_detail → insert_table_row → 返回结果(一次性执行完) ✅ 正确做法: 1. 调用 get_table_detail 了解表结构 2. 展示必填字段清单,询问用户:"请提供以下必填字段的值:..." 3. 用户回复后,展示将要插入的数据预览 4. 询问:"确认插入以上数据?" 5. 用户确认后才调用 insert_table_row ``` --- ### 三、遇到多项选择时必须询问用户 当执行任务过程中遇到需要选择的场景时,**AI 不得擅自做主选择**: 1. **列出所有可选方案**,说明每个方案的优缺点或适用场景 2. **等待用户明确选择**,不要猜测用户意图 3. **不要默认选择第一个**或看似最合理的选项 #### 常见需要询问的选择场景: - 有多个数据源可选时 - 有多个数据库可选时 - 有多个表可选时 - 有多种操作方式可选时(如:用 SQL 查询 vs 用表数据查询工具) - 有多种字段类型可选时 - 用户描述模糊,存在多种理解方式时 **示例**: ``` 用户:"查一下订单数据" ❌ 错误做法:直接选择第一个数据源和第一个订单表进行查询 ✅ 正确做法: "找到以下数据源包含订单相关表: 1. HMD产品 → order_db → orders 表(156 条记录) 2. 测试数据源 → test_db → test_orders 表(10 条记录) 请问您想查询哪个?" ``` --- ## 场景 1:浏览数据源(新手入门第一步) 当用户想了解系统里有哪些数据库或表时,使用此流程。 ### 工作流程 ``` 用户请求: "有哪些数据源?" / "看看 XX 数据源有哪些表?" / "帮我查一下数据库" ↓ 1. 调用 list_datasources() ↓ 2. 展示数据源列表(名称、类型、状态、数据库数、表数) ↓ 3. 用户选择数据源后,调用 get_datasource_detail(datasourceId="xx") ↓ 4. 展示数据库列表和实时表结构 ``` ### 示例 **用户**: "帮我看看有哪些数据源" ``` 调用: list_datasources() 返回: { "total": 14, "rows": [ {"id": "58", "datasourceName": "HMD产品", "host": "host.docker.internal", "port": 5432, "status": 0, ...}, ... ] } 回复: 共找到 14 个数据源: 1. HMD产品(PostgreSQL, host.docker.internal:5432, 运行中) 2. ... 请告诉我你想看哪个数据源? ``` **用户**: "看看 HMD 产品有哪些表" ``` 调用: get_datasource_detail(datasourceId="58") 返回: { "detail": {...}, "config": {...}, "structure": { "databases": [ {"name": "order_db", "tables": [ {"tableName": "orders", "columns": [...]}, ... ]} ] } } 回复: HMD产品 数据源包含以下数据库和表: order_db: - orders (订单表, 15 个字段) - users (用户表, 8 个字段) ``` ### 注意事项 - 数据源类型为 `builtin` 表示系统内置数据库,类型为具体的数据库引擎名称(mysql、postgresql 等)表示外部数据源 - 如果用户只说"查一下数据库",先调用 `list_datasources()` 再引导选择 - 已停止的数据源(status=1)无法访问其结构 --- ## 场景 2:查询表数据 当用户想要查看某张表的具体数据记录时,使用此流程。 ### 工作流程 ``` 用户请求: "查一下 users 表的数据" / "看看前 20 条订单" ↓ 1. 如果不知道 tableId,先浏览数据源找到目标表 ↓ 2. 调用 query_table_data(tableId="xx", pageNum=1, pageSize=10, target="prod") ↓ 3. 展示数据(表格形式,包含字段名和值) ↓ 4. 如果数据量大,提示用户可翻页或调整 pageSize ``` ### 示例 **用户**: "查一下 users 表前 10 条数据" ``` 调用: query_table_data(tableId="5", pageNum=1, pageSize=10) // target 默认 test;查正式数据传 target="prod" 返回: { "data": { "tables": { "tableName": "users", "columns": [ {"columnName": "id", "columnType": "serial", "isPrimaryKey": true}, {"columnName": "username", "columnType": "varchar"}, ... ] }, "content": [[1, "admin", "admin@test.com"], [2, "user1", "user1@test.com"], ...], "total": 156 } } 回复: users 表共 156 条记录,当前显示第 1-10 条: | id | username | email | |----|----------|-----------------| | 1 | admin | admin@test.com | | 2 | user1 | user1@test.com | ... ``` > **返回结构注意**:列定义在 `data.tables.columns[]`(字段名 `columnName`、是否主键 `isPrimaryKey`),行数据在 `data.content[]` 且是**位置数组**(按列顺序,不是键值对象)。展示/取主键时要把 content 的每个位置对到 columns 的同序字段。 ### 注意事项 - `target` 参数:`test`=测试环境(**默认**),`prod`=生产环境(查正式数据须显式传) - 如果用户未指定数量,默认 `pageSize=10` - 如果用户说"翻页",增加 `pageNum` 参数 - 如果用户想看更多数据,可以增大 `pageSize`(最大根据 API 限制) - 行数据是位置数组(`data.content[]`),需对照 `data.tables.columns[]` 的列顺序解析 --- ## 场景 3:执行 SQL 当用户需要执行自定义 SQL 查询时,使用此流程。 ### 工作流程 ``` 用户请求: "帮我执行 SQL..." / "查一下订单数大于 100 的用户" ↓ 1. 如果用户直接提供 SQL,直接使用 如果用户提供自然语言需求,先转换为 SQL ↓ 2. 调用 execute_sql(datasourceId="xx", sql="SELECT ...") ↓ 3. 展示查询结果 ↓ 4. 如果 SQL 执行失败,展示错误信息并建议修正 ``` ### 示例 **用户**: "统计每个地区的订单数量" ``` 转换为 SQL: SELECT region, COUNT(*) as order_count FROM orders GROUP BY region ORDER BY order_count DESC 调用: execute_sql( datasourceId="58", sql="SELECT region, COUNT(*) as order_count FROM orders GROUP BY region ORDER BY order_count DESC" ) 返回: { "columns": [{"name": "region"}, {"name": "order_count"}], "data": [{"region": "华东", "order_count": 1250}, {"region": "华南", "order_count": 980}, ...] } 回复: 各地区订单统计: | 地区 | 订单数 | |------|--------| | 华东 | 1,250 | | 华南 | 980 | | 华北 | 756 | ``` ### 注意事项 - `datasourceId` 必须提供,如果用户未指定,先询问 - `sqlTemplate` 可选,用于模板化查询 - `params` 可选(对象),用于参数化查询(防止 SQL 注入);工具内部映射为后端的 `parameters` - `target` 可选:`test`=测试环境(默认),`prod`=生产环境 - **执行危险操作(DELETE/DROP/TRUNCATE)前,必须向用户确认** - 如果查询结果超过 100 行,建议用户使用 `query_table_data` 代替 - 对于只读查询(SELECT),可以直接执行;对于写操作(INSERT/UPDATE/DELETE),必须二次确认 --- ## 场景 4:增删改数据 当用户需要修改表中的数据时,使用此流程。 > 🔒 **写操作统一规则(插入 / 更新 / 删除都适用)**:在调用 `insert_table_row` / `update_table_row` / `delete_table_rows` 之前,**必须先把将要写入/修改/删除的具体数据预览给用户,并等待用户明确确认后才执行**。不得在用户未确认的情况下直接落库。 ### 4.1 插入数据 ``` 用户请求: "新增一个用户,用户名是 test_user" ↓ 1. 先调用 get_table_detail(tableId="xx") 了解表结构 ↓ 2. 确认必填字段(非空字段、无默认值字段) ↓ 3. 向用户展示将要插入的数据,询问"确认插入以上数据?",等待用户确认 ↓ 4. 用户确认后,调用 insert_table_row(tableId="xx", data={...}) ↓ 5. 确认插入成功 ``` **示例**: **用户**: "新增一个用户,用户名 test_user,邮箱 test@test.com" ``` 调用: get_table_detail(tableId="5") 返回: {columns: [{name: "id", isPrimaryKey: true, isAutoIncrement: true}, {name: "username", isNullable: false}, ...]} 回复: 即将向 users 表插入以下数据: username = test_user, email = test@test.com (id 自动生成)。确认插入吗? 用户: "确认" 调用: insert_table_row( tableId="5", data={"username": "test_user", "email": "test@test.com"} ) 回复: 已成功插入用户 test_user (ID 自动生成) ``` ### 4.2 更新数据 ``` 用户请求: "把用户 test_user 的邮箱改成 new@test.com" ↓ 1. 确认主键字段和要更新的值 ↓ 2. 向用户展示「目标行 + 改动前→改动后」的预览,询问"确认更新?",等待用户确认 ↓ 3. 用户确认后,调用 update_table_row(tableId="xx", primaryKey={主键}, data={要更新的字段}) ↓ 4. 确认更新成功 ``` **示例**: **用户**: "把 ID 为 5 的用户邮箱改成 new@test.com" ``` 回复: 即将更新 users 表 ID=5 的记录: email: old@test.com → new@test.com 确认更新吗? 用户: "确认" 调用: update_table_row( tableId="5", primaryKey={"id": 5}, data={"email": "new@test.com"} ) 回复: 已更新用户 ID=5 的邮箱为 new@test.com ``` ### 4.3 删除数据 ``` 用户请求: "删除用户 test_user" ↓ 1. ⚠️ 安全提醒:此操作存在删除风险。 说明:数据将永久删除,不可恢复。 请确认是否继续? ↓ 2. ⚠️ 危险操作!先确认删除范围和影响 ↓ 3. 向用户展示将要删除的数据,请求确认 ↓ 4. 用户确认后,调用 delete_table_rows(tableId="xx", primaryKeys=[{主键}]) ↓ 5. 确认删除成功 ``` **示例**: **用户**: "删除 ID 为 10 的订单" ``` 回复: ⚠️ 确认要删除以下记录吗? 订单 ID=10, 订单号=ORD-2024-0010, 金额=¥1,250.00 此操作不可恢复。请回复"确认删除"继续。 用户: "确认删除" 调用: delete_table_rows( tableId="3", primaryKeys=[{"id": 10}] ) 回复: 已成功删除订单 ID=10 ``` **注意:如果删除内容涉及敏感数据(如用户隐私、政治相关内容、疑似违规内容),必须额外说明后果并再次确认。** ### 4.4 导出表数据为 Excel ``` 用户请求: "把 users 表数据导出成 Excel" ↓ 1. 调用 export_table_excel(tableId="xx", target="prod") ↓ 2. 返回 base64 编码的 Excel 文件内容 ↓ 3. 提示用户解码 base64 获取文件 ``` **示例**: ``` 调用: export_table_excel(tableId="5") 返回: { "success": true, "file_base64": "UEsDBBQAAAAI...", "message": "Excel 文件已导出,请解码 base64 内容获取文件" } 回复: 已成功导出 users 表数据为 Excel 文件 文件内容已 base64 编码,请解码后保存为 .xlsx 文件 ``` ### 注意事项 - **写操作(插入/更新/删除)执行前必须先预览数据并等待用户确认**;删除操作不可恢复,需格外谨慎 - `primaryKey` 必须是对象格式,如 `{"id": 1}` - `primaryKeys` 是数组格式,如 `[{"id": 1}, {"id": 2}]` - `data` 只包含要更新的字段,不需要提供全部字段 - 插入数据时,自增主键不需要提供 - 如果操作涉及多行,使用批量操作或循环调用 - 增删改操作 `target` **默认 `test`**(安全优先);要写正式数据必须显式传 `target="prod"` --- ## 场景 5:AI 生成表结构 当用户需要创建新表但不知道如何设计表结构时,使用 AI 辅助生成。 ### 工作流程 ``` 用户请求: "我需要一个用户表" / "帮我设计一个订单系统的表结构" ↓ 1. 调用 generate_table_by_description(requirement="用户描述") → 返回 taskId(异步任务,此时还没有表结构) ↓ 2. 轮询 get_ai_training_detail(taskId="xx") 直到 trainingStatus=2(已完成) trainingStatus: 0 待训练 / 1 训练中 / 2 已完成 / 3 失败 完成后表结构在 createTableData.data.tables[] 里 ↓ 3. 展示 AI 生成的表结构(表名、字段、类型、注释) ↓ 4. ⚠️ 确认落点:列出可用数据源,让用户选择 connectionId 和 databaseName (多个数据源时必须让用户选,绝不擅自找一个;只有一个也要说明后再继续) ↓ 5. 用户确认表结构 + 落点后,调用 create_table(connectionId="xx", databaseName="xx", tableName="xx", columns=[...]) ↓ 6. 确认创建成功 ``` ### 示例 **用户**: "帮我设计一个商品表,包含名称、价格、库存、分类" ``` 调用: generate_table_by_description( requirement="我需要一个商品表,包含商品名称、价格、库存、分类,用于电商系统" ) 返回: {"data": {"taskId": "831", "status": "0", "message": "任务已提交,等待AI生成表结构"}} ← 异步!返回的是 taskId,不是表结构 轮询: get_ai_training_detail(taskId="831") 返回(完成时): { "data": { "trainingStatus": "2", // 2=已完成 "progress": 100, "createTableData": {"data": {"tables": [{ "tableName": "products", "tableComment": "商品表", "columns": [ {"columnName": "id", "columnType": "SERIAL", "isPrimaryKey": true, "columnComment": "主键ID"}, {"columnName": "name", "columnType": "VARCHAR", "columnLength": 200, "isNullable": false, "columnComment": "商品名称"}, {"columnName": "price", "columnType": "DECIMAL", "columnLength": 10, "columnComment": "价格"}, {"columnName": "stock", "columnType": "INTEGER", "columnComment": "库存数量"} ] }]}} } } 回复: AI 已生成表结构设计: 表名: products (商品表) 字段: - id (SERIAL, 主键) - 主键ID - name (VARCHAR(200), 非空) - 商品名称 - price (DECIMAL(10)) - 价格 - stock (INTEGER) - 库存数量 是否需要在此基础上修改或直接创建? 用户: "直接创建到 order_db 数据库" 调用: create_table( connectionId="58", databaseName="order_db", tableName="products", tableComment="商品表", columns=[...] // 使用轮询拿到的 createTableData.data.tables[0].columns ) 回复: 已成功创建表 products (商品表) ``` ### 修改表结构(alter_table) 如果用户需要修改已有表的结构: ``` 用户请求: "给 users 表加一个 phone 字段" ↓ 1. 确认表结构和要修改的内容 ↓ 2. 构建 operations 数组(支持多种变更类型) ↓ 3. 调用 alter_table(connectionId="xx", databaseName="xx", tableName="xx", operations=[...]) ↓ 4. 确认修改成功 ``` **可用的 operations 类型(真机验证,后端仅支持这 3 种)**: - `ADD_COLUMN`:添加字段 - `MODIFY_COLUMN`:修改字段(改类型/长度/可空/默认值/注释,整列重定义) - `DROP_COLUMN`:删除字段 > ⚠️ 后端**不支持** `RENAME_COLUMN`/`ALTER_COLUMN_TYPE`/`SET_NOT_NULL`/`DROP_NOT_NULL`/`SET_DEFAULT`/`DROP_DEFAULT`(会报「不支持的操作类型」)。改字段类型/约束统一用 `MODIFY_COLUMN` 传完整列定义。 > `operations[].column` 是列定义对象,字段同建表(columnName/columnType/columnLength/isNullable/columnComment/defaultValue 等)。 ### 注意事项 - `requirement` 参数应尽可能详细,包含业务场景和字段需求 - AI 生成的表结构可能需要用户调整(如字段长度、类型) - 创建表前需要确认 `connectionId` 和 `databaseName` - 常用字段类型:`VARCHAR`, `INTEGER`, `SERIAL`(自增主键), `DECIMAL`, `TIMESTAMP`, `TEXT`, `BOOLEAN` - 如果用户描述模糊,先引导用户补充细节 --- ## 场景 6:数据导入(Excel 到数据库) 当用户需要从 Excel 文件导入数据到数据库时,使用此流程。 ### 工作流程 ``` 用户请求: "帮我导入这个 Excel 文件" / "把表格数据导入数据库" ↓ 1. 拿到 Excel 文件的可下载 URL(http/https,<500KB,.xlsx/.xls) ↓ 2. 调用 preview_import_data(connectionId="xx", file_url="https://example.com/data.xlsx", target="test") ↓ 3. 展示 AI 识别的表结构和数据预览 ↓ 4. ⚠️ 安全提醒:此操作可能涉及数据安全风险。 说明:导入的数据将写入数据库,请确认数据来源合法合规,不包含敏感信息、政治内容或违规内容。 请确认是否继续? ↓ 5. 用户确认无误后,调用 confirm_import_data(connectionId="xx", databaseName="目标库名", data=<预览返回的原文>, target="test") (把 preview_import_data 的返回原样传给 data,工具会自动组装后端要求的结构;databaseName 是落库的目标库) ↓ 6. 确认导入成功(返回含 insertedRows 插入行数) ``` ### confirm_import_data 的 data 传什么 把 `preview_import_data` 返回的 data 原文整块传给 `data` 参数即可,工具会自动解包组装。data 的标准形态(= preview 返回): ```json { "tableStructure": { "success": true, "message": "Excel表结构生成成功", "data": { "tables": [ { "tableName": "animals", "tableComment": "宠物信息表", "columns": [ { "columnName": "id", "columnType": "SERIAL", "isPrimaryKey": true, "isAdditionField": true }, { "columnName": "animal_name", "columnType": "VARCHAR", "columnLength": 5000 } ] } ] }, "allData": [ ["id", "animal_name", "..."], ["1", "豆豆", "..."], ["2", "咪咪", "..."] ] }, "databaseName": "pp_test", "target": "prod" } ``` - `tableStructure`:preview 的表结构包装(`{success, message, data:{tables:[...]}}`),工具会取 `tables[0]` 当单表对象,并把 `databaseName` 塞进去。 - `databaseName` / `target` 既可放顶层参数,也可放在 `data` 里,工具都认。 - ⚠️ **allData 是二维数组,首行必须是「列名表头行」**: - `allData[0]` = 各列的 `columnName`(列名表头),**真实数据从 `allData[1]` 起**; - 每行(含表头行)都是按 `columns` 顺序排列的位置数组,**行宽 = 列总数**(含 `SERIAL` 主键等所有列,**不裁剪**,主键列给占位值即可,后端自增时会忽略); - 若传入的 allData 没带表头行(首行就是数据),工具会**据列名自动补一行表头**——否则后端会把首行数据当成字段名,报「查询字段不存在/字段名称不正确」。 - ⚠️ **columns / 表头列名必须对应目标表真实存在的字段**:后端按列名拼 INSERT,`tableStructure.columns`(以及 allData 首行表头)里的列名必须是目标表里**确实存在的字段名**,否则报「查询字段不存在 / 字段名称不正确」。 - **导入到已有表时**:不要直接用 Excel 识别出的列,应**先 `get_table_detail(tableId="xx")` 拿到目标表真实字段,再把 data 里的 columns、allData 首行表头、各行取值都对齐到这些真实字段**(前端就是用目标表真实列覆盖 AI 识别列的)。 ### 注意事项 - 文件大小限制:< 500KB - 支持格式:.xlsx / .xls - 导入前默认使用 `test` 环境(安全做法) - 如果用户要导入到正式环境,必须二次确认 - `file_url` 要求 http/https 可下载链接,且文件大小 < 500KB - `file_url` 对应的文件扩展名需为 `.xlsx` / `.xls` - **`confirm_import_data` 必须传 `databaseName`**(落库目标库);`data` 直接传 `preview_import_data` 的返回原文即可,工具内部会自动解包并组装成 `{tableStructure(含databaseName), allData}` - AI 识别会把中文表头转成英文列名(如「姓名」→`name`);若导入数据键名与生成的列名对不上会报「未找到 XX 字段」,此时需按预览返回的列名核对 - 后端报「插入数据失败(第N行):查询字段不存在/字段名称不正确」时,多半是 **allData 缺了列名表头行**(后端把首行数据当成了字段名),或某行列数与 `columns` 对不上——确认首行是列名、每行值个数 = 列总数 --- ## 场景 7:API 密钥管理 当用户需要管理 API 密钥时,使用此流程。 ### 7.1 查看密钥列表 ``` 调用: list_api_keys() 返回: { "total": 6, "rows": [ {"id": "7", "apiKeyName": "AWINBEXT", "apiKey": "Lb8Lg...", "status": 0, "expireTime": "2027-06-06..."}, ... ] } ``` ### 7.2 创建新密钥 ``` 调用: create_api_key(apiKeyName="新密钥名称") 返回: 包含新创建的密钥信息 ``` ### 7.3 启用/禁用密钥 ``` 调用: toggle_api_key_status(id="7", status=0) // 0=启用, 1=禁用 ``` ### 7.4 删除密钥 ``` ⚠️ 删除前确认: ⚠️ 安全提醒:此操作存在删除风险。 说明:API 密钥删除后不可恢复,依赖该密钥的服务将失效。 请确认是否继续? 回复: 确认要删除 API 密钥 "AWINBEXT" 吗?此操作不可恢复。 调用: delete_api_key(id="7") ``` ### 7.5 查看密钥权限 ``` 调用: get_api_key_permissions(apiKeyId="7") ``` ### 7.6 批量授权 ``` 调用: grant_api_key_permissions( apiKeyId="7", batchDatas=[ { "connectionId": "58", "permissionLevel": "connection", "permissionType": "read,write" }, { "connectionId": "58", "permissionLevel": "database", "databaseName": "order_db", "permissionType": "read" } ] ) ``` 权限级别说明: - `connection`:数据源级别权限 - `database`:数据库级别权限 - `table`:表级别权限 > ⚠️ 权限为「仅追加」模型:`grant_api_key_permissions` 只能新增权限,不会覆盖已有权限,且后端**不支持撤销/删除已授予的权限**。授权前务必确认范围,授错只能删掉整个密钥(`delete_api_key`)后重建。 ### 7.7 调整权限(只能重建密钥) ``` # 后端不支持撤销单条权限。如需收回某密钥的权限,只能删除密钥后重新创建并重新授权: 调用: delete_api_key(id="7") 调用: create_api_key(apiKeyName="xxx") 调用: grant_api_key_permissions(apiKeyId="<新密钥ID>", batchDatas=[...]) ``` > 说明:后端 permission 删除接口返回「不支持当前的调用方式」,无法撤销单条已授予权限。要缩小权限范围,走「删密钥 → 重建 → 重新授权」。 --- ## 场景 8:技能与工具管理 当用户需要把 SQL 沉淀为数据源的可复用工具时,使用此流程。 > 🔒 **核心约束:技能(skill)必须挂着工具才有效**。后端/前端都没有「只建空技能」这个动作——单独建技能会留下一个无效的空技能。前端唯一入口是「添加工具」,它会按需把技能建好、配好,最后必定以创建工具收尾。 ### 8.0 一步到位:把 SQL 沉淀为工具(推荐) **优先用 `add_sql_tool_to_datasource`**,它一步完成整条链路,保证技能必有工具: ``` 调用: add_sql_tool_to_datasource( datasourceId="58", name="查询活跃用户", businessDescription="查询所有状态为活跃的用户", sqlTemplate="SELECT * FROM users WHERE status = #{status}", sqlParams={"type":"object","required":["status"],"properties":{"status":{"type":"string","description":"用户状态","examples":["active"]}}}, // 可选 resultType="list", // 可选,默认 list businessScenario="用于查看当前活跃用户列表", // 可选 tableIds=["5"] // 可选 ) ``` > **sqlParams 格式**:标准 JSON Schema,形如 `{"type":"object","required":[...],"properties":{"参数名":{"type":"...","description":"...","examples":[...]}}}`。`properties` 的键要与 SQL 模板里的 `#{参数名}` 占位符一一对应。传 dict 会自动序列化为 JSON 字符串;无参数可传 `{}`。 内部流程(= 前端 handleAddToolSubmit): ``` 读 skillBool(GET /datasource/config/{id}) ├─ 技能已存在 → getByDatasource 拿 skillId → 按 sqlTemplate 去重 → confirmTools 建工具 └─ 技能不存在 → createOrGet 建技能 → getByDatasource 拿 skillId → 去重 → updateOrGet 写 lzwcai-mcp-sqlexecutor 配置模板 → confirmTools 建工具 ``` - **幂等**:同 datasourceId 下若已有 `sqlTemplate` 相同的工具(空白归一化后比较),返回 `skipped`,不重复创建。 - **skillId 来自 getByDatasource**,不是 createOrGet 的返回(后端 createOrGet 不回可靠 id)。 ### 8.1 查看数据源关联的技能 ``` 调用: get_skill_by_datasource(datasourceId="58") ``` ### 8.3 查看技能下的工具 ``` 调用: get_skill_tools(skillId="xx") ``` --- ### 分步操作(高级,一般不需要) > ⚠️ **不要单独建空技能**:技能必须挂着工具才有效,平时不会单独创建技能。常规「把 SQL 沉淀为工具」一律用 `add_sql_tool_to_datasource`(它会按需建技能+配模板+建工具)。下面的散工具仅用于「技能已存在」时单独加/改工具。 ### 8.4 向已有技能添加 SQL 工具(底层积木,需技能已存在) ``` # 前提:技能已存在(用 get_skill_by_datasource 拿到 skillId); # 若技能不存在,请直接用 add_sql_tool_to_datasource,别手动建空技能 调用: create_sql_tool( skillId="xx", tableIds=["5"], suggestions=[{ "name": "查询活跃用户", "businessDescription": "查询所有状态为活跃的用户", "sqlTemplate": "SELECT * FROM users WHERE status = #{status}", "sqlParams": {"type":"object","required":["status"],"properties":{"status":{"type":"string","description":"用户状态","examples":["active"]}}}, "resultType": "list", "businessScenario": "用于查看当前活跃用户列表" }] ) ``` ### 8.5 删除技能工具 ``` ⚠️ 删除前确认: ⚠️ 安全提醒:此操作存在删除风险。 说明:技能工具删除后不可恢复。 请确认是否继续? 调用: delete_skill_tool(skillToolId="xx") ``` ### 8.6 更新技能配置 ``` # datasourceId + skillId 均必填(真实 ID,来自其他工具返回,不可臆造) # 只给这两个 ID 即自动生成 lzwcai-mcp-sqlexecutor 标准配置模板 调用: update_skill_config( datasourceId="58", // 来自 list_databases / list_tables_with_ai / get_connection_config_list skillId="xx" // 来自 get_skill_by_datasource 返回 ) # 或:手动指定完整 configTemplate(覆盖自动生成) 调用: update_skill_config( datasourceId="58", skillId="xx", configTemplate='{"mcpServers": {...}}' // JSON 字符串 ) ``` > 说明:configTemplate 大部分是固定值,只有 mcpServerKey 后缀、`env.databaseId`、`env.skillId` 随 datasourceId / skillId 变化。两个 ID 都必填且必须是其他工具返回的真实值。不显式传 configTemplate 时,工具会按标准模板自动生成(与前端 SqlControllerMsg.vue 一致),无需手写整段 JSON。 ### 8.7 修改技能下某个工具 ``` 调用: update_skill_tool( id="2066468871151718402", // 工具 ID(来自 get_skill_tools 返回的 id) description="改后的业务描述", // 可选 uniqueName="新展示名", // 可选(工具展示名) sqlTemplate="SELECT ...", // 可选 resultType="list" // 可选:single / list ) ``` > 说明:后端实体真实字段为 `id`/`uniqueName`/`description`/`sqlTemplate`/`resultType`。旧参数名 `skillToolId`/`name`/`businessDescription` 仍有兼容映射,但建议直接用上面的真实字段名。`businessScenario` 后端无此字段,会被丢弃。 --- ## 场景 9:表订阅管理 ``` 用户请求: "订阅 orders 表" / "取消订阅 users 表" 调用: toggle_table_subscription( configId="数据库配置ID", tableName="orders", subscribe=true // true=订阅, false=取消订阅 ) ``` --- ## 场景 10:库表关联配置(外置源纳管 / 内置删库) 「库表关联配置」是数据源能用于智能问数的**最后一步**:外置数据源建好连接后,必须选定要纳管的库与表,平台才会同步结构、允许后续问数。这一类有 3 个工具:`create_connection_config` / `update_connection_config` / `delete_connection_config`。 > **概念澄清**: > - 配置(config)≠ 连接(connection)。`create_connection_config` 落库后产生的 **config id**,正是 `list_databases` / `list_tables_with_ai` 里要传的那个「库/配置 ID」(`datasourceId` 参数实际指它,不是连接 ID)。 > - `delete_connection_config` 既是「删库表关联」,也是**「删除内置库」的唯一实现**——删内置库就是删掉它对应的那条配置。 ### 10.1 外置源纳管(建连接后的收尾步骤) ``` 用户请求: "把刚建的 MySQL 数据源接进来" / "让这个数据源能问数" ↓ 1. 已有外置连接(create_datasource 返回的 connectionId) ↓ 2. 调用 get_realtime_structure(datasourceId="连接ID") 探测真实库表 ↓ 3. ⚠️ 列出探测到的库和表,让用户勾选要纳管的范围 (多个库/表时必须让用户选,不得擅自全选或挑第一个) ↓ 4. 调用 create_connection_config(connectionId="xx", databases=[{databaseName, tableNames:[...]}]) ↓ 5. 确认纳管成功(返回 config id,后续 list_tables_with_ai 用它) ``` **示例**: **用户**: "把 mysql_test 数据源的 order_db 库接进来,纳管 orders 和 users 两张表" ``` 调用: get_realtime_structure(datasourceId="58") // 先确认库表真实存在 调用: create_connection_config( connectionId="58", syncTables=true, // 默认 true,同步表结构 databases=[ {"databaseName": "order_db", "tableNames": ["orders", "users"]} ] ) 回复: 已纳管 order_db 库的 orders、users 两张表,该数据源现在可用于智能问数。 ``` ### 10.2 修改纳管范围 ``` 用户请求: "再把 products 表也纳管进来" / "改一下纳管的表" ↓ 1. 先拿到该配置的 config id(list_databases 返回里的 id) ↓ 2. ⚠️ 与用户确认最终要纳管的完整库表清单(这是全量覆盖,不是增量追加) ↓ 3. 调用 update_connection_config(id="配置ID", connectionId="xx", databases=[...]) ↓ 4. 确认更新成功 ``` > ⚠️ **全量覆盖语义**:`databases` 传的是更新后的**完整**纳管范围,不是增量。漏传已有的表会导致那些表被移出纳管,务必带上全部要保留的表。 **示例**: ``` 调用: update_connection_config( id="123", // 配置 ID(编辑必传) connectionId="58", databases=[ {"databaseName": "order_db", "tableNames": ["orders", "users", "products"]} ] ) 回复: 已更新纳管范围,order_db 现纳管 orders、users、products 三张表。 ``` ### 10.3 删除配置(含删除内置库) ``` ⚠️ 安全提醒:此操作存在删除风险。 说明:删除库表关联配置后,该库表将退出纳管、无法再问数; 若目标是内置库,则该库本身会被删除,库内数据永久丢失,不可恢复。 请确认是否继续?(回复"确认"继续,或取消操作) ↓ 用户确认后,调用 delete_connection_config(ids=["配置ID1", "配置ID2"]) ``` **示例**: **用户**: "删掉那个测试内置库" ``` 回复: ⚠️ 确认要删除内置库「test_db」(配置 ID=456)吗? 库内全部数据将永久删除,不可恢复。请回复"确认删除"继续。 用户: "确认删除" 调用: delete_connection_config(ids=["456"]) 回复: 已删除配置 456(内置库 test_db)。 ``` ### 注意事项 - `databases` 每项是 `{databaseName, tableNames:[...]}`,`tableNames` 是表名字符串数组(不是 tableId) - `syncTables` 默认 `true`(纳管时同步表结构),一般无需手动传 - `update_connection_config` 必传 `id`(配置 ID),且 `databases` 为**全量**覆盖 - `delete_connection_config` 的 `ids` 是数组,支持批量删;删内置库即删其对应配置 ID - 内置库删除属**危险操作**,务必先确认库名与影响后再执行 --- ### 1. 安全第一 #### 通用安全确认规则 - 执行任何工具前,评估是否存在删除、泄密、政治敏感、似黄等风险 - 存在风险时,**必须询问用户确认**,说明后果,不得擅作主张 - 用户未明确确认前,不得执行 - 执行任何写操作(INSERT/UPDATE/DELETE)前,先确认环境(prod vs test) - 删除操作必须向用户展示将要删除的数据并二次确认 - 危险操作(DELETE/DROP/TRUNCATE/UPDATE 影响多行)前必须明确告知用户风险 - 数据导入时默认使用 `test` 环境 ### 2. 分步引导 - 新手可能不知道 `datasourceId`、`tableId` 等参数,先通过列表工具引导获取 - 复杂操作分步执行,每步确认后继续 - 如果用户请求不完整(如未指定数据源),先引导补充信息 ### 3. 数据展示 - 表格数据使用 Markdown 表格格式 - 长文本截断显示(最多 100 字符) - 数字格式化(千位分隔符、货币符号) - 时间格式化为可读格式 - 展示数据时包含字段名和类型 ### 4. 错误处理 - API 错误:展示错误信息,建议重试或检查参数 - SQL 错误:展示 SQL 错误位置,建议修正 - 连接错误:检查数据源状态,建议启用或重新配置 - "登录过期":提示用户检查 `API_KEY` 环境变量 ### 5. 沟通方式 - 向小白用户解释时,避免使用技术术语(如 JSON Schema、SERIAL 等),用通俗语言 - 操作完成后告知结果(成功/失败/影响行数) - 如果用户操作成功,给出明确的反馈信息 --- ## 常用参数参考 ### 数据源类型 - `builtin` - 内置 PostgreSQL - `external` - 外部数据库(MySQL/PostgreSQL/Oracle/SQL Server/达梦等) ### 数据源状态 - `0` - 运行中 - `1` - 已停止 ### 环境 - `test` - 测试环境(**表数据 CRUD 的默认值**,安全优先) - `prod` - 生产环境(操作正式数据须显式传 `target="prod"`;仅 `execute_sql` 默认 prod) ### 常用字段类型 | 类型 | 用途 | 示例 | |------|------|------| | `SERIAL` | 自增主键 | `id SERIAL PRIMARY KEY` | | `VARCHAR(n)` | 短文本 | `username VARCHAR(50)` | | `TEXT` | 长文本 | `description TEXT` | | `INTEGER` | 整数 | `stock INTEGER` | | `DECIMAL(m,n)` | 精确小数 | `price DECIMAL(10,2)` | | `TIMESTAMP` | 时间戳 | `created_at TIMESTAMP` | | `BOOLEAN` | 布尔值 | `is_active BOOLEAN` | ### 表结构变更操作类型(alter_table) | 类型 | 用途 | column 对象关键字段 | |------|------|------| | `ADD_COLUMN` | 添加字段 | columnName, columnType, columnLength, isNullable, columnComment | | `MODIFY_COLUMN` | 修改字段(类型/长度/约束等,含改类型) | columnName, columnType, columnLength, ... | | `DROP_COLUMN` | 删除字段 | columnName | > 后端**只支持上述 3 种**。`RENAME_COLUMN`/`ALTER_COLUMN_TYPE`/`SET_NOT_NULL`/`DROP_NOT_NULL`/`SET_DEFAULT`/`DROP_DEFAULT` 均会报「不支持的操作类型」(已真机验证)。改字段类型用 `MODIFY_COLUMN`。 ### 权限级别(API 密钥授权) | 级别 | 范围 | |------|------| | `connection` | 整个数据源 | | `database` | 指定数据库 | | `table` | 指定表 | --- ## 快速开始 如果用户说"帮我查一下数据库",按以下步骤操作: 1. 调用 `list_datasources()` 获取数据源列表 2. 展示列表,让用户选择目标数据源(**多个候选时必须让用户选,不得默认第一个**;只有一个候选也要先说明"我将使用 XXX"再继续) 3. 调用 `get_datasource_detail(datasourceId="xx")` 获取数据库和表信息 4. 引导用户选择要操作的表 5. 根据用户意图调用相应的工具: - 想看数据 → `query_table_data` - 想执行 SQL → `execute_sql` - 想新增数据 → `insert_table_row` - 想修改数据 → `update_table_row` - 想删除数据 → `delete_table_rows`(需确认) - 想导出 Excel → `export_table_excel` - 想创建表 → `generate_table_by_description` + `create_table` - 想导入 Excel → `preview_import_data` + `confirm_import_data`