关于 Postgres Mcp
Postgres MCP Pro 是一个开源的 Postgres MCP 服务,面向开发、测试到生产调优的全流程。它提供索引调优、EXPLAIN 执行计划分析、数据库健康检查以及可配置的安全 SQL 执行能力,并可通过只读模式用于生产环境。
主要功能
- 01索引调优与索引推荐
- 02EXPLAIN 执行计划分析与假设索引模拟
- 03数据库健康检查
- 04基于 schema 的上下文感知 SQL 生成
- 05支持只读的可配置访问控制
- 06支持 stdio 与 SSE 传输
适用场景
- 01排查慢查询并获取优化建议
- 02针对工作负载推荐索引
- 03在生产环境中以只读模式检查数据库健康状况
MCP 相关
该项目是一个 MCP 服务,通过 MCP 工具(如 list_schemas、execute_sql、explain_query、analyze_db_health)向 MCP 客户端暴露 Postgres 的结构查询、SQL 执行与性能分析功能。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
概述
Postgres MCP Pro 是一个开源的模型上下文协议(MCP)服务,旨在支持您和 AI Agent 完成整个开发流程——从初始编码、测试和部署,到生产环境调优与维护。
Postgres MCP Pro 的功能远不止封装数据库连接。
其功能包括:
- 🔍 数据库健康状况 - 分析索引健康状况、连接利用率、缓冲区缓存、清理健康状况、序列上限、复制延迟等。
- ⚡ 索引调优 - 使用工业级算法探索数千种可能的索引,为您的工作负载找到最佳方案。
- 📈 查询计划 - 通过检查 EXPLAIN 计划并模拟假设索引的影响,验证并优化性能。
- 🧠 架构智能 - 基于对数据库架构的深入理解,生成上下文相关的 SQL。
- 🛡️ 安全 SQL 执行 - 可配置访问控制,包括只读模式和安全 SQL 解析支持,因此可用于开发和生产环境。
Postgres MCP Pro 同时支持 标准输入/输出(stdio)和服务器发送事件(SSE)传输方式,以适应不同环境。
如需了解构建 Postgres MCP Pro 的更多背景信息,请参阅我们的发布博客文章。
演示
从无法使用到快如闪电
- 挑战: 我们使用 AI 助手生成了一个电影应用,但 SQLAlchemy ORM 代码运行得异常缓慢。
- 解决方案: 我们使用 Postgres MCP Pro 和 Cursor,在几分钟内解决了性能问题。
我们做了以下工作:
- 🚀 修复性能问题——包括 ORM 查询、索引和缓存
- 🛠️ 修复损坏的页面——提示 Agent 探索数据、修复查询并添加相关内容。
- 🧠 改进热门电影展示——探索数据并修复 ORM 查询,以呈现更相关的结果。
请观看下方视频,或阅读操作详情。
https://github.com/user-attachments/assets/24e05745-65e9-4998-b877-a368f1eadc13
快速入门
前提条件
开始之前,请确保您具备:
- 数据库访问凭据。
- Docker 或 Python 3.12 或更高版本。
访问凭据
您可以使用 psql 或 pgAdmin 等 GUI 工具验证访问凭据是否有效。
Docker 或 Python
您可以自行选择使用 Docker 还是 Python。 我们通常建议使用 Docker,因为 Python 用户可能会遇到更多特定于环境的问题。 不过,使用您最熟悉的方式通常更合适。
安装
选择以下任一方法安装 Postgres MCP Pro:
选项 1:使用 Docker
拉取 Postgres MCP Pro MCP 服务的 Docker 镜像。 此镜像包含所有必要的依赖项,可在各种环境中可靠地运行 Postgres MCP Pro。
docker pull crystaldba/postgres-mcp
选项 2:使用 Python
如果已安装 pipx,可以使用以下命令安装 Postgres MCP Pro:
pipx install postgres-mcp
否则,使用 uv 安装 Postgres MCP Pro:
uv pip install postgres-mcp
如果需要安装 uv,请参阅 uv 安装说明。
配置 AI 助手
我们提供了使用 Claude Desktop 配置 Postgres MCP Pro 的完整说明。 许多 MCP 客户端的配置文件类似,你可以调整以下步骤以适用于所选客户端。
Claude Desktop 配置
你需要编辑 Claude Desktop 配置文件以添加 Postgres MCP Pro。 此文件的位置取决于你的操作系统:
- MacOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%/Claude/claude_desktop_config.json
你也可以使用 Claude Desktop 中的 Settings 菜单项来定位配置文件。
接下来,编辑配置文件中的 mcpServers 部分。
如果你使用 Docker
{
"mcpServers": {
"postgres": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"DATABASE_URI",
"crystaldba/postgres-mcp",
"--access-mode=unrestricted"
],
"env": {
"DATABASE_URI": "postgresql://username:password@localhost:5432/dbname"
}
}
}
}
Postgres MCP Pro Docker 镜像会自动将主机名 localhost 重新映射,以便在容器内使用。
- MacOS/Windows:自动使用
host.docker.internal - Linux:自动使用
172.17.0.1或适当的主机地址
如果你使用 uvx
{
"mcpServers": {
"postgres": {
"command": "uvx",
"args": [
"postgres-mcp",
"--access-mode=unrestricted"
],
"env": {
"DATABASE_URI": "postgresql://username:password@localhost:5432/dbname"
}
}
}
}
如果你使用 pipx
{
"mcpServers": {
"postgres": {
"command": "postgres-mcp",
"args": [
"--access-mode=unrestricted"
],
"env": {
"DATABASE_URI": "postgresql://username:password@localhost:5432/dbname"
}
}
}
}
如果你使用 uv
{
"mcpServers": {
"postgres": {
"command": "uv",
"args": [
"run",
"postgres-mcp",
"--access-mode=unrestricted"
],
"env": {
"DATABASE_URI": "postgresql://username:password@localhost:5432/dbname"
}
}
}
}
连接 URI
将 postgresql://... 替换为你的 Postgres 数据库连接 URI。
访问模式
Postgres MCP Pro 支持多种访问模式,让你可以控制 AI Agent 对数据库执行的操作:
- 不受限制模式:允许完全读写访问,以修改数据和架构。适用于开发环境。
- 受限模式:将操作限制为只读事务,并对资源使用施加限制(目前仅限执行时间)。适用于生产环境。
若要使用受限模式,请在上述配置示例中将 --access-mode=unrestricted 替换为 --access-mode=restricted。
其他 MCP 客户端
许多 MCP 客户端的配置文件与 Claude Desktop 类似,你可以调整上述示例以适用于所选客户端。
- 如果你使用 Cursor,可以从
Command Palette导航到Cursor Settings,然后打开MCP选项卡以访问配置文件。 - 如果你使用 Windsurf,可以从
Command Palette导航到Open Windsurf Settings Page以访问配置文件。 - 如果你使用 Goose,请运行
goose configure,然后选择Add Extension。 - 如果你使用 Qodo Gen,请打开 Chat 面板,点击
Connect more tools,再点击+ Add new MCP,然后添加新配置。
SSE 传输
Postgres MCP Pro 支持 SSE 传输,允许多个 MCP 客户端共用一个服务,该服务也可以是远程服务。
要使用 SSE 传输,需要使用 --transport=sse 选项启动服务。
例如,使用 Docker 时运行:
docker run -p 8000:8000 \
-e DATABASE_URI=postgresql://username:password@localhost:5432/dbname \
crystaldba/postgres-mcp --access-mode=unrestricted --transport=sse
然后更新 MCP 客户端配置,使其调用 MCP 服务。
例如,在 Cursor 的 mcp.json 或 Cline 的 cline_mcp_settings.json 中,你可以填写:
{
"mcpServers": {
"postgres": {
"type": "sse",
"url": "http://localhost:8000/sse"
}
}
}
对于 Windsurf,mcp_config.json 中的格式略有不同:
{
"mcpServers": {
"postgres": {
"type": "sse",
"serverUrl": "http://localhost:8000/sse"
}
}
}
Postgres 扩展安装(可选)
要启用索引调优和全面的性能分析,你需要在数据库中加载 pg_stat_statements 和 hypopg 扩展。
pg_stat_statements扩展可让 Postgres MCP Pro 分析查询执行统计信息。 例如,这样它就能了解哪些查询运行缓慢或消耗大量资源。hypopg扩展可让 Postgres MCP Pro 模拟添加索引后 Postgres 查询规划器的行为。
在 AWS RDS、Azure SQL 或 Google Cloud SQL 上安装扩展
如果你的 Postgres 数据库运行在云提供商的托管服务上,系统中应该已提供 pg_stat_statements 和 hypopg 扩展。
此时,你只需使用权限充足的角色运行 CREATE EXTENSION 命令:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS hypopg;
在自托管 Postgres 上安装扩展
如果你自行管理 Postgres 安装,可能还需要进行额外操作。
加载 pg_stat_statements 扩展前,必须确保 Postgres 配置文件中的 shared_preload_libraries 已列出该扩展。
hypopg 扩展可能还需要额外的系统级安装(例如通过包管理器安装),因为 Postgres 并非总是自带该扩展。
使用示例
获取数据库运行状况概览
提问:
检查我的数据库运行状况并找出问题。
分析慢查询
提问:
我的数据库中最慢的查询是什么?我该如何加快它们?
获取提速建议
提问:
我的应用运行缓慢。如何让它更快?
生成索引建议
提问:
分析我的数据库工作负载,并建议可提升性能的索引。
优化特定查询
提问:
帮我优化这个查询:SELECT * FROM orders JOIN customers ON orders.customer_id = customers.id WHERE orders.created_at > '2023-01-01';
MCP 服务 API
MCP 标准定义了多种端点类型:工具、资源、提示词等。
Postgres MCP Pro 仅通过 MCP 工具提供功能。 我们选择这种方式,是因为 MCP 客户端生态广泛支持 MCP 工具。 这与其他 Postgres MCP 服务采用的方式不同,例如 Reference Postgres MCP Server使用 MCP 资源来公开架构信息。
Postgres MCP Pro 工具:
| 工具名称 | 描述 |
|---|---|
list_schemas | 列出 PostgreSQL 实例中所有可用的数据库架构。 |
list_objects | 列出指定架构中的数据库对象(表、视图、序列、扩展)。 |
get_object_details | 提供特定数据库对象的信息,例如表的列、约束和索引。 |
execute_sql | 在数据库上执行 SQL 语句;以受限模式连接时仅可执行只读操作。 |
explain_query | 获取 SQL 查询的执行计划,说明 PostgreSQL 将如何处理该查询,并展示查询规划器的成本模型。可通过假设索引调用,以模拟添加索引后的行为。 |
get_top_queries | 根据 pg_stat_statements 数据,按总执行时间报告最慢的 SQL 查询。 |
analyze_workload_indexes | 分析数据库工作负载,识别占用大量资源的查询,并为其推荐最优索引。 |
analyze_query_indexes | 分析最多 10 条指定的 SQL 查询,并为其推荐最优索引。 |
analyze_db_health | 执行全面的健康检查,包括:缓冲区缓存命中率、连接健康状况、约束验证、索引健康状况(重复/未使用/无效)、序列限制和清理健康状况。 |
相关项目
Postgres MCP 服务
- Query MCP。用于 Supabase Postgres 的 MCP 服务,采用三层安全架构,并支持 Supabase 管理 API。
- PG-MCP。用于 PostgreSQL 的 MCP 服务,支持灵活的连接选项、执行计划、扩展上下文等。
- Reference PostgreSQL MCP Server。一个简单的 MCP 服务实现,可将架构信息作为 MCP 资源公开,并执行只读查询。
- Supabase Postgres MCP Server。此 MCP 服务提供 Supabase 管理功能,由 Supabase 社区积极维护。
- Nile MCP Server。提供 Nile 多租户 Postgres 服务管理 API 访问权限的 MCP 服务。
- Neon MCP Server。提供 Neon 无服务器 Postgres 服务管理 API 访问权限的 MCP 服务。
- Wren MCP Server。提供语义引擎,为 Postgres 和其他数据库提供商业智能支持。
DBA 工具(包括商业产品)
- Aiven Database Optimizer。提供全面的数据库工作负载分析、查询优化及其他性能改进的工具。
- dba.ai。一款 AI 驱动的数据库管理助手,可与 GitHub 集成以解决代码问题。
- pgAnalyze。一个全面的监控和分析平台,可用于识别性能瓶颈、优化查询并进行实时告警。
- Postgres.ai。结合了丰富的 Postgres 知识库与 GPT-4 的交互式聊天体验。
- Xata Agent。一个开源 AI Agent,使用大模型驱动的推理和操作手册自动监控数据库运行状况、诊断问题并提供建议。
Postgres 实用工具
- Dexter。用于生成和测试 PostgreSQL 假设索引的工具。
- PgHero。Postgres 性能仪表盘,并提供建议。 Postgres MCP Pro 集成了来自 PgHero 的运行状况检查。
- PgTune。用于调整 Postgres 配置的启发式方法。
常见问题
Postgres MCP Pro 与其他 Postgres MCP 服务有何不同? 有许多 MCP 服务允许 AI Agent 对 Postgres 数据库运行查询。 Postgres MCP Pro 也能做到这一点,但还增加了用于了解和提升 Postgres 数据库性能的工具。 例如,它实现了 Microsoft SQL Server 数据库调优顾问的 Anytime Algorithm,这是一种先进、达到工业级水平的自动索引调优算法。
| Postgres MCP Pro | 其他 Postgres MCP 服务 |
|---|---|
| ✅ 确定性的数据库健康检查 | ❌ 无法重复的 LLM 生成式健康查询 |
| ✅ 有原则的索引搜索策略 | ❌ 生成式 AI 对索引改进的猜测 |
| ✅ 分析工作负载以找出主要问题 | ❌ 不一致的问题分析 |
| ✅ 模拟性能改进 | ❌ 自己试试看是否有效 |
Postgres MCP Pro 通过添加确定性工具和经典优化算法,为生成式 AI 提供补充。 两者结合既可靠又灵活。
当大模型能够推理、生成 SQL 等时,为什么还需要 MCP 工具? 大模型对于涉及模糊性、推理或自然语言的任务至关重要。 然而,与过程式代码相比,它们可能速度较慢、成本较高、非确定性较强,有时还会产生不可靠的结果。 在数据库调优领域,我们有经过数十年开发、并已证明有效的成熟算法。 Postgres MCP Pro 将大模型与经典优化算法及其他过程式工具结合,让你兼得两者之长。
如何测试 Postgres MCP Pro? 测试对于确保 Postgres MCP Pro 可靠且准确至关重要。 我们正在构建一套由 AI 生成的对抗性工作负载,旨在挑战 Postgres MCP Pro,并确保它能应对各种场景。
支持哪些 Postgres 版本? 目前,我们的测试侧重于 Postgres 15、16 和 17。 我们计划支持 Postgres 13 至 17。
谁创建了这个项目? 此项目由 Crystal DBA 创建并维护。
路线图
待定
你和你的需求是我们构建方向的重要驱动力。 请通过提交 issue 或 pull request 告诉我们你希望看到什么。 你也可以通过 Discord 联系我们。
技术说明
本节概述影响 Postgres MCP Pro 设计的技术考量。
索引调优
开发者都知道,缺少索引是数据库性能问题最常见的原因之一。 索引提供访问方法,使 Postgres 能够快速定位执行查询所需的数据。 当表较小时,索引影响不大;但随着数据量增长,表扫描与索引查找在算法复杂度上的差异会变得显著(通常为 O(n) 与 O(log n),如果涉及多个表的连接,差异可能更大)。
在 Postgres MCP Pro 中,生成建议索引分为几个阶段:
-
识别需要调优的 SQL 查询。 如果你知道某条特定 SQL 查询存在问题,可以直接提供该查询。 Postgres MCP Pro 也可以分析工作负载,识别需要进行索引调优的目标。 为此,它依赖
pg_stat_statements扩展,该扩展会记录每条查询的运行时间和资源消耗。 如果某个查询是资源消耗最高的查询之一,无论按单次执行还是累计计算,它就适合进行索引调优。 目前,我们用执行时间作为累计资源消耗的替代指标,但也可以考虑查看具体的资源指标,例如访问的块数或从磁盘读取的块数。analyze_query_workload工具专注于慢查询,使用单次执行平均耗时,并设置执行次数和平均执行时间的阈值。 Agent 也可以调用get_top_queries,指定按平均还是总执行时间排序,然后将这些查询传给analyze_query_indexes,以获取索引建议。高级索引调优系统会使用“工作负载压缩”,生成能够反映整体工作负载特征的代表性查询子集,从而简化后续算法需要解决的问题。 Postgres MCP Pro 通过规范化查询,实现了有限形式的工作负载压缩,使同一模板生成的查询合并为一个。 它对每个查询赋予相同权重,这种简化在索引带来的收益较大时有效。
-
生成候选索引 确定要通过索引优化的 SQL 查询列表后,我们会生成一组可能要添加的索引。 为此,我们会解析 SQL,并识别用于筛选、联接、分组或排序的列。
要生成所有可能的索引,我们需要考虑这些列的各种组合,因为 Postgres 支持多列索引。 在当前实现中,每个可能的多列索引只包含一个排列组合,并随机选出。 我们采用这种简化方式来缩小搜索空间,因为不同排列的性能往往相当。 不过,我们希望在这方面有所改进。
-
搜索最优索引配置。 我们的目标是找到索引组合,在性能收益与存储和维护这些索引的成本之间实现最佳平衡。 我们使用
hypopg扩展提供的“假设分析”功能来估算性能提升。 该功能会模拟添加索引后 Postgres 查询优化器如何执行查询,并根据 Postgres 的实际成本模型报告变化。一个挑战是,生成查询计划通常需要了解查询中使用的具体参数值。 查询规范化是缩小待分析查询范围所必需的,但会移除参数常量。 通过绑定变量提供的参数值同样无法获取。
为了解决这个问题,我们会从表统计信息中采样,生成可作为参数提供的真实常量。 在版本 16 中,Postgres 新增了通用解释计划功能,但该功能存在一些限制,例如对
LIKE子句的处理有限,而我们的实现没有这些限制。搜索策略至关重要,因为只有在简单情况下才能评估所有可能的索引组合。 各种索引方法的主要区别通常就在于此。 我们借鉴了 Microsoft 的 Anytime 算法,采用贪心搜索策略:先找到最佳的单索引方案,再找出添加到该方案中、效果最佳的索引,从而生成双索引方案。 当时间预算耗尽,或某轮探索未能取得超过 10% 最低提升阈值的收益时,搜索就会终止。
-
成本效益分析。 当面对两种索引方案时,一种性能更好,另一种占用空间更多,我们该如何决定选哪一种? 传统上,索引顾问会询问存储预算,并在该预算范围内优化性能。 我们同样会考虑存储预算,但会在整个优化过程中进行成本效益分析。
我们将其视为沿着 帕累托前沿 选择一个点的问题——帕累托前沿是这样一组选择:改善一项质量指标必然会使另一项变差。 理想情况下,我们或许会想用货币衡量存储成本和性能提升带来的收益。 不过,有一种更简单、更实用的方法:比较相对变化。 大多数人都会认同,即使存储成本翻倍,性能提升 100 倍也值得。 在我们的实现中,我们使用一个可配置参数来设定这一阈值。 默认情况下,我们要求性能提升的对数(以 10 为底)变化量,是空间成本对数变化量的 2 倍。 这相当于允许空间增加最多 10 倍,以换取性能提升 100 倍。
我们的实现与 Microsoft SQL Server 中的 Anytime Algorithm 最为相似。 与 Postgres 自动索引工具 Dexter 相比,我们搜索的空间更大,并且使用了不同的启发式方法。 因此,我们能生成更好的方案,但运行时间也更长。
我们还会展示每一轮搜索所做的工作,包括添加每个索引前后查询计划的对比。 这能为 LLM 提供更多上下文,供其在回应索引建议时使用。
实验性:由 LLM 进行索引调优
Postgres MCP Pro 包含一项实验性的索引调优功能,基于 Optimization by LLM。
我们不使用启发式方法探索可能的索引配置,而是将数据库架构和查询计划提供给 LLM,并请它提出索引配置方案。
然后,我们使用 hypopg 预测这些索引的性能,再将结果反馈给 LLM,以生成一组新的建议。
我们会重复此过程,直到经过多轮迭代后不再有进一步改进。
当索引搜索空间较大,或需要考虑包含许多列的索引时,由 LLM 进行索引优化具有优势。
与传统的基于搜索的方法一样,这种方法依赖于 hypopg 性能预测的准确性。
要使用 LLM 进行索引优化,必须设置 OPENAI_API_KEY 环境变量来提供 OpenAI API 密钥。
数据库健康状况
数据库健康检查可在问题演变为严重故障前,发现优化机会和维护需求。 在当前版本中,Postgres MCP Pro 直接改编了 PgHero 中的数据库健康检查。 我们正在全面验证这些检查,并可能在未来对其进行扩展。
- 索引健康状况。查找未使用的索引、重复索引和膨胀的索引。膨胀的索引会低效地使用数据库页。 Postgres 自动清理进程会清理指向死元组的索引条目,并将这些条目标记为可复用。不过,它不会压缩索引页,因此随着时间推移,索引页中可能只剩下少量指向存活元组的引用。
- 缓冲区缓存命中率。衡量由缓冲区缓存而非磁盘提供服务的数据库读取所占比例。 如果缓冲区缓存命中率较低,就必须进行调查,因为这通常不具备成本效益,还会导致应用性能下降。
- 连接健康状况。检查数据库连接数,并报告连接的使用情况。 最大的风险是连接耗尽,但大量空闲或受阻的连接也可能表明存在问题。
- 清理健康状况。清理之所以重要,原因有很多。 其中一个关键原因是防止事务 ID 回卷,否则数据库可能会停止接受写入。 Postgres 多版本并发控制(MVCC)机制要求每个事务都有唯一的事务 ID。 但是,由于 Postgres 使用 32 位有符号整数表示事务 ID,因此在最多 20 亿个事务后需要重用事务 ID。 为此,它会“冻结”历史事务的事务 ID,将它们全部设为一个表示遥远过去的特殊值。 记录首次写入磁盘时,会以对一系列事务 ID 可见的形式写入。 在重用这些事务 ID 之前,Postgres 必须更新所有磁盘上的记录,将其“冻结”,以移除对待重用事务 ID 的引用。 此检查会查找需要清理以防止事务 ID 回卷的表。
- 复制健康状况。通过监控主节点与副本之间的延迟、验证复制状态,以及跟踪复制槽的使用情况来检查复制健康状况。
- 约束健康状况。在正常运行期间,Postgres 会拒绝任何会导致违反约束的事务。 但是,加载数据后或在恢复场景中可能会出现无效约束。此检查会查找所有无效约束。
- 序列健康状况。查找有可能超过最大值的序列。
Postgres 客户端库
Postgres MCP Pro 使用 psycopg3 通过异步 I/O 连接到 Postgres。 在底层,psycopg3 使用 libpq 库连接到 Postgres,从而提供对完整 Postgres 功能集的访问,并采用由 Postgres 社区全面支持的底层实现。
其他一些基于 Python 的 MCP 服务使用 asyncpg,这可能通过消除 libpq 依赖项来简化安装。
asyncpg 也可能比 psycopg3 更快,但我们尚未自行验证这一点。
较早的基准测试显示性能差距更大,这表明随着 psycopg3 日趋成熟,它已缩小了差距。
权衡这些因素后,我们选择了 psycopg3,而不是 asyncpg。
我们仍愿意在未来重新考虑这一决定。
连接配置
与PostgreSQL MCP 参考服务一样,Postgres MCP Pro 在启动时接收 Postgres 连接信息。 对于始终连接到同一数据库的用户来说,这很方便;但用户切换数据库时可能会感到麻烦。
PG-MCP 采取了另一种方式:在使用时通过 MCP 工具调用提供连接详情。 对于切换数据库的用户来说,这样更方便,也允许一个 MCP 服务同时支持多个终端用户。
应该有比这两种方式都更好的方案。 两者都有安全隐患——很少有 MCP 客户端会安全地存储 MCP 服务配置(Goose 是个例外),而通过 MCP 工具提供的凭据会经过大模型,并保存在聊天记录中。 此外,在某些场景下,两者的易用性也存在问题。
架构信息
架构信息工具的目的是向调用它的 AI Agent 提供生成正确且高效的 SQL 所需的信息。 例如,假设用户询问:“过去一年里,有多少架飞机从旧金山起飞并降落在巴黎?” AI Agent 需要找到存储航班信息的表、存储出发地和目的地的列,或许还需要找到一张用于映射机场代码和机场位置的表。
既然大模型通常能够直接生成用于从 Postgres 检索这些信息的 SQL,为什么还要提供架构信息工具?
根据我们使用 Claude 的经验,调用方大模型很擅长通过查询Postgres 系统目录和信息架构(一种符合 ANSI 标准的数据库元数据视图)来探索 Postgres 架构。 不过,我们不确定其他大模型是否也能同样可靠且熟练地做到这一点。
与其使用MCP 工具,是否更适合通过MCP 资源提供架构信息?
PostgreSQL MCP 参考服务使用资源而非工具来公开架构信息。 浏览资源类似于浏览文件系统,因此这种方式在很多方面都很自然。 不过,在 MCP 客户端生态系统中,对资源的支持不如对工具的支持普遍(参见客户端示例)。 此外,虽然 MCP 标准规定 AI Agent 和终端用户都可以访问资源,但有些客户端只支持由人类浏览资源树。
受保护的 SQL 执行
AI 加剧了保护数据库免受各种威胁这一长期存在的挑战,威胁范围从简单的错误到恶意行为者发起的复杂攻击。 无论威胁是意外还是恶意,适用的安全框架都类似,其目标可分为三类:机密性、完整性和可用性。 便利与安全之间的常见矛盾也同样明显且突出。
Postgres MCP Pro 的受保护 SQL 执行模式侧重于完整性。 在 MCP 的语境下,我们最担心大模型生成的 SQL 造成损害,例如意外修改或删除数据,或进行其他可能绕过组织变更管理流程的更改。
确保完整性的最简单方法,是确保对数据库执行的所有 SQL 均为只读。 一种方法是创建具有只读访问权限的数据库用户。 虽然这是一个不错的方法,但许多人发现它在实践中很繁琐。 Postgres 不提供将连接或会话设为只读模式的方法,因此 Postgres MCP Pro 采用了一种更复杂的方法,在读写连接之上确保只读 SQL 执行。
Postgres MCP 提供只读事务模式,可防止修改数据和架构。 与 PostgreSQL MCP 参考服务 一样,我们使用只读事务来实现受保护的 SQL 执行。
为了使此机制足够可靠,我们需要确保 SQL 不会以某种方式绕过只读事务模式,例如通过执行 COMMIT 或 ROLLBACK 语句,然后开始一个新事务。
例如,大模型可以通过执行 ROLLBACK 语句,然后开始一个新事务来绕过只读事务模式。
例如:
ROLLBACK; DROP TABLE users;
为了防止此类情况,我们使用 pglast 库在执行前解析 SQL。
我们会拒绝任何包含 commit 或 rollback 语句的 SQL。
值得庆幸的是,常见的 Postgres 存储过程语言,包括 PL/pgSQL 和 PL/Python,都不允许使用 COMMIT 或 ROLLBACK 语句。
如果你的数据库启用了不安全的存储过程语言,那么我们的只读保护可能会被绕过。
目前,Postgres MCP Pro 为数据库提供了两个极端的保护级别,分别位于便利性与安全性光谱的两端。
- “Unrestricted” 提供最大的灵活性。 适用于速度和灵活性至关重要,且无需保护有价值或敏感数据的开发环境。
- “Restricted” 在灵活性与安全性之间取得平衡。 适用于数据库向不受信任的用户开放,且保护有价值或敏感数据至关重要的生产环境。
Unrestricted 模式与 Cursor 的自动运行模式 的做法一致,在该模式下,AI Agent 只受到有限的人工监督或审批。 我们预计自动运行模式会部署在开发环境中,因为这类环境中的错误后果较轻,数据库不包含有价值或敏感的数据,并且在需要时可以重新创建数据库或从备份中恢复。
我们将 restricted 模式设计得较为保守,即使可能不够方便,也优先考虑安全性。 Restricted 模式仅限只读操作,并且我们限制查询执行时间,以防长时间运行的查询影响系统性能。 未来我们可能会添加一些措施,以确保 restricted 模式可安全用于生产数据库。
Postgres MCP Pro 开发
以下说明面向希望参与 Postgres MCP Pro 开发的开发者,或希望从源代码安装 Postgres MCP Pro 的用户。
Local Development Setup
-
Install uv:
curl -sSL https://astral.sh/uv/install.sh | sh -
Clone the repository:
git clone https://github.com/crystaldba/postgres-mcp.git cd postgres-mcp -
Install dependencies:
uv pip install -e . uv sync -
Run the server:
uv run postgres-mcp "postgres://user:password@localhost:5432/dbname"
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。