让 AI Agent 安全使用 MySQL / PostgreSQL 的 CLI 工具。 通过
node-sql-parser做 AST 级权限校验,配~/.agents/skills/db-driver/一键安装到所有 Agent。
让 AI 直接拼 SQL 是有风险的:
- 注释断字
U/**/PDATE绕过简单正则检测 - 存储过程
CALL proc()可以做任何事 - 一句写错的 SQL 改坏了生产数据
db-driver 把 SQL 喂给 AST 解析器(node-sql-parser),按权限位拦截,配 JSON 输出 / 加密存储 / Agent skill 给 AI Agent 用——最少上下文、最高可控、失败安全。
- 🛡️ AST 级权限校验 — 4 个权限位(query / update / delete / ddl),解析失败一律拒绝
- 🔐 加密存储 — AES-256-GCM 二进制 + master key 由 OS keyring 托管(Windows DPAPI / macOS Keychain / Linux Secret Service)
- 🤖 AI Agent 原生 —
db-driver install把 skill 装到~/.agents/skills/db-driver/,所有 Agent 自动学会用法 - 🗃️ MySQL & PostgreSQL — PG 多 schema、MySQL 分区表、
EXPLAIN/EXPLAIN ANALYZE - 💻 双模式配置 — 网页控制台(React UI)或 CLI flags(适合脚本)
- 📝 用法笔记 — 按
dbId绑定 SQL 习惯,明文 SQLite 存储(不含密码,可分享) - 🔁 备份与迁移 — 加密导出(PBKDF2 / AES-256-GCM),跨机器可恢复
只想让 AI Agent 立刻学会 db-driver 的用法、还没正式安装?一行命令把 skill 装到 ~/.agents/skills/db-driver/,不需要预装 db-driver 本体:
npx -y db-driver@latest install适合:
- 🤖 AI Agent 在用户机器上首次出现,临时把 skill 喂给本地的 Agent 工具(Claude Code、IDE agent 等)
- 🧪 想先看
SKILL.md内容再决定是否正式安装 - 🚀 CI / 脚本环境里不想
npm install -g污染全局
跑完这条命令后,Agent 就能识别
db-driver ...命令;需要真正执行 SQL 时再npm install -g db-driver即可。
# 1. 安装
npm install -g db-driver
# 2. 给 AI 配置一个 DB 连接(建议用只读账号)
db-driver config --dbId my-app \
--type mysql --host 127.0.0.1 --port 3306 \
--user reader --password secret --database mydb
# 3. 让 AI 自动装上 skill(也可省略——上面的 npx 命令已装过)
db-driver install
# 4. AI 开始查询
db-driver schema my-app
db-driver execute my-app "SELECT * FROM users LIMIT 5" --jsondb-driver install 会把 skill/SKILL.md 写入 ~/.agents/skills/db-driver/。之后任何支持 skills 的 Agent 工具(Claude Code、本地 IDE agent 等)都能自动发现并学会这套命令。
AI 拿到任务时的标准流程:
db-driver list→ 知道有哪些 dbId 可用db-driver schema <dbId>→ 列出表名(轻量,不爆上下文)db-driver schema <dbId> --table <name>→ 找具体表的字段 + 索引db-driver sample <dbId> <table>/count <dbId> <table>→ 看样本 / 统计db-driver execute <dbId> "<SQL>" --json→ 跑查询- 需要改表结构?→
db-driver execute <dbId> "<DDL>"(需要ddl权限)
给 AI 的最佳实践:
- 永远加
--json— Agent 解析 JSON 比解析表格稳 - 永远带
--limit— 默认 50 行,防爆炸 - 不确定时先 schema — 别瞎写列名 / 表名
- 写操作前先 count — 确认影响范围
核心设计:每个连接保存时绑定 4 个权限位,执行 SQL 前做权限校验。
| 权限位 | 默认值 | 允许的 SQL 类型 |
|---|---|---|
dmlQuery |
✅ true | SELECT / SHOW / DESCRIBE / EXPLAIN |
dmlUpdate |
❌ false | INSERT / UPDATE / REPLACE / MERGE |
dmlDelete |
❌ false | DELETE |
ddl |
❌ false | CREATE / ALTER / DROP / TRUNCATE / RENAME 等 |
任何 SQL 执行前都会走这个流程:
SQL 文本
↓
node-sql-parser 解析为 AST
↓
解析失败?→ ❌ 拒绝(防注释断字 / 条件注释等绕过)
↓
AST 类型 → 映射到 4 个权限位之一
↓
权限位开启?→ ✅ 执行
权限位关闭?→ ❌ 拒绝并打印「<操作> 已被禁用」
| 攻击 | 拦截方式 |
|---|---|
UPDATE users SET ... |
AST 识别为 update + dmlUpdate 未开 |
U/**/PDATE users ... |
注释断字 → parser 失败 → 拒绝 |
/*! UPDATE */ users ... |
MySQL 条件注释 → parser 失败 → 拒绝 |
CALL dangerous_proc() |
AST 识别为 call → 要求 ddl 权限 |
LOAD DATA INFILE ... |
AST 识别为 load → 要求 ddl 权限 |
PREPARE stmt FROM '...' |
AST 识别为 prepare → 要求 ddl 权限 |
多语句 SELECT 1; DROP TABLE x |
parser 返回多条语句 → 拒绝 |
| 语法错误 / 解析失败 | 一律 dangerous → 拒绝 |
- 数据库触发器:SELECT 自动触发 INSERT/UPDATE
- 用
root/superuser账号 → 任何工具都拦不住直接psql/mysql连 - AI 改其它通道(直接 psql、SSH、Web 面板)
👉 终极建议:用最小权限的 DB 账号配置 db-driver
-- MySQL 只读账号示例
CREATE USER 'reader'@'%' IDENTIFIED BY 'xxx';
GRANT SELECT ON mydb.* TO 'reader'@'%';
-- 写权限账号(谨慎)
CREATE USER 'writer'@'%' IDENTIFIED BY 'yyy';
GRANT SELECT, INSERT, UPDATE ON mydb.* TO 'writer'@'%';把 reader 配进 db-driver 给日常查询,需要写时再单独配 writer。
两种方式,二选一:
db-driver config \
--dbId my-app \
--type mysql \
--host 127.0.0.1 --port 3306 \
--user root --password secret \
--database app \
--dml-query --dml-update --ddl \
--test # 保存前先 ping必填:--dbId --type --host --user --password --database
可选:--port(按类型默认)、权限开关、--test、--schema(PG)、--description
PG 一个 catalog 内有多个 schema(如 public、tenant_1)。db-driver 默认按 public 处理:
db-driver config --dbId my-app \
--type postgres --host ... --database mydb \
--schema tenant_1 # 默认 public,可指定
--description "生产 - 租户1" # 可选,便于区分多套环境schema 命令支持临时覆盖:
db-driver schema my-app --schema tenant_1
db-driver schema my-app --schema tenant_1 --table ordersdb-driver console浏览器打开 http://127.0.0.1:7842,可视化增删改连接配置、勾选权限、查看表结构、编辑 SQL 用法笔记、测试连接等。Ctrl+C 退出。
连接配置用 AES-256-GCM 加密二进制存储,master key 由 OS keyring 托管(Windows DPAPI / macOS Keychain / Linux Secret Service)。
- 不存在明文 JSON,密码字段不被机器单独抽取
- 配置文件不公开具体路径
- 系统重装 / 换用户后 keyring 中的 key 会丢失,配置需重新 config(设计如此:密钥不跨机器迁移)
- 没有手动编辑入口;统一通过
db-driver config(CLI)或db-driver console(网页)修改
| 命令 | 说明 |
|---|---|
db-driver console [--port N] |
打开网页控制台(连接 + 用法,默认 7842 端口) |
db-driver config --dbId x --type ... |
命令行快速保存连接(适合脚本) |
db-driver list |
列出所有 dbId |
db-driver show <dbId> |
看连接详情(密码默认隐藏,--reveal-password 显示明文) |
db-driver test <dbId> |
测试连通性 |
db-driver remove <dbId> --yes |
删除连接 |
db-driver export <file> [--passphrase <pwd>] |
导出所有连接到文件(passphrase 留空 = 明文 JSON;≥8 位 = 加密 .exp) |
db-driver import <file> [--passphrase <pwd>] [--replace] |
从文件导入连接(同名 dbId 默认跳过,--replace 覆盖) |
| 命令 | 说明 |
|---|---|
db-driver schema <dbId> |
列表名(第一步必走) |
db-driver schema <dbId> --table <t> |
看字段 + 索引 + 注释 |
db-driver schema <dbId> --table <t> --show-partitions |
同时输出 MySQL 分区子表信息 |
db-driver schema <dbId> --search <p> |
按表名模糊过滤 |
db-driver schema <dbId> --schema <s> |
PG 临时切换 schema(覆盖配置默认) |
db-driver schema <dbId> --limit N --offset M |
列表分页(total / offset / limit 都在输出里) |
db-driver sample <dbId> <table> |
样本数据(默认 10 行) |
db-driver count <dbId> <table> |
行数 |
db-driver execute <dbId> "<SQL>" --json |
跑查询(带 JSON 输出) |
db-driver explain <dbId> "<SQL>" |
执行计划(不执行) |
db-driver explain <dbId> "<SQL>" --analyze |
真正执行并返回耗时 |
| 命令 | 说明 |
|---|---|
db-driver usage list |
列出(默认只显示标题 + 首行预览) |
db-driver usage list --dbId a,b |
过滤(逗号分隔,OR 匹配) |
db-driver usage list --search <kw> |
关键词搜索(title / dbIds / content) |
db-driver usage list --limit N --offset M |
翻页 |
db-driver usage detail <index> |
查看某条完整 Markdown |
db-driver usage save --dbId a,b --title "..." --content "..." |
新增(多 dbId 逗号分隔) |
db-driver usage save --dbId a --title "..." --content-file ./note.md |
从文件读内容 |
db-driver usage save --dbId a --title "..." --content-file - |
从 stdin 读 |
db-driver usage update <index> --title/--content/--dbIds |
更新(AI 友好,字段可省略) |
db-driver usage update <index> --content-file ./new.md |
从文件读新内容 |
db-driver usage bind --add prd |
批量给所有笔记加 prd 关联 |
db-driver usage bind --remove staging |
批量给所有笔记删 staging 关联 |
db-driver usage bind --entries 1,2,3 --add a |
只给指定序号加 |
db-driver usage rm <index> |
删除 |
db-driver usage clear [--dbId <id>] --yes |
清空(可指定 dbId) |
| 命令 | 说明 |
|---|---|
db-driver install |
把 skill 装到 ~/.agents/skills/db-driver/ |
db-driver update |
从 npm 自更新(拒绝源码 link 模式) |
db-driver update --check |
仅检查是否有新版 |
--json— 所有查询类命令都支持,AI 解析用--limit N—execute/sample限制返回行数(默认 50 / 10);schema/usage list列表分页--offset M—schema/usage list列表分页(与--limit配合翻页)--where <expr>—sample/count附加 WHERE 条件
所有 DB 错误自动翻译为中文,格式 中文提示(原始错误消息),便于排查:
| 错误码 | 翻译 |
|---|---|
| 1044 | 访问被拒绝:当前用户无权访问该数据库 |
| 1045 | 访问被拒绝:用户名或密码错误 |
| 1049 | 数据库不存在 |
| 1054 | 未知列 |
| 1062 | 唯一键冲突(重复插入) |
| 1064 | SQL 语法错误 |
| 1141 / 1142 | 权限不足 |
| 1146 | 表不存在 |
| 1205 | 锁等待超时 |
| 1213 | 死锁,请重试 |
| 2002 | 无法连接到数据库主机(连接被拒绝) |
| 2003 | 无法连接到数据库主机(端口不可达) |
| 2013 | 连接丢失(网络问题或查询超时) |
| ECONNREFUSED | 连接被拒绝:检查 host / port 是否正确,数据库服务是否启动 |
| SQLSTATE | 翻译 |
|---|---|
| 08000 / 08001 / 08003 / 08006 | 连接异常 / 失败 |
| 23502 | 非空约束违反 |
| 23503 | 外键约束违反 |
| 23505 | 唯一键冲突(重复插入) |
| 28P01 | 身份验证失败:用户名或密码错误 |
| 3D000 | 数据库(catalog)不存在 |
| 40P01 | 死锁,请重试 |
| 42501 | 权限不足 |
| 42601 | SQL 语法错误 |
| 42703 | 列不存在 |
| 42P01 | 表或视图不存在 |
| 55P03 | 锁等待超时,请稍后重试 |
| 现象 | 排查 |
|---|---|
| 命令不存在 | npm install -g db-driver 没跑 / PATH 不对 |
| 连接不存在 | db-driver list 看可用 dbId |
| 权限被拒("已被禁用") | db-driver show <dbId> 看实际权限位;错误消息附带 SELECT=... UPDATE=... DELETE=... DDL=...;手动用 db-driver config 调整(不要让 AI 自动调) |
| SELECT 报权限不足但理应通过 | 错误消息会附带当前权限,确认 dmlQuery=true;可能 SQL 被 AST 识别成其他类型(用 --json + node-sql-parser 排查) |
| 表 / 列不存在 | db-driver schema <dbId> --search <keyword> |
| PG schema 找不到表 | db-driver show <dbId> 确认 schema 字段;可用 --schema 临时切换 |
| 列表太多想翻页 | schema / usage list 加 --limit N --offset M |
| 想看 MySQL 分区子表 | schema <dbId> --table <t> --show-partitions |
| 无法解析 SQL | 含注释断字 / 条件注释,已被拒绝(设计如此) |
| 笔记想批量加 dbId | usage bind --add <dbId>(一次性应用到所有笔记) |
| 笔记想单条改 dbId / title | usage update <index> --title ... --dbIds a,b(AI 友好,非阻塞) |
| 进程卡住 | MySQL / PG 连接池问题;db-driver update 拉到最新版试试;npm run dev:stop 清理残留 |
如果由 AI Agent 在调用本工具:
- 禁止自行提升权限 —— 权限被拒时不要自动跑
db-driver config加新权限 - 提权必须用户明确同意 —— 只有用户亲口说"开 XX 权限"才能给新的 config 命令
- 失败立即停下并报告 —— 不要尝试第二条路径蒙混
- 不要直接编辑配置文件 —— 让用户自己用
db-driver config
完整版见 skill/SKILL.md(AI Agent 实际加载的入口)。
db-driver/
├── src/
│ ├── cli.ts # commander 入口
│ ├── commands/ # 每个子命令一个文件
│ │ ├── config.ts # 配置(Web + CLI 双模式)
│ │ ├── list/show/test/remove.ts # 连接管理
│ │ ├── schema/sample/count.ts # 数据浏览
│ │ ├── execute.ts # SQL 执行 + AST 权限校验
│ │ ├── explain.ts # EXPLAIN / EXPLAIN ANALYZE
│ │ ├── export.ts / import.ts # 加密导出导入
│ │ ├── usage.ts # 用法笔记
│ │ └── install/update.ts # skill 安装 / npm 自更新
│ ├── db/
│ │ ├── index.ts # DbDriver 接口 + createDriver 工厂
│ │ ├── mysql.ts # MySQL 实现(mysql2/promise)
│ │ ├── postgres.ts # PostgreSQL 实现(pg.Client)
│ │ ├── pool.ts # 进程内连接池(30s TTL)
│ │ ├── permissions.ts # AST 解析 + 权限校验
│ │ └── types.ts # DbConnectionConfig 等共享类型
│ ├── store/
│ │ ├── configStore.ts # AES-256-GCM 加密连接配置
│ │ └── usageStore.ts # 用法笔记(明文 SQLite)
│ ├── utils/
│ │ ├── paths.ts # 配置 / skill 路径
│ │ ├── crypto.ts # AES-256-GCM 加解密
│ │ ├── ident.ts # 表名 / 列名引用
│ │ └── errors.ts # 错误码中英文翻译
│ └── web/ # db-driver console 的本地网页(React + Vite)
│ ├── server.ts # 本地 HTTP 服务(连接 + 用法 API)
│ ├── index.html
│ └── src/ # React 组件
├── skill/SKILL.md # AI Agent 看到的入口
├── README.md / README.en.md # 本文件 / English version
└── AGENTS.md # 架构与规范(给后续贡献者)
git clone https://github.com/668mt/db-driver.git
cd db-driver
npm install
npm run build # 编译到 dist/
npm link # 全局链接 → db-driver 命令可用修改代码后必跑:
npm run build # 编译
db-driver install # 同步 skill(命令改了必跑)完整规范见 AGENTS.md。
# 改版本 + 编译 + 发布
npm run release:patch # 0.1.0 → 0.1.1
# 或 minor / major
# 推送代码 + tag
git push --follow-tags发布后用户用 db-driver update 升级。
欢迎 PR / Issue:
- 🐛 Bug 报告:附上
db-driver --version、复现命令、完整错误输出 - 💡 功能建议:先在 Issue 里讨论设计,避免 PR 方向跑偏
- 🔧 代码提交:改动后跑
npm run build+db-driver install,更新 README / SKILL.md / AGENTS.md
完整流程见 AGENTS.md(含发布到 npm 的步骤)。
MIT © 668mt — see package.json ("license": "MIT")