关于 pgmcp
pgmcp 是面向 PostgreSQL 运维和 DBA 诊断的只读 MCP 服务,适用于排查性能与数据库健康问题。它结合全局诊断和受限制的临时查询,并通过数据库权限、只读事务和 SQL 检查限制访问。
主要功能
- 01按多种指标排列慢查询
- 02检查查询计划和计划哈希
- 03检查索引与表健康状况
- 04查看锁等待、连接和复制延迟
- 05检查配置并执行受限只读 SQL
适用场景
- 01在故障期间调查慢查询
- 02查找阻塞会话和锁等待环
- 03检查未使用索引和滞后的自动清理
- 04检查备用节点延迟和数据库配置
MCP 相关
它通过 stdio 或 Streamable HTTP 向 MCP 客户端提供九个诊断工具、两个资源和一个 `diagnose_slow_query` 提示词。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
pgmcp
pgmcp 是一款适用于 Model Context Protocol 的只读 PostgreSQL 运维/DBA 服务,基于官方 modelcontextprotocol/go-sdk 构建。它可以回答 DBA 在事件处理中会提出的问题:哪些语句执行缓慢、为什么这个执行计划很慢、哪些索引毫无用处、哪些表的自动清理进度落后、谁在阻塞谁、备用服务器落后了多少——而且只读是由设计保证的,而非约定俗成:专用数据库角色不具备任何写入权限;每条语句都在带有语句超时的 BEGIN READ ONLY 事务中执行;SQL 解析器防护则会拒绝任何不是单条 SELECT/EXPLAIN/SHOW 的语句,以及所有可能在只读事务中改变状态的函数。已通过 PostgreSQL 16 测试;要求版本为 13 或更高。
安装
**Claude Desktop,一键安装:**从 Releases 下载 pgmcp_<version>.mcpb 并打开。Claude Desktop 会提示输入 Postgres 连接字符串,将其保存在操作系统钥匙串中,并自行启动捆绑的二进制文件——无需将内容放入 PATH,也无需编辑配置文件。一个安装包支持 macOS(通用版)和 Windows(x64)。
也可以从 Releases 下载适用于你平台的二进制文件——支持 darwin、linux 和 windows,以及 amd64 和 arm64,并提供校验和。
或者使用 Go CLI 工具 go 从源代码构建:
go install github.com/pascalallen/pgmcp/cmd/pgmcp@latest
也可以运行已发布的镜像,该镜像采用 distroless、非 root 用户并支持多架构:
docker run --rm -i -e PGMCP_DATABASE_URL='postgres://…' ghcr.io/pascalallen/pgmcp
pgmcp 已在 MCP Registry 中登记,名称为 io.github.pascalallen/pgmcp。
在连接任何数据库之前,请先创建只读角色——参见数据库角色。即使另外两层出现缺陷,这一层仍能提供保障。
使用方法
一种 MCP 接口,两种传输方式。使用哪一种由配置决定,不需要构建不同版本。
Claude Code,stdio——客户端启动二进制文件,并通过 stdin/stdout 通信:
claude mcp add pgmcp --transport stdio \
--env PGMCP_DATABASE_URL='postgres://pgmcp:…@db.internal:5432/app?sslmode=require' \
-- pgmcp
Claude Desktop,stdio——从 Releases 安装 .mcpb 安装包(参见安装),或者手动将相同配置写入 claude_desktop_config.json:
{
"mcpServers": {
"pgmcp": {
"command": "pgmcp",
"env": {
"PGMCP_DATABASE_URL": "postgres://pgmcp:…@db.internal:5432/app?sslmode=require"
}
}
}
}
HTTP——在静态 bearer 密钥保护下使用 Streamable HTTP,适用于共享部署。pgmcp 使用纯 HTTP,不会自行终止 TLS;请在反向代理后通过回环地址运行。
PGMCP_DATABASE_URL='postgres://pgmcp:…@db.internal:5432/app?sslmode=require' \
PGMCP_AUTH_MODE=static \
PGMCP_API_KEYS="$(openssl rand -hex 32)" \
pgmcp --transport http --listen 127.0.0.1:8080
claude mcp add pgmcp --transport http https://pgmcp.example.com/mcp \
--header "Authorization: Bearer <key>"
TLS 终止、流式传输所需的代理设置、针对身份提供商的 JWT 身份验证,以及将 pgmcp 配置为 claude.ai 自定义连接器的方法,均见 docs/DEPLOYING.md。
工具
| 工具 | 回答的问题 |
|---|---|
top_queries | 整个服务中哪些语句运行缓慢或开销高?按总耗时、平均耗时、调用次数、行数或读取的块数对 pg_stat_statements 排名。 |
explain | 这条 语句为什么运行缓慢?显示计划树、耗费最多自身时间的节点、计划警告,以及稳定的 plan_hash,以便与之后的运行结果进行比较。 |
index_health | 哪些索引可以删除,哪些索引未能发挥作用?包括从未扫描、重复、无效和膨胀的索引。 |
table_health | 自动清理在哪些地方落后了?按表显示死元组比例、上次清理/分析时间、顺序扫描与索引扫描情况,以及估算的膨胀程度。 |
lock_waits | 这个查询为什么会卡住?显示当前锁等待图:谁被阻塞、谁在阻塞,以及是否存在构成死锁的循环。 |
connections | 服务当前在做什么,距离 max_connections 上限还有多远?按状态、等待事件、应用、用户或数据库分组显示后端进程,包括事务空闲会话。 |
replication | 备用节点落后了多少,哪个槽位正在保留 WAL?显示主/备用角色、各备用节点的延迟(字节和毫秒)、槽位以及当前 WAL 速率。 |
config_check | 这个服务的调优是否合理?根据内存、自动清理、WAL 和连接启发式规则检查 pg_settings,为每项设置给出 ok/review/warn 判定和说明。 |
query | 其他八个工具无法涵盖的所有内容。在 READ ONLY 事务中执行一条只读 SELECT/EXPLAIN/SHOW,并受行数上限和语句超时限制,支持 $1..$n 绑定参数。 |
每个工具都标注了 readOnlyHint: true、destructiveHint: false、idempotentHint: true、openWorldHint: false,并返回类型化的输出架构。
query 是唯一支持自由格式 SQL 的工具,而且是可选的。--disable-query 会将其从工具目录中完全移除——只需要八个诊断工具的部署可以完全不提供任何临时 SQL 接口。--query-schemas=public,app 则将其限制为指定的架构;由于 analyze=true 会执行语句,它也会限制 explain。请阅读 docs/SECURITY.md,了解此选项会阻止和不会阻止的内容。
资源与提示词
| 资源 | 内容 |
|---|---|
pgmcp://overview | 用于开始排查的服务快照:版本、运行时间、恢复状态、已安装扩展、各数据库大小、缓存命中率,以及与 max_connections 的连接数对比。可缓存 30s。 |
pgmcp://settings | 原始 pg_settings 行。可缓存 5m。 |
| 提示词 | 参数 | 用途 |
|---|---|---|
diagnose_slow_query | sql(必填) | 四步排查:对语句运行 explain,检查计划热点节点涉及的每个架构中的 index_health/table_health,在 top_queries 中查找该语句,然后总结根本原因、证据和建议的索引或改写方案——仅以文本形式写出,绝不执行。 |
配置
每个设置都有一个 --flag 和一个 PGMCP_<KEY> 环境变量。命令行标志优先于环境变量,环境变量优先于默认值。配置错误会以状态码 2 退出,并在一条消息中列出所有有问题的键;运行时故障会以状态码 1 退出。
| 标志 | 环境变量 | 默认值 | 含义 |
|---|---|---|---|
--database-url | PGMCP_DATABASE_URL | —(必填) | Postgres 连接字符串 |
--transport | PGMCP_TRANSPORT | stdio | stdio 或 http |
--listen | PGMCP_LISTEN | 127.0.0.1:8080 | HTTP 监听地址 |
--resource-url | PGMCP_RESOURCE_URL | — | 此服务可供访问的公开源站,用于 OAuth 资源元数据 |
--auth-mode | PGMCP_AUTH_MODE | none | none、static 或 jwt(仅限 HTTP) |
--api-keys | PGMCP_API_KEYS | — | 以逗号分隔的静态 API 密钥;static 模式下必填 |
--jwks-url | PGMCP_JWKS_URL | — | JWK 集 URL;jwt 模式下必填 |
--jwt-issuer | PGMCP_JWT_ISSUER | — | 必需的 iss 声明;jwt 模式下必填 |
--jwt-audience | PGMCP_JWT_AUDIENCE | — | 必需的 aud 声明;jwt 模式下必填 |
--auth-servers | PGMCP_AUTH_SERVERS | — | 以逗号分隔的 OAuth 授权服务器列表,通过 RFC 9728 公告 |
--disable-query | PGMCP_DISABLE_QUERY | false | 完全移除临时 query 工具 |
--query-schemas | PGMCP_QUERY_SCHEMAS | — | 以逗号分隔的架构列表,query 和 explain 工具可读取;未设置时不启用允许列表 |
--max-conns | PGMCP_MAX_CONNS | 4 | Postgres 最大连接数 |
--call-timeout | PGMCP_CALL_TIMEOUT | 60s | 每次工具调用的超时时间 |
--rate-limit | PGMCP_RATE_LIMIT | 60 | 每个主体每分钟的工具调用次数(仅限 HTTP) |
--max-output-bytes | PGMCP_MAX_OUTPUT_BYTES | 1048576 | 单次工具调用结构化内容的大小上限 |
--log-level | PGMCP_LOG_LEVEL | info | debug、info、warn 或 error |
--log-format | PGMCP_LOG_FORMAT | text | text 或 json |
--insecure-no-auth | PGMCP_INSECURE_NO_AUTH | false | 允许在非环回监听地址上使用 auth-mode=none |
--version | — | — | 输出版本并退出 |
身份验证配置仅适用于 HTTP 传输。使用 stdio 时,由操作系统决定调用方身份:启动该二进制文件的父进程,除此之外别无他人。
安全模型
- 通过三种彼此独立的方式实现只读。 使用没有写入权限的专用角色(
pg_monitor加SELECT,并且刻意不授予pg_signal_backend);适配器运行的每条语句都在BEGIN READ ONLY事务中执行,并设置SET LOCAL statement_timeout和lock_timeout = '2s',随后始终回滚;还会在解析器层进行防护,因为只读事务本身无法阻止pg_terminate_backend、pg_read_file、pg_sleep或setval。 - SQL 防护优先采用允许列表。 只允许一条顶层语句,且必须是
SELECT、EXPLAIN或SHOW;语法树中任何位置都不能包含嵌套写入语句;不允许使用FOR UPDATE/FOR SHARE锁定子句或SELECT INTO;也不允许调用被禁止的函数,包括文件访问、备份和 WAL 控制、复制槽、咨询锁、dblink、序列修改和统计信息重置。 - 架构允许列表是防护措施,而非安全边界。
--query-schemas会对解析语句中限定表引用的架构进行不区分大小写的匹配,并限制两个允许调用方提供 SQL 的工具——query和explain,因此使用analyze=true的explain也无法针对被排除的架构执行。允许架构中的视图、返回集合的函数或SECURITY DEFINER函数仍可读取该架构以外的数据。数据库权限才是安全边界;允许列表只是收窄显而易见的访问路径。 - 通过 HTTP 进行身份验证,失败时默认拒绝。 静态密钥会以恒定时间与每个已存储的哈希进行比较,不会提前退出;JWT 会根据 JWK 集验证,且只允许非对称算法(不允许
alg=none,也不会混淆 HMAC),并要求提供iss、aud和exp。验证器在收到 JWKS 前不会持有任何密钥,因此启动时默认拒绝访问,而非默认允许。RFC 9728 受保护资源元数据会公布获取令牌的位置。关闭身份验证时,服务不会在非环回地址上启动。 - 设有资源限制。 包括按主体进行速率限制、每次调用超时、事务中的语句超时和锁超时、
query工具的行数上限、结果结构化内容上限,以及 1 MiB 请求正文大小上限。 - 不会记录任何敏感信息。 工具调用只记录名称、耗时、结果和调用方用户 ID——绝不记录参数、SQL 文本、结果行或错误文本。解析失败时会返回固定措辞,而不是回显语句;连接错误中的 DSN 也会被隐藏。
docs/SECURITY.md 介绍了威胁模型、各层防护的完整说明,以及每层防护无法覆盖的限制。
测试
使用竞态检测器和覆盖率运行测试套件:
go test -race -cover ./...
集成测试需要 Postgres 数据库;未设置 PGMCP_TEST_DSN 时会跳过这些测试。若要使用预加载了 pg_stat_statements 的临时 Postgres 运行测试:
docker run -d --rm --name pg -e POSTGRES_PASSWORD=postgres -p 5544:5432 postgres:16 \
-c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all
docker exec pg psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements"
PGMCP_TEST_DSN="postgres://postgres:postgres@localhost:5544/postgres?sslmode=disable" go test -race -cover ./...
创建并查看覆盖率配置文件:
go test -covermode=count -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
通过官方 MCP 一致性测试套件测试运行中的服务,或使用 Inspector 进行冒烟测试:
npx -y @modelcontextprotocol/conformance server --url http://127.0.0.1:8080/mcp \
--expected-failures .github/conformance-expected-failures.yaml
npx @modelcontextprotocol/inspector --cli http://127.0.0.1:8080/mcp --transport http --method tools/list
贡献
欢迎提交拉取请求。对于重大更改,请先提交议题, 讨论您希望进行的更改。
请务必酌情更新测试。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。