db-readonly-mcp
db-readonly-mcp
一个 MCP 服务器,为 AI 助手(Claude Code、Claude Desktop 或任何其他 MCP 客户端)提供受保护的、只读的 Postgres 数据库访问。例如,你可以问"帮我查一下昨天创建的所有商家",助手会编写 SQL 并通过此服务器执行,服务器会强制保证查询只能读取数据。
仅支持 Postgres——不支持其他数据库。
为什么存在
让助手直接查询你的数据库,对于调试、数据探索以及回答"有多少 X"这类问题非常实用,无需每次都编写脚本。风险显而易见:LLM 可能会产生幻觉或被诱导编写破坏性查询。此服务器的存在就是为了将这种风险降到接近于零,通过多层独立的保护机制,而不是依赖任何单一措施。
Related MCP server: Postgres Scout MCP
安全模型
分层设计,按实际信任程度排序:
数据库角色——连接使用一个专用的 Postgres 角色,仅授予
SELECT权限。 这是真正的边界:即使其他所有层都被绕过,该角色也无法写入。查询验证——拒绝任何不是单一
SELECT/WITH ... SELECT语句的内容(不允许分号堆叠的语句,不允许 DDL/DML 关键字)。强制
LIMIT——每个查询都被包装为SELECT * FROM (...) LIMIT N,无论请求多少,上限均为MAX_LIMIT。statement_timeout——查询在STATEMENT_TIMEOUT_MS之后会被终止。启动日志——启动时向 stderr 记录所连接的数据库/用户,以便在任何查询运行之前清楚地知道当前指向的是哪个数据库。
请务必将此服务器仅指向开发/测试/预发布数据库——切勿指向生产环境。 第 2-5 层是纵深防御;第 1 层(数据库角色)才是唯一真正应该信任的层,即便如此,也不应让它接触生产数据。
环境要求
Node.js >= 20
一个可以创建角色的 Postgres 数据库
一个 MCP 客户端(例如 Claude Code、Claude Desktop,或任何其他支持通过 stdio 使用 MCP 服务器的客户端)
安装
1. 克隆并安装
git clone https://github.com/david-mogbeyi/db-readonly-mcp.git
cd db-readonly-mcp
npm install2. 创建只读角色
针对目标 Postgres 数据库执行以下命令——如果你的应用使用的不是 public,请替换角色名、密码、数据库名以及 schema/owner:
CREATE ROLE myapp_readonly WITH LOGIN PASSWORD '<choose-a-password>';
GRANT CONNECT ON DATABASE myapp TO myapp_readonly;
GRANT USAGE ON SCHEMA public TO myapp_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO myapp_readonly;
-- Keeps future tables (new migrations) readable automatically, without
-- re-running this grant every time the schema changes.
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO myapp_readonly;如果你的 schema 不是 public,或者有多个 schema,请为每个 schema 重复 GRANT USAGE/GRANT SELECT/ALTER DEFAULT PRIVILEGES 这几行。此服务器目前仅对 public schema 执行 list_tables/describe_table 查询,但 query_readonly 可以引用该角色已被授予访问权限的任何 schema。
3. 配置
cp .env.example .env编辑 .env,将 DATABASE_URL 设置为只读角色的连接字符串:
DATABASE_URL=postgresql://myapp_readonly:<password>@localhost:5432/myapp其他变量请参阅下面的配置部分。
4. 构建
npm run build这会通过 tsc 将 src/ 编译到 dist/。拉取更新或编辑源码后请重新运行。
注册到 MCP 客户端
Claude Code
在你想查询的项目中,添加一个 .mcp.json(或编辑现有的):
{
"mcpServers": {
"db-readonly": {
"command": "node",
"args": ["/absolute/path/to/db-readonly-mcp/dist/index.js"],
"env": {
"DATABASE_URL": "postgresql://myapp_readonly:<password>@localhost:5432/myapp"
}
}
}
}将 /absolute/path/to/db-readonly-mcp 替换为你克隆此仓库的位置。重启 Claude Code(或重新连接 MCP 服务器)以使其生效。
你也可以将其注册为全局而非按项目——有关 claude mcp add 及作用域选项,请参阅 Claude Code MCP 文档。
Claude Desktop / 其他 MCP 客户端
任何支持通过 stdio 使用 MCP 服务器的客户端都可以以相同方式使用此服务器:将其指向 node /absolute/path/to/db-readonly-mcp/dist/index.js,并在其环境中设置 DATABASE_URL(以及可选的其他环境变量)。有关 MCP 服务器配置存放位置,请参阅客户端的文档——对于 Claude Desktop,配置文件为 claude_desktop_config.json,使用与上述相同的 command/args/env 结构。
配置
所有配置均通过环境变量完成(本地运行时在 .env 中设置,或在 MCP 客户端配置的 env 块中设置)。
变量 | 是否必需 | 默认值 | 描述 |
| 是 | — | 只读角色的 Postgres 连接字符串。 |
| 否 | 100 | 查询未指定时应用的行数限制。 |
| 否 | 1000 | 返回行数的硬性上限,无论请求多少。 |
| 否 | 5000 | 每个查询的 Postgres |
工具
服务器向助手暴露三个工具:
list_tables
列出 public schema 中的表。无参数。
→ [
{ "table_name": "merchants" },
{ "table_name": "orders" },
...
]describe_table(table)
public schema 中某个表的列、类型、可空性和默认值。
{ "table": "merchants" }
→ [
{ "column_name": "id", "data_type": "uuid", "is_nullable": "NO", "column_default": "gen_random_uuid()" },
{ "column_name": "created_at", "data_type": "timestamp with time zone", "is_nullable": "NO", "column_default": "now()" },
...
]query_readonly(sql, limit?)
执行一条受保护的单一 SELECT(或 WITH ... SELECT)语句。limit 为可选参数,即使传入更大的值也会被限制在 MAX_LIMIT 以内。
{ "sql": "SELECT id, name, created_at FROM merchants WHERE created_at > now() - interval '1 day'" }
→ { "rowCount": 3, "rows": [ { "id": "...", "name": "...", "created_at": "..." }, ... ] }任何不是单一 SELECT/WITH 语句的内容——多条语句、DDL、DML、SET 等——都会在到达数据库之前被拒绝,并附上原因说明。
本地开发
npm run dev # runs src/index.ts directly via tsx, loads .env via Node's --env-file项目结构
src/
index.ts # MCP server setup and tool definitions
sqlGuard.ts # query validation (layer 2 of the safety model)
db.ts # Postgres pool setup (statement_timeout, pool size)
config.ts # env var loading/validation故障排查
"DATABASE_URL environment variable is required" ——
.env缺失或未被加载;请确认该文件存在(通过cp .env.example .env创建),并确认你的 MCP 客户端的env块或npm run dev/npm start正在读取它。服务器启动时记录了错误的数据库/用户 —— 检查
DATABASE_URL;启动日志(connected as "..." to database "...")特意打印出来,就是为了在任何查询运行之前便于发现此问题。"Query rejected: ..." —— 查询要么不是单一的
SELECT/WITH语句,要么包含被禁止的关键字。这是安全模型第 2 层在按预期工作,而不是 bug。查询挂起后报错 —— 很可能是触发了
STATEMENT_TIMEOUT_MS;如果你的工作负载确实需要更长时间,可以在.env中调高该值,或者优化查询。
贡献
欢迎提交 Issue 和 PR。这有意保持为一个小型、可审计的工具——目标是让安全模型足够简单、可以完整阅读,而不是将其发展成一个通用的查询构建器。
许可证
This server cannot be deployed
Maintenance
Related MCP Connectors
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Query Postgres, MySQL, SQL Server, Oracle, BigQuery, ClickHouse and Redshift from your AI client.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables AI assistants to interact with PostgreSQL databases using natural language queries, providing secure read-only access to database schemas and SQL translation capabilities.68 npm-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to safely explore, analyze, and maintain PostgreSQL databases with read-only mode by default, SQL injection prevention, query performance analysis, and optional write operations.52 npmApache 2.0
- FlicenseAqualityCmaintenanceEnables read-only exploration of a Postgres database using natural language, with multiple safety layers to prevent any modifications.5-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to query PostgreSQL, inspect schemas, and explain queries, designed for local and development databases with read-only safety by default.42 npmMIT