PostgreSQL Field Guide

Postgres MCP Server

用 MCP 把 Claude Code 或 Cursor 接入 Postgres——只读角色、每 PR 一个分支、可验证的工具边界。

MCP(Model Context Protocol)为 agent 调用工具和读取数据提供了统一协议。Postgres MCP server 位于 agent 与数据库之间,把 schema 元数据、只读查询和 EXPLAIN 输出暴露为工具,让 agent 对照真实的系统目录工作,而不是猜测列名。这会改变 AI 生成 SQL 的失败模式——模型能自查之后,大多数“幻觉列名”错误就消失了。

Server 本身只是传输层,真正的安全边界是它连接时使用的数据库角色,下文以及安全 SQL 护栏会展开说明。

选择 server

以下工具能力声明均以 2026-08 时各项目仓库为准核对;MCP 生态变化很快,采用前请重新确认。

项目维护方说明
Postgres MCP Propostgres-mcpCrystal DBASchema 浏览、EXPLAIN 分析、索引调优与健康检查。提供 --access-mode=restricted 参数,将执行限制为只读 SQL。基于 Python,通过 uvxpipxcrystaldba/postgres-mcp Docker 镜像运行。
Neon MCPNeon增加了项目级资源:创建分支、在分支上执行迁移、获取连接串。
Supabase MCPSupabase托管 server,覆盖数据库与项目管理(分支、日志、advisor)。

旧官方参考实现已归档

@modelcontextprotocol/server-postgres——Anthropic 最初的参考实现——已在 npm 上标记废弃,源码移入只读的 servers-archived 仓库,不再有维护和安全修复。新部署不要使用它(2026-08 核对)。

无论选哪个 server,都把厂商的功能列表当作临时状态看待:只有确实用到调优工具时才启用 pg_stat_statementshypopg,并在配置中固定 server 版本,让升级成为一个主动决定。

先建只读角色

配置任何客户端之前,先创建一个只能读的角色:

CREATE ROLE readonly LOGIN PASSWORD 'secret';
GRANT CONNECT ON DATABASE myapp TO readonly;
GRANT USAGE ON SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;

ALTER ROLE readonly SET default_transaction_read_only = on;
ALTER ROLE readonly SET statement_timeout = '5s';

ALTER DEFAULT PRIVILEGES 这行很关键:没有它,之后新建的表对该角色不可见,agent 看到的 schema 会悄悄过期。超时也应在角色层设置,避免 agent 发出的失控查询长期占用资源——完整配置(lock timeout、idle-in-transaction timeout、行数上限)见安全 SQL 护栏

永远不要把写权限交给 agent

不要给 MCP server 超级用户或表属主凭据——本地开发也不行,因为开发配置里的习惯会漏进生产。生产环境的写权限绝不应暴露给 agent:让它连接只读副本、Aurora reader 端点或数据库分支。MCP server 的受限模式只是第二层防线,不能替代角色层的权限控制。

在 Claude Code 中接入

项目级 .mcp.json(提交到仓库,团队共享同一份 server 配置),或用 claude mcp add 添加用户级条目:

{
  "mcpServers": {
    "postgres": {
      "command": "uvx",
      "args": [
        "postgres-mcp",
        "--access-mode=restricted",
        "postgres://readonly:secret@localhost:5432/myapp"
      ]
    }
  }
}

--access-mode=restricted 保证即使 agent 发起写请求,server 也只执行只读 SQL(2026-08 在项目 README 中核对)。连接串优先从环境变量或 secret manager 注入,不要把密码提交进仓库。

在 Cursor 中接入

.cursor/mcp.json

{
  "mcpServers": {
    "postgres": {
      "command": "uvx",
      "args": ["postgres-mcp", "--access-mode=restricted"],
      "env": {
        "DATABASE_URI": "postgres://readonly:secret@localhost:5432/myapp"
      }
    }
  }
}

每个 PR 一个数据库分支

Neon 和 Supabase 都支持基于 copy-on-write 的即时分支。结合 MCP,每个 PR 可以拥有一个独立数据库,供 agent 执行迁移、查询,用完即销毁:

  1. 从 main fork 一个分支(毫秒级,不复制数据)。
  2. 对着真实形态的数据跑迁移和测试,让 agent 在真实数据量上读 EXPLAIN
  3. 在 PR 中 review 变更,合并后删除分支。
neon branches create --name pr-123 --parent main
export DATABASE_URI=$(neon connection-string --branch pr-123)
# 用 DATABASE_URI 启动 MCP server

这是 MCP 价值最大的场景:agent 对照真实 catalog 和真实数据分布验证迁移,全程不接触生产写入端。

通过契约约束暴露面

数据库 MCP server 回答的是“schema 长什么样”“这条查询会做什么”——它不应该变成通用的数据外泄通道。用上下文契约把面向任务的上下文控制得小而明确:agent 只拿到与任务相关的表和列,MCP server 负责验证,而不是漫游无关的 schema。

配合 MCP 使用的 prompt

Schema 审计
使用 postgres MCP:

1. 用 `list_schemas` / `list_objects` 列出所有用户 schema 与表。
2. 对每个核心业务表,使用 `get_object_details` 查看列、外键、索引。
3. 跑只读查询 `SELECT count(*) FROM <table>` 估算量级(大表用 pg_class.reltuples)。
4. 检查:
 - 哪些表没有主键?
 - 哪些 timestamp 列没有时区?
 - 哪些外键列没有索引?
 - 哪些查询路径在 pg_stat_statements 中 top 10?
5. 给出 1 页改进清单,按“风险 × 影响”排序。

只读,禁止 DDL/DML。
基于真实数据写迁移
使用 postgres MCP:

我准备给 `orders` 表加一个 `tags text[]` 列并支持 GIN 索引。请:

1. 先 `get_object_details orders` 确认当前结构与行数。
2. 估算线上加列 + 加 GIN 索引的代价(用 `reltuples` * 单行成本,引用官方文档说明)。
3. 给出一份 **零停机迁移** 计划(用 `CONCURRENTLY` 建索引、分批回填)。
4. 输出迁移 SQL(含回滚),分多个 statement,每个 statement 注释解释。
5. 不要执行 ALTER;只输出 SQL 文件给我 review。

下一步

Last updated on

On this page