mcpField
P
Postgres (read-only transactions)

Postgres (read-only transactions)

本地服务
github.com/Poudel0数据库16 天前更新

关于 Postgres (read-only transactions)

postgres-mcp-safe 是面向 AI 工具的 Postgres MCP 服务,可查询数据库、读取结构并解释查询。它以数据库强制的只读事务和调用限制,替代已弃用的 server-postgres。

主要功能

  1. 01只读 SQL 查询
  2. 02浏览表与视图
  3. 03查看列、约束和索引
  4. 04解释查询计划
  5. 05限制超时、行数和字节数

适用场景

  1. 01安全地检查生产数据库
  2. 02查找表结构与索引信息
  3. 03分析查询执行计划

MCP 相关

它向 MCP 客户端提供 query、list_tables、describe_table 和 explain 工具,以及 schema 资源。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"poudel0-postgres-mcp-safe": {
"command": "npx",
"args": [
"-y",
"postgres-mcp-safe"
]
}
}
}
启动命令npx -y postgres-mcp-safe

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmpostgres-mcp-safe0.1.3
ocighcr.io/poudel0/postgres-mcp-safe:0.1.3

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

postgres-mcp-safe

已弃用的 @modelcontextprotocol/server-postgres 的即插即用替代品,但它真正只读。

让 AI 工具(Claude、Cursor、Zed 等)查询 Postgres 数据库、读取其架构并解释查询。只需在 MCP 配置中替换包名,其他内容保持不变。

npm ci

Postgres(只读事务)MCP 服务

从 server-postgres 迁移

 {
   "mcpServers": {
     "postgres": {
       "command": "npx",
-      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"]
+      "args": ["-y", "postgres-mcp-safe", "postgresql://localhost/mydb"]
     }
   }
 }

Docker:docker run -i --rm ghcr.io/poudel0/postgres-mcp-safe postgresql://host.docker.internal:5432/mydb。 Linux、macOS 和 Windows 的二进制文件可在发布页面获取。

**有一点需要注意:**如果你的 URL 使用超级用户登录(例如 Docker 默认的 postgres 用户),每次调用都会被拒绝,除非你创建只读角色(推荐),或在 URL 前添加 --allow-superuser。超级用户可以绕过只读事务,因此我们不会声称它能保证只读。

旧服务的 query 工具和 postgres://.../<table>/schema 资源用法保持不变。小幅且有意的变更请参阅差异。

原因

旧服务的“只读”模式可以通过 COMMIT; DROP TABLE ... 绕过 (Datadog Security Labs,2025-08-21)。 上游已合并修复,但从未发布;该软件包已弃用,也没有官方继任者。

标志

标志必须放在 URL 之前。

标志默认值
--timeout30s每次调用的时间限制。
--max-rows1000每次调用返回的行数。超出的行会被截断,并附带说明。
--max-bytes262144每次调用返回的 JSON 字节数上限,也是单行的最大大小。
--allow-explain-analyze关闭允许 explain 执行 EXPLAIN ANALYZE,这会执行查询。
--allow-superuser关闭允许使用超级用户角色或其成员身份。此时无法保证只读。

每次调用都会建立一个新连接(这是安全模型的一部分)。通过 TLS 连接远程数据库时,这需要几次往返:在 50 ms 延迟下,每次调用约需 0.5 s。在 Postgres 17+ 上,可在 URL 中添加 sslnegotiation=direct,减少一次往返。

限制无法关闭;0 会报错。URL 也可以使用关键字 DSN(host=db dbname=app),并且会像 libpq 一样读取标准的 PG* 环境变量(PGPASSWORD 等)。

工具

工具输入
querysql一条只读语句。返回 JSON 行数组。
list_tablesschema?包含架构和类型的表及视图。
describe_tabletable、schema?(public)列、约束和索引。
explainsql、analyze?查询计划。analyze 需要 --allow-explain-analyze。

如何强制实施只读

由 Postgres 强制实施,而不是由 SQL 解析器。每次调用都会:

  1. 打开一个全新连接(调用之间不会保留会话状态),并启动一个 READ ONLY 事务。
  2. 将你的 SQL 作为单条协议级 Parse 消息发送。Postgres 会在此处拒绝多条语句,因此 COMMIT; ... 会在执行任何操作前失败。
  3. 仅在 Postgres 确认语句会返回行时才执行。COMMIT、SET、DO、COPY、CALL、PREPARE 等 都会被拒绝,不会执行。
  4. 应用 statement_timeout、客户端截止时间,以及行数和字节数上限。
  5. 关闭连接,从而结束事务。

bypass suite 会针对真实数据库运行所有已知负载,并在每次运行后检查金丝雀表:

负载结果
COMMIT; DROP SCHEMA public CASCADE;已拒绝:多条语句
COMMIT / SET TRANSACTION READ WRITE / DO $$...$$ / CALL p()已拒绝:不会返回行
COPY (SELECT 1) TO PROGRAM '...'(以超级用户身份)已拒绝:不会返回行
DELETE ... RETURNING * / WITH d AS (DELETE ...) SELECT ...只读事务错误
SELECT nextval('s')只读事务错误
SELECT set_config('transaction_read_only','off',true)错误
SELECT pg_sleep(600),即使在其后调用 set_config('statement_timeout','0')在 --timeout 时取消
SELECT pg_advisory_lock(1)调用结束时释放
SELECT generate_series(1,10000000) / repeat('x', 10000000)达到上限/被拒绝,内存占用保持有界
带有 ANALYZE SELECT ... 的 explain语法错误:无法夹带 ANALYZE

发现绕过方式?请提交 issue。修复前,它会先成为一条测试用例。

同时使用只读角色

此服务会在事务级别让每次调用保持只读。有些操作不受事务限制,只有数据库角色才能阻止它们:

  • dblink_exec(...) 会打开一个独立会话,该会话不是只读的。
  • pg_terminate_backend(...) 会终止其他连接。
  • 超级用户可以读取服务器文件(pg_read_file、pg_ls_dir):只读会阻止写入,不会阻止读取。
  • 即使在只读事务中,超级用户也可以使用 lo_export 写入服务器文件。

因此,请使用仅具备读取权限的角色连接:

CREATE ROLE mcp_ro LOGIN PASSWORD '...';
GRANT pg_read_all_data TO mcp_ro;                     -- PG 14+; or GRANT SELECT on what it needs
ALTER ROLE mcp_ro SET default_transaction_read_only = on;

由于上述最后两项,除非传入 --allow-superuser,否则服务会拒绝超级用户角色及其成员。

与 server-postgres 的差异

  1. 工具调用中的错误会作为工具结果返回,并带有 isError: true、Postgres 消息和 SQLSTATE,以便模型修正 SQL。旧版服务返回的是 JSON-RPC 错误。
  2. resources/read 只会按列顺序显示 public 表的列。旧版会混入其他 schema 中同名表的列。
  3. 资源 URI 中经过百分号编码的表名会被解码(旧版服务不会匹配它们)。
  4. 值采用 Postgres 的打印形式,并在类型明确时保留类型:布尔值、数字(包括 bigint 和 numeric)及 json 都是 JSON 值;其他所有值都是字符串,例如 "2026-01-02 03:04:05+00"、"\\x0102" 或 "{x,y}"。NaN 会表示为 "NaN"(旧版服务返回 null)。
  5. 不返回行的语句(SET、DO、COPY 等)会被拒绝。旧版服务会执行这些语句并返回 []。

开发

docker run -d --name pg-mcp-test -e POSTGRES_PASSWORD=postgres -p 127.0.0.1:5434:5432 postgres:17-alpine
export DATABASE_URL='postgresql://postgres:[email protected]:5434/postgres?sslmode=disable'
make test     # all tests, including the bypass suite
make golden   # re-record the old server's output (needs npx)

DATABASE_URL 必须是超级用户:测试装置会重置 public schema 并创建 mcp_ro 角色。请使用临时数据库。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。