sqlglot MCP server
Provides SQL parsing, transpilation, formatting, extraction, and condition injection via MCP protocol, enabling agents to validate, analyze, and transform SQL.
README
SQL 解析 API 服务(REST / HTTP)
基于 sqlglot 的 SQL 解析 / 转译 / 格式化 / 提取 /
条件注入服务,使用 FastAPI 暴露为 REST 接口。核心逻辑在 core.py,被本服务(HTTP)复用。
运行
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
启动后访问交互式文档:http://localhost:8000/docs
服务默认开启 CORS(allow_origins=["*"]),便于前端跨域调用。
接口总览
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /health |
健康检查,返回 sqlglot 版本 |
| GET | /dialects |
列出 sqlglot 支持的所有方言 |
| POST | /parse |
将 SQL 解析为结构化 AST(JSON) |
| POST | /transpile |
在方言之间互转 SQL(如 MySQL → PostgreSQL) |
| POST | /format |
美化 / 标准化 SQL |
| POST | /validate |
校验 SQL 语法是否合法(不抛异常) |
| POST | /extract |
提取表名、列名、函数、CTE 及别名映射 |
| POST | /add_condition |
追加 WHERE 条件(自动别名,支持多表 / 多条件 / 多操作符 / 直拼原始 SQL) |
所有接口在 SQL 解析 / 处理失败时会返回 400,错误信息在响应体 detail 字段中。
接口详情
1. 健康检查 GET /health
返回服务状态与 sqlglot 版本号。
curl http://localhost:8000/health
# {"status":"ok","sqlglot_version":"30.12.0"}
2. 方言列表 GET /dialects
返回 sqlglot 支持的全部方言名称(按字母序)。
curl http://localhost:8000/dialects
# {"dialects":["bigquery","clickhouse","mysql","postgres", ...]}
3. 解析为 AST POST /parse
请求体:
| 字段 | 类型 | 说明 |
|---|---|---|
sql |
string | 待解析的 SQL |
read |
string? | 输入方言,留空自动识别 |
pretty |
bool | AST 是否美化输出(默认 true) |
curl -X POST http://localhost:8000/parse \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT a, b FROM t WHERE a > 1"}'
# {"sql":"...","dialect":null,"ast":"SELECT a, b FROM t WHERE a > 1","json":{...}}
返回含 sql / dialect / ast / json 四个字段,其中 json 为 AST 的树形结构。
4. 方言转译 POST /transpile
| 字段 | 类型 | 说明 |
|---|---|---|
sql |
string | 待转译的 SQL |
read |
string? | 输入方言,留空自动识别 |
write |
string | 目标方言(必填) |
curl -X POST http://localhost:8000/transpile \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT IFNULL(a, 0) FROM t", "write": "postgres"}'
# {"read":null,"write":"postgres","sql":"SELECT IFNULL(a, 0) FROM t","transpiled":"SELECT COALESCE(a, 0) FROM t"}
5. 格式化 POST /format
| 字段 | 类型 | 说明 |
|---|---|---|
sql |
string | 待格式化的 SQL |
read |
string? | 输入方言,留空自动识别 |
write |
string? | 输出方言,默认与输入一致(可顺带转译) |
curl -X POST http://localhost:8000/format \
-H "Content-Type: application/json" \
-d '{"sql": "select a,b from t where a>1"}'
# {"sql":"select a,b from t where a>1","formatted":"SELECT a, b\nFROM t\nWHERE a > 1"}
6. 语法校验 POST /validate
| 字段 | 类型 | 说明 |
|---|---|---|
sql |
string | 待校验的 SQL |
read |
string? | 输入方言,留空自动识别 |
返回不抛异常,valid 为布尔,error 在合法时为 null。
curl -X POST http://localhost:8000/validate \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT a FROM t"}'
# {"valid":true,"error":null}
7. 提取元数据 POST /extract
| 字段 | 类型 | 说明 |
|---|---|---|
sql |
string | 待分析的 SQL |
read |
string? | 输入方言,留空自动识别 |
返回字段:
| 字段 | 说明 |
|---|---|
tables |
真实表名(已剔除 CTE 名) |
columns |
带表限定符的列名,如 t1.id |
columns_bare |
裸列名(不含来源),如 id |
functions |
函数调用文本 |
ctes |
CTE 别名 |
table_aliases |
FROM/JOIN 上的显式别名映射 [{alias, table}] |
cte_sources |
CTE 名 → 内部真实表映射 [{cte, tables}] |
curl -X POST http://localhost:8000/extract \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT a, b FROM t1 JOIN t2 ON t1.id = t2.id"}'
# {"tables":["t1","t2"],"columns":["a","b","t1.id","t2.id"],
# "columns_bare":["a","b","id"],"functions":[],"ctes":[],
# "table_aliases":[],"cte_sources":[]}
8. 追加条件 POST /add_condition
为 SQL 追加 WHERE 条件,支持 多表 / 多条件 / 多操作符 / 直拼原始 SQL。自动定位每个真实表在 SQL 中的引用名(别名优先),把裸列或真实表名限定列改写为别名前缀后,注入到「该表所属查询的作用域」。
提供三种入参方式(互斥,优先级:conditions > raw > 兼容旧版):
方式一 · 结构化(推荐,支持多表 + 多操作符) — 字段 conditions 为条件数组,每个元素:
| 字段 | 类型 | 说明 |
|---|---|---|
column |
string | 列名,可带引用前缀,如 "status" 或 "t1.id" |
op |
string | 操作符,默认 =。支持 = != > >= < <= LIKE IN NOT IN BETWEEN IS NULL IS NOT NULL |
value |
any? | 比较值;IN / NOT IN 用列表,BETWEEN 用 [下限, 上限] 两元素列表,IS NULL 可省略 |
table |
string? | 可选,条件所属真实表名(多表场景);跨表 JOIN 条件留空,注入顶层查询 |
combine |
string | 与上一条条件的连接符 AND(默认)或 OR |
curl -X POST http://localhost:8000/add_condition \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT a FROM table1 AS t1 JOIN table2 AS t2 ON t1.id = t2.id WHERE t1.flag = 0",
"conditions": [
{"column": "status", "op": "=", "value": 1, "table": "table1", "combine": "AND"},
{"column": "amount", "op": ">", "value": 100, "table": "table1"},
{"column": "id", "op": "IN", "value": [1, 2, 3], "table": "table2", "combine": "OR"},
{"column": "t1.id", "op": "=", "value": "t2.fid"}
]
}'
# SELECT a FROM table1 AS t1 JOIN table2 AS t2 ON t1.id = t2.id
# WHERE t1.flag = 0 AND (((t1.status = 1 AND t1.amount > 100) OR t2.id IN (1, 2, 3)) AND t1.id = 't2.fid')
方式二 · 直拼原始 SQL(自动把真实表名替换为别名) — 字段 raw,直接写 WHERE 片段(用真实表名),系统自动改写为别名后注入:
| 字段 | 类型 | 说明 |
|---|---|---|
raw |
string | string[] | 原始 WHERE 片段(用真实表名写);多条按 operator 合并 |
operator |
string | 多 raw 片段之间的合并方式,AND(默认)或 OR |
read |
string? | 输入方言,留空自动识别 |
# 片段里用真实表名 table1 / table2 写,自动替换为别名 t1 / t2
curl -X POST http://localhost:8000/add_condition \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT a FROM table1 AS t1 JOIN table2 AS t2 ON t1.id = t2.id WHERE t1.flag = 0",
"raw": "table1.status = 1 AND table2.amount > 100"}'
# SELECT a FROM table1 AS t1 JOIN table2 AS t2 ON t1.id = t2.id
# WHERE t1.flag = 0 AND (t1.status = 1 AND t2.amount > 100)
# 多条 raw 片段按 operator 合并
curl -X POST http://localhost:8000/add_condition \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT a FROM table1 AS t1",
"raw": ["table1.status = 1", "table1.deleted_at IS NULL"], "operator": "OR"}'
# SELECT a FROM table1 AS t1 WHERE table1.status = 1 OR table1.deleted_at IS NULL
方式三 · 兼容旧版(单表 + 原始条件串):
| 字段 | 类型 | 说明 |
|---|---|---|
sql |
string | 原始 SQL |
table |
string | 真实表名(非别名),用于定位引用名 |
condition |
string | string[] | 条件片段;单条字符串或字符串数组(多条件) |
operator |
string | 多条件合并方式,AND(默认)或 OR |
read |
string? | 输入方言,留空自动识别 |
curl -X POST http://localhost:8000/add_condition \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT a FROM table1 AS t1", "table": "table1",
"condition": ["status = 1", "amount > 100"], "operator": "AND"}'
# SELECT a FROM table1 AS t1 WHERE t1.status = 1 AND t1.amount > 100
选型建议:
- 需要精确控制多表分作用域和每个条件的操作符 → 用
conditions(方式一)。 - 已有现成的 WHERE 片段(用真实表名写)想直接拼上去 → 用
raw(方式二)。 - 老接口 / 单表简单场景 → 用
table+condition(方式三)。
行为说明:
- 自动建立「真实表名 → 别名」映射;
raw直拼片段里用真实表名写的列(如table1.status)会自动改写为别名(t1.status)。 - 裸列自动加引用名前缀(
status = 1→t1.status = 1);列已带前缀(如t1.id)则原样保留。 - 多表:条件按
table定位到各自所属查询作用域;表位于子查询 / CTE 内部时,条件只注入到那一层。所有表在同一查询(如 JOIN)时,条件合并进同一 WHERE。raw片段若跨多表,注入到这些表的最近公共查询作用域。 - 多操作符:除
AND/OR连接符外,每个条件自带op(IN/BETWEEN/LIKE/IS NULL等)。 - 同一作用域内多条件按各自
combine从左到右联结;若目标查询已有 WHERE,则与原有条件AND合并。 - 同一真实表在 SQL 中出现多次时取第一个匹配;找不到表 / 操作符不合法 / SQL 解析失败时返回
400错误。
错误处理
所有接口在 SQL 解析 / 处理失败时会返回 HTTP 400,错误信息位于响应体的 detail 字段:
{ "detail": "解析失败: ..." }
常见错误与含义:
detail 片段 |
含义 |
|---|---|
解析失败: ... |
输入 SQL 或条件片段无法被 sqlglot 解析(语法错误) |
未在 SQL 中找到表: xxx |
table / conditions[].table 指定的真实表在 SQL 中不存在 |
条件不能为空 |
传入的 condition / raw 为空 |
不支持的合并方式: xxx |
operator 不是 AND / OR |
不支持的操作符: xxx |
conditions[].op 不在支持的操作符列表内 |
IN 操作符的 value 必须为列表 |
使用 IN / NOT IN 时 value 不是数组 |
BETWEEN 操作符的 value 必须为包含 [下限, 上限] 的列表 |
使用 BETWEEN 时 value 不是两元素数组 |
提示:
/validate接口不会抛异常,可通过其valid/error字段预先判断 SQL 是否合法,再调用其它写操作接口。
MCP 服务(供 Agent 调用)
除了 REST 接口,本服务还提供 MCP Server(mcp_server.py),让 Agent 通过 MCP 协议(stdio 传输)直接调用 SQL 解析/校验/权限能力。
特点:零额外依赖,仅依赖 sqlglot(未使用官方 mcp SDK 分叉包,避免版本/兼容风险),通过标准「换行分隔的 JSON-RPC 2.0」与任何 MCP 客户端(Claude Desktop、自定义 Agent 等)对接。
运行(Agent 以子进程方式拉起):
python mcp_server.py
暴露的工具
| 工具 | 说明 |
|---|---|
validate_sql |
校验 SQL 语法是否合法,返回 {valid, error}(不抛异常) |
parse_sql |
将 SQL 解析为结构化 AST(JSON) |
transpile_sql |
方言互转(如 MySQL → PostgreSQL) |
format_sql |
美化 / 标准化 SQL |
extract_sql |
提取表名、列名、函数、CTE 及别名映射 |
add_condition |
追加 WHERE 条件(多表 / 多条件 / 多操作符 / 直拼原始 SQL) |
check_permission |
按策略校验 SQL(表/列白黑名单、禁止 DML/DDL 等),仅校验不改写 |
enforce_permission |
校验通过后自动加固 SQL(注入行级过滤、自动补 LIMIT),返回改写结果 |
权限策略(policy)
check_permission / enforce_permission 共用如下策略(全部可选):
| 字段 | 类型 | 说明 |
|---|---|---|
allow_write |
bool | 是否允许 DML(INSERT/UPDATE/DELETE),默认 false |
allow_ddl |
bool | 是否允许 DDL(CREATE/DROP/ALTER/TRUNCATE),默认 false |
allowed_tables |
list | 表白名单(非空时,不在其中的表一律拒绝) |
denied_tables |
list | 表黑名单(命中即拒绝,优先级高于白名单) |
allowed_columns |
dict | 列级白名单 {表: [列,...]}(仅校验带表限定符的列) |
row_filters |
dict | 行级过滤 {表: "条件"},enforce_permission 自动注入 WHERE |
max_limit |
int | SELECT 自动补 LIMIT 上限(无 LIMIT 时) |
enforce_permission 示例(enforce_permission 工具):
{
"sql": "SELECT id, amount FROM orders",
"policy": {
"allow_write": false,
"row_filters": { "orders": "tenant_id = 7" },
"max_limit": 100
}
}
→ 返回 SELECT id, amount FROM orders WHERE tenant_id = 7 LIMIT 100(行级隔离 + 限流已自动生效)。
Agent 接入配置示例
Claude Desktop / 兼容 MCP 的客户端(claude_desktop_config.json):
{
"mcpServers": {
"sqlglot": {
"command": "python",
"args": ["/绝对路径/mcp-sqlglot/http/mcp_server.py"]
}
}
}
自定义 Agent(stdio 调用骨架):向子进程 stdin 逐行写入 JSON-RPC 消息,读取 stdout 每行响应:
→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"agent","version":"1"}}}
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"sqlglot-mcp","version":"1.0.0"}}}
→ {"jsonrpc":"2.0","id":2,"method":"tools/list"}
→ {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"enforce_permission","arguments":{"sql":"SELECT * FROM orders","policy":{"row_filters":{"orders":"tenant_id = 7"},"max_limit":100}}}}
http/
├── main.py # FastAPI 应用与全部 REST 接口
├── mcp_server.py # MCP Server(stdio JSON-RPC,供 Agent 调用,零额外依赖)
├── core.py # 核心逻辑(解析/转译/格式化/提取/条件注入/权限校验)
├── requirements.txt # 依赖(fastapi, uvicorn, sqlglot, pydantic, ...)
└── README.md # 本文档
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。