Skip to main content
Glama
README.md
# sqlmcp — 带 AI 操作审计的 SQL MCP Server

让 AI(MCP 客户端)安全地查询/操作数据库:**每条 SQL 经风险分级,危险操作二次确认,全部动作落防篡改审计链**。

```
AI ──SQL──▶ 风险分级 ──▶ 只读?──执行──┐
                 │                    ├─▶ 结果(含 audit_id)
                 └─ WRITE/DANGER ──▶ confirm_token 两段式确认
                            全程 ──▶ SQLite 审计哈希链(append-only + verify)
```

## 特性

- **风险三级**:`READ` / `WRITE` / `DANGER`(DROP/TRUNCATE/无 WHERE 的 DELETE 等),sqlglot 解析判级
- **两段式确认**:DANGER 操作必须先向用户展示 SQL,拿到 HMAC 签名的 `confirm_token` 才执行,token 5 分钟过期、防重放
- **访问级别**:每库独立配 `read_only` / `read_write_danger`,只读库硬拦截一切写语句
- **防篡改审计**:SQLite 哈希链(每条记录含前条哈希),`audit_verify` 一键验链,改一条即断链
- **密码不落明文**:`master.key`(ACL 限当前用户)+ AES-256-GCM,config 里只有 `enc:v1:…` 密文;`sqlmcp rekey` 一键轮换
- **本地控制台**:`sqlmcp ui` 起配置/审计页面(仅绑 127.0.0.1),可视化编辑配置、查审计、导出 HTML

## 安装

```bash
# 推荐:uvx(无需自装 Python 环境)
uvx --from sqlmcp sqlmcp --help

# 或 pip
pip install sqlmcp            # 核心包
pip install "sqlmcp[mysql]"   # + MySQL 驱动
pip install "sqlmcp[postgres]"# + PostgreSQL 驱动
```

SQLite 零驱动依赖,开箱即用。

## 三步接入

```bash
# 1. 初始化 ~/.sql-mcp/(config 模板 + 审计库 + master.key + token 密钥,ACL 限当前用户)
sqlmcp init

# 2. 编辑配置(或直接用 UI:sqlmcp ui,保存时明文密码自动加密)
#    ~/.sql-mcp/config.json
sqlmcp ui

# 3. 自检(驱动/配置/密钥/审计链全绿即可接入客户端)
sqlmcp doctor
```

配置示例:

```json
{
  "version": 1,
  "databases": {
    "appdb": {
      "type": "mysql", "host": "127.0.0.1", "port": 3306,
      "user": "app", "password": "填明文后由 UI/encrypt 自动加密为 enc:v1:…",
      "database": "appdb", "access": "read_only"
    },
    "scratch": {
      "type": "sqlite", "path": "D:/tmp/scratch.sqlite",
      "access": "read_write_danger",
      "danger_whitelist": []
    }
  },
  "audit": { "max_rows": 1000, "log_results": false },
  "ui": { "port": 7421, "idle_timeout_min": 120 }
}
```

## WorkBuddy 接入

`~/.workbuddy/mcp.json` 添加(**不要**在 env 里放密码):

```json
{
  "mcpServers": {
    "sqlmcp": {
      "command": "uvx",
      "args": ["--from", "sqlmcp", "sqlmcp", "serve"],
      "env": {}
    }
  }
}
```

保存后在连接器管理里信任并启用 `sqlmcp`,对话里即可使用。改过 config 后需重连一次连接器(新配置随新进程生效,审计链 SESSION_START 会记录配置指纹,`sqlmcp doctor` 可核对)。

## MCP 客户端通用接入(非 WorkBuddy)

stdio 协议,任何 MCP 客户端等价配置:

```json
{ "command": "uvx", "args": ["--from", "sqlmcp", "sqlmcp", "serve"] }
```

建议同时给 AI 一段使用规范(复制进 system prompt / 项目约定):

```text
使用 sqlmcp 操作数据库时遵守:
1. 先 list_databases 看可用库,db_name 必须来自该清单,不确定就先查,禁止猜别名;
2. 写操作前先 dry_run 看风险级别;DANGER 级必须先把 SQL 原文展示给用户、
   等用户明确同意后,再走 execute(空 token) → 拿 confirm_token → 带 token 重发;
3. 禁止替用户决定执行危险操作,禁止绕过/猜测 confirm_token;
4. 被拦截(BLOCKED)是安全机制生效,不要重试绕过,向用户说明原因;
5. 结论需要佐证时用 audit_query 拉原始记录,用 audit_verify 自证链完整。
```

## 工具清单(8 个)

| 工具 | 作用 | 备注 |
|------|------|------|
| `list_databases` | 列出已配置库(别名/类型/级别) | 不触库、不写审计 |
| `get_schema` | 库内表清单 / 表结构 | 只读通道 |
| `query` | 只读 SQL(SELECT/SHOW/DESC…) | 经 sqlglot 判级 |
| `execute` | 写 SQL,DANGER 需 confirm_token | 两段式确认 |
| `explain` | 执行计划(不执行内层语句) | 只读通道 |
| `dry_run` | 只判级不执行 | 让 AI 预演 |
| `audit_query` | 审计原始记录查询 | 含完整 SQL 文本 |
| `audit_verify` | 校验审计哈希链 | 返回 ok/count/break_at |

## 安全模型(诚实边界)

**防得住**:配置/日志/环境变量里的明文密码(AES-GCM 密文化);只读库的写操作;DANGER 操作的无确认执行;事后抵赖(哈希链 + 配置指纹)。

**防不住**:与 MCP 同 Windows 账户运行的进程读取 `master.key` 后解密——MCP 必须能解密才能连库,这是能力边界。真要隔离需将 MCP 跑在独立系统账户下。详见 `docs/DESIGN.md` §6。

## CLI

```text
sqlmcp init      # 初始化目录/审计库/配置模板/密钥
sqlmcp ui        # 本地控制台(默认 http://127.0.0.1:7421)
sqlmcp serve     # 启动 MCP stdio 服务(客户端接这个)
sqlmcp doctor    # 自检:驱动/配置/密钥/审计链
sqlmcp rekey     # 轮换 master.key(全量密文重加密,自动备份)
sqlmcp verify    # CLI 校验哈希链
sqlmcp export    # 审计导出自包含 HTML
```

## 开发

```bash
pip install -e ".[mysql]" pytest httpx
pytest tests -q          # 全量测试
python -m build          # 构建产物
```

License: MIT