---
title: "Postgres MCP Pro 架构解读"
description: "仓库 petwan/postgres-mcp 的深度架构解读。它不只是又一个\"让 LLM 跑 SQL\"的 MCP server，而是把 LLM 的语言智能和 DBA 的算法确定性捏在一起的数据库 copilot 网关 — 对 data agent 和非技术人员查阅数据都有显著提效。"
---

> Documentation Index
> Fetch the complete documentation index at: https://petwan.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Postgres MCP Pro 架构解读

> 仓库：[petwan/postgres-mcp](https://github.com/petwan/postgres-mcp)（fork 自 [crystaldba/postgres-mcp](https://github.com/crystaldba/postgres-mcp)，README / 维护者 / 社区渠道仍指向上游）
>
> 一句话：**它不是又一个"让 LLM 跑 SQL"的 MCP server，而是一个把"LLM 的语言智能"和"DBA 的算法确定性"捏在一起的数据库 copilot 网关。**

## 1. 它要解决的问题

LLM 单独面对生产数据库有三个本质缺陷：

1. **看不见** — 没有 `pg_stat_statements`、没有 `pg_class`、没有 vacuum 历史，它对"系统慢在哪里"是瞎的。
2. **会乱猜** — 让 LLM 给你推荐索引，它会一本正经写 `CREATE INDEX`，但它不知道为什么推荐、推荐之后代价是多少。索引推荐是组合爆炸问题（每张表 × 每列 × 每种索引类型 × 每种组合），只能用搜索算法。
3. **会出事** — 把 `drop table` / `update … set …` 一不小心就执行掉。

Postgres MCP Pro 的设计哲学正好对这三个缺陷打补丁：把 LLM 放回"提问和决策"的位置，把所有需要**确定性**的动作（SQL 执行、索引搜索、健康检查）做成**结构化 MCP tools**，让 LLM 通过调用工具拿到的是**真实可重现的结果**，而不是 LLM 自己编出来的答案。

- **确定性** — 健康检查、索引推荐、慢查询分析全部由算法执行，可重复。
- **可验证** — 索引推荐通过 hypopg 模拟，不写磁盘、不影响线上。
- **可观测** — tool annotations 把"会改数据 / 不会改数据"暴露给 LLM。
- **可回滚** — 任何 DDL 在 hypopg 层都是虚拟的，可以即时撤销。

这就是 README 里那张对比表的精髓：

| 能力 | Postgres MCP Pro | 其他 Postgres MCP Server |
|---|---|---|
| 数据库健康检查 | ✅ 确定性 | ❌ LLM 自己跑不可重复的查询 |
| 索引推荐 | ✅ 算法搜索 | ❌ GenAI 瞎猜 |
| 慢查询分析 | ✅ 基于 workload | ❌ 不一致 |
| 性能预估 | ✅ 用 hypopg 模拟 | ❌ 自己试试看 |

## 2. 架构骨架

四个关键设计取舍：

### 2.1 Tools 而非 Resources — 主动暴露能力

README 里特意点出：他们**只用 MCP Tools，不暴露 Resources**。

- 生态兼容：MCP clients（Claude / Cursor / Goose / Qodo）对 tools 的支持最完整。
- 工具是**主动调用**（LLM 决定何时调用），资源是**被动拉取**（LLM 必须自己记得去读）。把健康检查、索引推荐做成 tool，LLM 才会在"用户问系统慢在哪"时主动触发它们，而不是依赖 prompt 暗示。

### 2.2 access-mode 二元化 — 同一二进制，开发/生产两用

- `--access-mode=unrestricted` — 全读写。开发环境用，agent 可以建表、跑 migration、调索引。
- `--access-mode=restricted` — 强制只读 + 事务超时。生产环境挂这个，agent 误操作最坏也只能 SELECT。
- 同名工具 `execute_sql` 在两种模式下语义不同，靠 MCP **tool annotations**（`readOnlyHint` / `destructiveHint`）让客户端 LLM 知道当前会话的危险等级。

这是把"安全策略"做成 LLM 看得见的语义，而不是藏在后端的 ACL。

> **为什么要 tool annotations**
>
> LLM 在写 SQL 时，客户端 UI 会显示"这个工具会改数据 / 不会改数据"，这是给 LLM 加**前置护栏** — 比事后审计日志更早，比权限 ACL 更可观察。

### 2.3 经典算法接管"决策"层

索引推荐工具内部用了 **Anytime Algorithm**（源自 Microsoft SQL Server Tuning Advisor 的工业级搜索算法）：

- 不是 LLM 给"建议"，而是 LLM 提供候选查询集合 + 算法穷举组合 + 用 PostgreSQL 自身的 cost model 估算收益。
- 通过 `hypopg` 扩展做"假设性索引"评估 — 索引**只存在于内存里**，不写磁盘，不影响线上。
- LLM 在这个工作流里只负责两件事：选 query 集合 + 把算法的输出翻译成自然语言解释。

这是整个项目最漂亮的一笔：**让算法做它擅长的穷举，让 LLM 做它擅长的语言**。

### 2.4 多 transport — 适配不同部署形态

`stdio`（本地开发，默认）、`SSE`（早期 HTTP 推送）、`streamable-http`（MCP 新标准）。三种并存，让一个二进制既能跑在本地 IDE 里，也能部署在团队共享的服务器上。

## 3. 工具集的具体能力

| 工具 | 干啥 | 谁会调用 |
|---|---|---|
| `list_schemas` / `list_objects` / `get_object_details` | 浏览 schema | LLM 在写第一条 SQL 前必跑 |
| `execute_sql` | 跑 SQL（受 access-mode 约束） | 几乎所有数据任务 |
| `explain_query` | EXPLAIN + 模拟假设性索引 | 调优 |
| `get_top_queries` | 基于 `pg_stat_statements` 拉慢查询 | 性能问题排查 |
| `analyze_workload_indexes` / `analyze_query_indexes` | 算法级索引推荐 | 慢查询根因 |
| `analyze_db_health` | 一次性体检（vacuum、连接、缓存、复制、sequence、约束） | 周期性巡检 |

工具集**故意做得小**（9 个 tool） — 少而精，每个都能解释，每个都有边界。这是好的 API 设计哲学：tool 太多 = LLM 选择困难，tool 太少 = 表达力不够。9 个刚好覆盖一个 DBA 日常会用 psql 跑的所有动作。

## 4. 对 Data Agent 的价值

把 Postgres MCP Pro 接进 LLM Agent 工作流之后，agent 的能力发生**质变**。具体可以拆成 4 个层次：

### 4.1 从"猜"到"测"

没有这个 server，LLM 帮你看慢查询是这样的：

> "试试给 `orders(customer_id)` 加个索引"

有了它：

> agent 先 `get_top_queries` → 拿到前 10 慢查询 → `analyze_query_indexes` 跑算法 → `explain_query` + 假设性索引验证 → "**`CREATE INDEX orders_created_at_idx ON orders(created_at)`** 把 query 3 的 cost 从 1240 降到 17，预计 73× 加速"。

从"建议"升级到"可验证的工程建议"。LLM 现在能写出 **带数据支撑的优化报告**。

### 4.2 从"读 SQL"到"懂 schema"

`get_object_details` 把表的列、约束、索引、外键结构化返回，LLM 在写 JOIN 的时候不再瞎猜字段名，错误率显著下降。生产环境的迁移类任务（写 DDL）尤其依赖这个。

### 4.3 从"一次性修复"到"周期性巡检"

把 `analyze_db_health` 接进 cron 触发的 agent 工作流（GitHub Action / cron + MCP），每周自动出一份数据库体检报告。LLM 解读健康分，标记 vacuum 滞后、缓存命中率、复制延迟等红灯项。相当于把 DBA 的日常巡检自动化。

### 4.4 从"单兵作战"到"团队 copilot"

上游把它定位成"全开发周期伴侣"：写代码时它帮 ORM 写对 SQL，code review 时它能跑 EXPLAIN 给 PR 加评估，上线后它巡检健康。这就把"数据库知识"装进了 agent，团队的资深 DBA 经验被一个工具打包复用。

## 5. 对其他团队人员"查阅数据"的提效

这部分是**最被低估的价值**。展开说：

### 5.1 产品 / 运营 / 业务分析师 — 不再卡在 SQL 门槛上

> **Note**
>
> **传统流程**：业务："上月广东省的客单价趋势？" → 分析师："我先翻 schema → 找订单表 → 找地区字典表 → 写 JOIN → ... 等 DBA 给权限 ..."

**接 MCP 之后**：业务在 Cursor / Claude 里："上月广东省的客单价趋势，按周给我" → agent：`list_schemas` → `list_objects('public')` → `get_object_details('orders')` → 自己拼 SQL → `execute_sql`（restricted 模式）→ 用中文总结成趋势图描述。

> **提效点**
>
> 分析需求从"天级"（等排期）→"分钟级"（直接问）。分析师不再卡在"哪个字段代表地区"这种 schema 考古问题上。

### 5.2 后端 / 数据工程师 — 不再孤军作战

新人入职最大的成本之一是"搞清楚我们的 schema"。MCP 提供的 `list_objects` + `get_object_details` 把 schema 探索变成**对话式**：

- "我们的 orders 表有外键指向 customer 吗？"
- "这个 customer_id 字段允许 NULL 吗？"
- "近 30 天有新建过索引吗？"

不用打开 pgadmin，不用懂关系图，agent 直接读 catalog 回答。

### 5.3 DBA / SRE — 从救火到系统性治理

- `analyze_db_health` 把"今天数据库健康吗"做成**一调用出报告**。
- `get_top_queries` 把"哪条 query 最拖累系统"做成**自动 top-N**。
- 索引推荐让 DBA 决定"要不要采纳"，而不是自己手动 EXPLAIN + 试错。

把 DBA 的工作时间从"逐案排查"释放到"系统性治理 + 容量规划"。

### 5.4 数据科学家 / ML 工程师 — 快速验证特征假设

> "我们想用 `orders.user_agent` 做特征，看看 distinct 值数量和 null 率"

agent 跑：`SELECT count(*), count(distinct user_agent), count(*) FILTER (WHERE user_agent IS NULL) ...`

不用申请读权限、不用写 Python 脚本连接 DB、不用等 ETL 出一份样本。直接在 IDE 里问。

## 6. 三个工程上的亮点（值得抄的）

- **hypopg 用法** — 评估索引收益**不真的建索引**。这是个通用的"假设实验"思路，可以套到任何"加新东西之前先估算收益"的场景（新增字段、新增分区策略等）。
- **Tool annotations** — 用语义元数据让 LLM 在调用前就知道风险。比"事后审计日志"更前置，比"权限 ACL"更可观察。
- **Access mode 二元化** — 同一二进制能服务两个完全不同的场景，运维成本最低。

## 7. 接入成本和坑

> **前置依赖**
>
> 接入前要准备：
>
> - **`pg_stat_statements` + `hypopg` 扩展** — 装上才能用满功能；自建 PG 需要改 `shared_preload_libraries`。
> - **read-only 用户的权限边界** — restricted 模式跑在生产库上时，至少需要 `pg_read_all_stats` + 目标 schema 的 SELECT。
> - **schema 暴露控制** — agent 能 `list_objects` 看到所有 schema；敏感 schema 应该用独立的 MCP 实例挂出来。
> - **审计** — 所有 `execute_sql` 都应该打日志，谁在什么时间跑过什么 SQL，agent 时代这点尤其重要。

## 8. 一句话总结

**Postgres MCP Pro 不是把数据库"打开"给 LLM，而是把数据库"翻译"给 LLM**：把 LLM 不擅长的部分（成本估算、索引搜索、健康巡检）固化成可调用的确定性 tools，让 LLM 发挥它擅长的部分（理解需求、解释结果、写报告、做决策）。结果是 — **同一个团队、同一个 agent 角色，覆盖了从 DBA 到分析师到产品经理的所有数据库交互场景**，而每个角色获得的提效点不一样，但对全公司来说，等于把"数据库知识"装进了一个 7×24 在线、随手可调的工具里。

## 9. 快速接入路径

Postgres MCP Pro 是一个 **Python 项目**，支持两种安装方式。最快路径：先跑本地 `uvx` 版本把功能体验起来，再决定要不要上 Docker。

### 9.1 前置条件

- Python 3.12+（或 `uv`，推荐）
- 一个带 `pg_stat_statements` + `hypopg` 扩展的 PostgreSQL 测试库

### 9.2 方式一：uvx 一行（最简单，本地开发首选）

```json title="mcp.json"
{
  "mcpServers": {
    "postgres": {
      "command": "uvx",
      "args": [
        "postgres-mcp",
        "--access-mode=unrestricted"
      ],
      "env": {
        "DATABASE_URI": "postgresql://user:password@localhost:5432/dbname"
      }
    }
  }
}
```

把这段贴进 Cursor 的 `mcp.json` 或 Cline 的 `cline_mcp_settings.json`，重开 IDE 就能用。`uvx` 会自动下载、缓存、启动，不用手动建 venv。

如果是第一次装 `uv`：

```bash title="安装 uv"
curl -LsSf https://astral.sh/uv/install.sh | sh    # macOS/Linux
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"  # Windows
```

### 9.3 方式二：pip 手动安装

```bash title="安装并启动 Postgres MCP"
uv pip install postgres-mcp        # 或 pip install postgres-mcp
postgres-mcp "postgres://user:password@localhost:5432/dbname"
```

### 9.4 方式三：Docker（生产部署）

```bash title="Docker 启动命令"
docker run -i --rm \
  -e DATABASE_URI=postgresql://user:password@host.docker.internal:5432/dbname \
  crystaldba/postgres-mcp --access-mode=restricted
```

Docker 版会自动把 `localhost` 映射到 `host.docker.internal`（macOS/Windows）或 `172.17.0.1`（Linux）。

### 9.5 生产建议

如果要落进生产，**强烈建议**先用 `restricted` 模式挂一个**只读副本**让团队熟悉 agent 的 SQL 输出习惯，再考虑给受限的开发库放开 `unrestricted`。

### 9.6 装 PostgreSQL 扩展

自建 PG 需在 `postgresql.conf` 里加：

```ini title="postgresql.conf"
shared_preload_libraries = 'pg_stat_statements, hypopg'
```

然后 `CREATE EXTENSION pg_stat_statements;` 和 `CREATE EXTENSION hypopg;` 即可。

Source: https://petwan.tech/postgres-mcp/index.mdx
