Skip to main content
Glama
ccervantes369

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.

为什么存在

把数据库连接交给语言模型确实是一件有风险的事。可能出错的有三种情况:

风险

处理方式

它执行 DELETEUPDATEDROP

只接受以 SELECT 开头的语句

它读取个人数据

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"
      }
    }
  }
}

之后重启应用。在应用运行时编辑文件是没用的——应用退出时会把配置文件覆盖成自己的内容。

配置

变量

默认值

含义

SQL_EXPLORER_DB

本仓库中的 sample.db

要提供数据库的 SQLite 文件

SQL_EXPLORER_BLOCKED_COLUMNS

customers.email, customers.phone

要禁止访问的列,格式为 table.column,逗号分隔

SQL_EXPLORER_TRANSPORT

stdio

stdiostreamable-http

SQL_EXPLORER_PORT

8000

监听端口,仅 HTTP 传输使用

SQL_EXPLORER_TOKEN

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

内容

schema://tables

每张表及其列,每行一个

schema://{table}

一张表的详细内容:列名、类型、是否必填

服务器拒绝读取的列会被标记为 [blocked]

customers(id, name, email [blocked], phone [blocked], city, signup_date)

这是故意的。这种保护不依赖保密性——授权器无论如何都会拒绝——所以列出被封锁的列毫无成本,反而能省去一次注定会被拒绝的 SELECT *

schema://{table} 是一个模板:一份定义即可为每张表生成一个地址,无论数据库实际包含哪些表。

Prompts

提示词

作用

analyze_table(table)

分析一张表:大小、分布、缺失、离群值

data_quality_report()

检查重复、孤儿记录、不可能的值、可疑的均匀性

提示词返回的是指令,而不是数据。它说明如何正确地使用这个服务器——先读 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。

Install Server
F
license - not found
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables read-only SQL database access for AI assistants, allowing schema exploration and safe query execution without risk of data modification.
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to query SQL databases safely with read-only access, allowing schema discovery and SELECT queries while blocking writes and DDL operations.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to explore and query SQLite databases through read-only tools, with defense-in-depth sandboxing preventing any data modifications.
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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