Skip to main content
Glama
david-mogbeyi

db-readonly-mcp

db-readonly-mcp

一个 MCP 服务器,为 AI 助手(Claude Code、Claude Desktop 或任何其他 MCP 客户端)提供受保护的、只读的 Postgres 数据库访问。例如,你可以问"帮我查一下昨天创建的所有商家",助手会编写 SQL 并通过此服务器执行,服务器会强制保证查询只能读取数据。

仅支持 Postgres——不支持其他数据库。

为什么存在

让助手直接查询你的数据库,对于调试、数据探索以及回答"有多少 X"这类问题非常实用,无需每次都编写脚本。风险显而易见:LLM 可能会产生幻觉或被诱导编写破坏性查询。此服务器的存在就是为了将这种风险降到接近于零,通过多层独立的保护机制,而不是依赖任何单一措施。

Related MCP server: Postgres Scout MCP

安全模型

分层设计,按实际信任程度排序:

  1. 数据库角色——连接使用一个专用的 Postgres 角色,仅授予 SELECT 权限。 这是真正的边界:即使其他所有层都被绕过,该角色也无法写入。

  2. 查询验证——拒绝任何不是单一 SELECT/WITH ... SELECT 语句的内容(不允许分号堆叠的语句,不允许 DDL/DML 关键字)。

  3. 强制 LIMIT——每个查询都被包装为 SELECT * FROM (...) LIMIT N,无论请求多少,上限均为 MAX_LIMIT。

  4. statement_timeout——查询在 STATEMENT_TIMEOUT_MS 之后会被终止。

  5. 启动日志——启动时向 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 install

2. 创建只读角色

针对目标 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 块中设置)。

变量

是否必需

默认值

描述

DATABASE_URL

是

—

只读角色的 Postgres 连接字符串。

DEFAULT_LIMIT

否

100

查询未指定时应用的行数限制。

MAX_LIMIT

否

1000

返回行数的硬性上限,无论请求多少。

STATEMENT_TIMEOUT_MS

否

5000

每个查询的 Postgres statement_timeout,单位毫秒。

工具

服务器向助手暴露三个工具:

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。这有意保持为一个小型、可审计的工具——目标是让安全模型足够简单、可以完整阅读,而不是将其发展成一个通用的查询构建器。

许可证

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to interact with PostgreSQL databases using natural language queries, providing secure read-only access to database schemas and SQL translation capabilities.
    6
    8 npm
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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 npm
    Apache 2.0
  • F
    license
    A
    quality
    C
    maintenance
    Enables read-only exploration of a Postgres database using natural language, with multiple safety layers to prevent any modifications.
    5
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to query PostgreSQL, inspect schemas, and explain queries, designed for local and development databases with read-only safety by default.
    42 npm
    MIT