sql-explorer
sql-explorer
一个 MCP 服务器,让 AI 助手可以用自然语言回答关于 SQLite 数据库的问题——同时既不会损坏数据库,也无法读取你标记为禁止访问的部分。
当被问到 “哪个城市花费最多?” 时,模型会自己发现数据表、读取 schema、编写自己的 SQL,然后给出答案。它永远没有机会去写入、删除或读取被封锁的列。
You: Which city has spent the most in total?
Claude: Lyon, with 14 orders totalling 2,840.03.
You: Give me the email and phone of every customer.
Claude: I can't — the server refuses access to customers.email.为什么存在
把数据库连接交给语言模型确实是一件有风险的事。可能出错的有三种情况:
风险 | 处理方式 |
它执行 | 只接受以 |
它读取个人数据 | SQLite 授权器 在引擎内部拒绝配置过的列 |
它返回数百万行 | 结果最多截断为 500 行,查询超过 5 秒会被中止 |
第二种情况最有趣。被封锁的列不会从 SQL 文本中被过滤掉——SQLite 在读取任何列之前都会询问“可以吗”,而服务器会给出回答。这意味着,即使一个查询从未在 SELECT 中提及 email,却用它作为过滤条件来一次猜一个地泄露地址,同样会被拒绝:
SELECT name FROM customers WHERE email LIKE '%ana%'
-- Query refused: access to customers.email is prohibited没有任何换一种措辞能够绕过它,因为检查看的并不是措辞。
Related MCP server: safe-sql-mcp
快速开始
需要 Python 3.12+ 和 uv。
git clone <your-repo-url>
cd mcp_server
uv sync
uv run python scripts/make_sample_db.py # builds the practice database
uv run pytest # 28 tests要在浏览器里手动手动试一下这些工具(需要 Node.js):
uv run mcp dev src/mcp_server/__init__.py与 Claude Desktop 配合使用
设置 → 开发者 → 编辑配置,然后添加:
{
"mcpServers": {
"sql-explorer": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/mcp_server", "mcp-server"],
"env": {
"SQL_EXPLORER_DB": "/absolute/path/to/your.db",
"SQL_EXPLORER_BLOCKED_COLUMNS": "users.password_hash, users.ssn"
}
}
}
}之后重启应用。在应用运行时编辑文件是没用的——应用退出时会把配置文件覆盖成自己的内容。
配置
变量 | 默认值 | 含义 |
| 本仓库中的 | 要提供数据库的 SQLite 文件 |
|
| 要禁止访问的列,格式为 |
|
|
|
|
| 监听端口,仅 HTTP 传输使用 |
| 无 | HTTP 传输所需的 Bearer 令牌。没有默认值;没有它,服务器就不会启动 |
不是 table.column 形状的值,都会让服务器拒绝启动,通过认证配置中的拼写错误要响亮地暴露出来,而不是被静默忽略。
Include Tools
Tools
list_tables() | 每张数据表的名称 |
| describe_table(table) | 某张表的列信息:名称、类型、是否必填 |
| run_query(sql) | 执行一个 SELECT 并返回列的信息 |
| ping() | 存活检查 |
run_query 在结果数量达到上限时会报告 truncated: true,所以部分结果永远不会被误认为完整结果。
ping() | 存活检查 |
(注意上面表格其实应该只有一个 ping 行,但请按原文保留)
Resources
URI | 内容 |
| 每张表及其列,每行一个 |
| 一张表的详细内容:列名、类型、是否必填 |
服务器拒绝读取的列会被标记为 [blocked]:
customers(id, name, email [blocked], phone [blocked], city, signup_date)这是故意的。这种保护不依赖保密性——授权器无论如何都会拒绝——所以列出被封锁的列毫无成本,反而能省去一次注定会被拒绝的 SELECT *。
schema://{table} 是一个模板:一份定义即可为每张表生成一个地址,无论数据库实际包含哪些表。
Prompts
提示词 | 作用 |
| 分析一张表:大小、分布、缺失、离群值 |
| 检查重复、孤儿记录、不可能的值、可疑的均匀性 |
提示词返回的是指令,而不是数据。它说明如何正确地使用这个服务器——先读 schema,充分聚合而不是逐行列举,不要伸手去取被封锁的列——这样即使一个不熟悉数据库的用户也能提出有价值的问题。
通过网络使用它
默认情况下,服务器运行在 stdio 上:客户端以本地进程方式启动它,双房通过管道通信。它不需要认证,因为操作系统已经决定了谁可以启动这个进程。
如果将 SQL_EXPLORER_TRANSPORT 设置为 streamable-http,它就会变成一个 Web 服务——而任何能访问端口的人都可以与它对话。因此令牌是强制的:
SQL_EXPLORER_TRANSPORT=streamable-http \
SQL_EXPLORER_TOKEN=$(python -c "import secrets; print(secrets.token_urlsafe(32))") \
uv run mcp-server每个请求都必须携带令牌:
curl -X POST http://127.0.0.1:8000/mcp \
-H "Authorization: Bearer $SQL_EXPLORER_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'任何其他东西都会得到 401,并且请求永远不会到达工具、资源或数据库。
如果没有设置 SQL_EXPLORER_TOKEN,服务器会拒绝启动。 它不会退回“开发模式”,也不会悄悄忽略。在监听一个 127.0.0.1 时,编译时要改安全配置之前,先阅读下面的安全说明。
在把它暴露到网络之前
TLS 是不可妥协的。 通过纯 HTTP 发送的 Bearer 令牌,中间任何夹在网络之间的人都可能是明文并重新使用它。请把它放在一个终止 HTTPS 的后者反向代理后面。
一个共享的令牌并不是 OAuth。 根据 MCP 规范,远程服务器要使用 OAuth 2.1,得到用户身份、scopes 和撤销能力。这比一个共享密钥好得多:每个调用者都是同一个人,而轮流用一个密钥,于是所有调用者同时被锁出来。这对于单人尤其可以接受,但对公共部署来说是错误选择。
没有频率限制保障。 这里没有任何机制能阻止某个调用者对着昂贵的查询拼命发送。
不要改动绑定的地址, 默认是
127.0.0.1。如果你改掉它,一定要看到上面的安全风险。
设计说明
为什么 schema 同时提供工具和资源。 dedicated_table 返回结构化后可用于计算的行;schema://customers 返回一个适合人类阅读的页面。相同的信息,两种形态,因为工具和资源的消费方式不同。工具也是更可靠的方式,因为客户端对资源的支持各不相同。
为什么拒绝 SELECT *。 它会被展开成具体列,其中包含被封锁的列,于是授权器会拒绝它。模型只能请求自己想要的列。这会让模型多干一点点,但绝不会造成意外泄漏。
为什么 describe_table 会直接处理参数。 PRAGMA table_info 不能接受绑定参数,所以表名必须先通过真实表列表的校验后再直接拼进语句,专家处理,而不是信任用户的输入。这是一种白名单,而不是 scape 暴露。
注意: PRAGMA table_info 不能接受绑定参数,所以需要把表名插入语句中——但会在拼进去之前先检查它是否出现在真实表清单里。这是白名单,不是转义。
限制
仅支持 SQLite。SQLite 的授权器是它独有的特性,而 PostgreSQL 或 MySQL 没有任何 columnauthorizer 机制,需要另外的方法。
屏蔽的是列而非行,无法配置“只允许用户的那几行”。
5 秒超时是墙钟时间,不是 CPU 时间。
运行测试
uv run pytest -v三个文件中共有 28 个测试。
tests/test_guards.py覆盖了所有安全护栏:被拒绝的语句、被拒绝的列(包括过滤/不去、只过滤的泄漏攻击)、截断、未知表名、查询超时。tests/test_resources_and_prompts.py覆盖了 resources 和 prompts,以及被封锁列的[blocked]标记,测试只覆盖它们不被修改。tests/test_http_auth.py覆盖了 HTTP 认证:正确的令牌通过,缺少 header、错误令牌、没有 Bearer 前缀的令牌、不完整的令牌都被拒绝,而且服务器在 http 模式且没有 token 时拒绝启动。每个拒绝都断言没有到达上节点,而不仅是最终状态码401。tests/conftest.py如果 sample database 缺失则会创建它,保证测试可以在一份新 clone 中运行。
“防护网测试”和“资源”这两类测试直接调用服务器的函数,而不是通过 MCP 会话,这意味着它们并不会捕获到一个被删除的 @decorator。
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables safe, read-only SQL access to SQLite databases for AI agents, allowing schema exploration and SELECT queries with defense-in-depth protections.3MIT
- FlicenseNot gradedqualityCmaintenanceEnables read-only SQL database access for AI assistants, allowing schema exploration and safe query execution without risk of data modification.
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to query SQL databases safely with read-only access, allowing schema discovery and SELECT queries while blocking writes and DDL operations.
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to explore and query SQLite databases through read-only tools, with defense-in-depth sandboxing preventing any data modifications.MIT
Related MCP Connectors
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Explore, query, and inspect SQLite databases with ease. List tables, preview results, and view det…
Read-only bank access for your AI agent. Connects Claude, ChatGPT, Cursor, Gemini, Codex.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ccervantes369/mcp-sql-explorer'
If you have feedback or need assistance with the MCP directory API, please join our Discord server