关于 MCP PostgreSQL Server
MCP PostgreSQL Server 是一个用于 PostgreSQL 数据库的 MCP 服务,支持本地、Docker、RDS、Neon 和 Supabase 等环境。默认只读,写入需要显式开启,并依靠数据库本身的只读事务进行保护。
主要功能
- 01通过 DATABASE_URL 或 PG_* 变量配置连接
- 02默认只读,PG_ALLOW_WRITE 显式开启写入
- 03只读事务强制执行,结果大小受限
- 04支持 $1 形式的预处理参数
- 05可选 SSH 隧道与主机密钥验证
适用场景
- 01让 AI 助手查询和了解数据库表结构
- 02通过只读账号分析生产副本或快照数据
- 03经由堡垒机访问内网 PostgreSQL 数据库
MCP 相关
该项目是 MCP 服务,向 MCP 客户端提供 query、list_tables、describe_table 等数据库工具,以及可选的 execute 和 connect_db 工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y mcp-postgres-serverDATABASE_URL密钥Full connection string (preferred). Supports sslmode in the URL.PG_HOSTDatabase host (fallback when DATABASE_URL is not set).PG_PORTDatabase port.PG_USERDatabase user.PG_PASSWORD密钥Database password.PG_DATABASEDatabase name.PG_ALLOW_WRITEWhen true, execute performs writes and reads are sent directly. Off (default) is read-only: execute refuses writes and each read runs in a READ ONLY transaction.PG_SSLMODETLS mode. require/allow/prefer encrypt without verifying the certificate; verify-ca/verify-full verify it (supply a CA via PG_SSL_CA). Unlike libpq, allow/prefer do not fall back to plaintext, so a server without TLS needs disable.PG_SSL_CAPath to a CA certificate file. Setting it by itself implies verify-full.PG_ENABLE_RUNTIME_CONNECTRegister the connect_db tool (runtime credential switching).PG_MAX_RESULT_BYTESByte budget for a query result sent to the model. Whole rows are kept while they fit; over the budget returnedRows < rowCount and truncated is true.PG_STATEMENT_TIMEOUTStatement timeout in milliseconds, applied to every session.PG_CONNECT_TIMEOUTTimeout in milliseconds for a single connect attempt (raise it for slow links or SSH tunnels).PG_SSH_HOSTSSH bastion host. Setting it enables tunneling: the server reaches the database only through an SSH tunnel to this host. Needs the ssh2 optional dependency.PG_SSH_PORTSSH bastion port.PG_SSH_USERSSH username.PG_SSH_PRIVATE_KEY密钥Path to a private key file. If unset, auth falls back like ssh: a running agent (SSH_AUTH_SOCK), then a default key (~/.ssh/id_ed25519, id_rsa, id_ecdsa).PG_SSH_PASSPHRASE密钥Passphrase for the private key, if encrypted.PG_SSH_AGENTtrue to use the ambient agent (SSH_AUTH_SOCK), or an explicit socket path / Windows named pipe.PG_SSH_PASSWORD密钥SSH login password. Opt-in; a key or agent takes precedence. Prefer keys, a bastion often disables password auth.PG_SSH_FINGERPRINTPinned host-key fingerprint (SHA256:...). Host-key verification is mandatory and set only this way: without it the tunnel refuses to connect. Get it with ssh-keygen -lF host.PG_SSH_KEEPALIVE_INTERVALSSH keepalive interval in ms; the tunnel drops after 3 unanswered keepalives, and the next call reconnects.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
5收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| sql | string | 是 | 一条 SQL 语句。参数请使用 $1、$2、...。 |
| params | array | 否 | 绑定到 $1、$2、... 占位符的位置参数值。 |
详细介绍
MCP PostgreSQL Server
用于 PostgreSQL 的模型上下文协议(MCP)服务,支持本地、Docker、RDS、Neon 和 Supabase 数据库。
该服务体积小且易于审计,只有四个运行时依赖:MCP SDK、
pg、pg-connection-string 和 zod(以及 ssh2,这是仅用于 SSH 隧道的可选依赖)。
需要 Node.js 20 或更高版本。
快速开始
配置该服务的首选方式是使用单个 DATABASE_URL:
{
"mcpServers": {
"postgres": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mcp-postgres-server"],
"env": {
"DATABASE_URL": "postgres://user:password@localhost:5432/mydb",
"PG_ALLOW_WRITE": "false"
}
}
}
}
将 PG_ALLOW_WRITE 设为 "false" 时,该服务对数据库具有只读访问权限。这是默认值;只有模型必须写入时才将其设为 "true"。
同一份 JSON 适用于任何使用 stdio 的 MCP 客户端:VS Code、Cursor、Claude Code、Codex、Windsurf。
或者,设置各个 PG_* 变量;仅当未设置 DATABASE_URL 时才会使用这些变量:
{
"mcpServers": {
"postgres": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mcp-postgres-server"],
"env": {
"PG_HOST": "your_host",
"PG_PORT": "5432",
"PG_USER": "your_user",
"PG_PASSWORD": "your_password",
"PG_DATABASE": "your_database",
"PG_ALLOW_WRITE": "false"
}
}
}
}
手动安装
npm install mcp-postgres-server
或者直接运行:
npx mcp-postgres-server
连接到数据库
本地 Postgres:
DATABASE_URL=postgres://mcp_readonly:secret@localhost:5432/mydb
**Docker 中的 Postgres:**如果数据库在已发布端口的容器中运行,请照常连接到 localhost:<published-port>。如果 MCP 服务本身 在容器中运行,而数据库在主机上运行,请使用 host.docker.internal 替代 localhost:
DATABASE_URL=postgres://mcp_readonly:[email protected]:5432/mydb
Amazon RDS:
DATABASE_URL=postgres://mcp_readonly:[email protected]:5432/mydb?sslmode=require
Neon:
DATABASE_URL=postgres://mcp_readonly:[email protected]/mydb?sslmode=require
Supabase:
DATABASE_URL=postgres://postgres.xxxxxxxx:[email protected]:5432/postgres?sslmode=require
工具
工具是否可用取决于配置:
| 工具 | 可用性 |
|---|---|
query、list_schemas、list_tables、describe_table | 始终可用 |
execute | 始终可用(除非 PG_ALLOW_WRITE=true,否则会拒绝写入) |
connect_db | 仅当 PG_ENABLE_RUNTIME_CONNECT=true 时可用 |
1. query
执行只读 SQL 语句。接受 SELECT、WITH ... SELECT、
EXPLAIN 和 SHOW。每次调用只能执行一条语句——扩展查询协议会拒绝多语句输入。在只读模式(默认)下,语句会按 BEGIN READ ONLY、查询和 ROLLBACK 的顺序执行——共三个命令,使用流水线时大约需要两次网络往返——因此数据库本身会拒绝任何写入。
设置 PG_ALLOW_WRITE=true 时,语句会直接发送,不会使用上述封装,因此通过 query 执行的写入会成功;写入请使用 execute。
支持 PostgreSQL 风格的 $1, $2 预处理语句参数;值由驱动绑定,绝不会插入 SQL 文本。
use_mcp_tool({
server_name: "postgres",
tool_name: "query",
arguments: {
sql: "SELECT * FROM users WHERE id = $1",
params: [1]
}
});
返回简洁的 JSON:{"rows": [...], "rowCount": n, "returnedRows": n, "truncated": false}。
当序列化后的行超过 PG_MAX_RESULT_BYTES 时,只返回可容纳的行(returnedRows < rowCount),truncated 为 true,并提示添加 LIMIT/WHERE 或选择更少的列。
2. list_schemas
列出已连接数据库中的所有模式。
use_mcp_tool({
server_name: "postgres",
tool_name: "list_schemas",
arguments: {}
});
3. list_tables
列出已连接数据库中的表。接受可选的模式参数(默认为 'public')。
// List tables in the 'public' schema (default)
use_mcp_tool({
server_name: "postgres",
tool_name: "list_tables",
arguments: {}
});
// List tables in a specific schema
use_mcp_tool({
server_name: "postgres",
tool_name: "list_tables",
arguments: {
schema: "my_schema"
}
});
4. describe_table
获取特定表的结构(列、类型、是否可为空、默认值、主键)。接受可选的模式参数(默认为 'public')。
use_mcp_tool({
server_name: "postgres",
tool_name: "describe_table",
arguments: {
table: "users",
schema: "my_schema" // optional
}
});
5. execute - 需要 PG_ALLOW_WRITE=true
执行 INSERT、UPDATE、DELETE 或 DDL 语句。始终会注册此工具,但在只读模式(默认)下会拒绝执行,并返回一条指出 PG_ALLOW_WRITE 的错误,且不会进行任何更改——语句不会到达数据库。设置 PG_ALLOW_WRITE=true 时则会执行:参数处理方式与 query 中的 $1, $2 相同,每次调用执行一条完整语句,且可执行的操作由连接所用的角色决定。
返回 {"rowCount": n, "command": "INSERT"}。
use_mcp_tool({
server_name: "postgres",
tool_name: "execute",
arguments: {
sql: "INSERT INTO users (name, email) VALUES ($1, $2)",
params: ["John Doe", "[email protected]"]
}
});
6. connect_db - 需要设置 PG_ENABLE_RUNTIME_CONNECT=true
使用提供的凭据在运行时连接到其他 PostgreSQL 数据库。默认不注册此工具——建议通过环境配置凭据,避免凭据出现在模型可见的参数中。每次重新连接后都会重新应用会话限制(statement_timeout、idle_in_transaction_session_timeout);只读查询会在各自的 BEGIN READ ONLY 事务中强制执行只读操作。
use_mcp_tool({
server_name: "postgres",
tool_name: "connect_db",
arguments: {
host: "localhost",
port: 5432,
user: "your_user",
password: "your_password",
database: "your_database"
}
});
配置参考
| 变量 | 默认值 | 描述 |
|---|---|---|
DATABASE_URL | - | 完整连接字符串(首选)。支持 URL 中的 ?sslmode=。 |
PG_HOST | - | 数据库主机(未设置 DATABASE_URL 时的备用项) |
PG_PORT | 5432 | 数据库端口 |
PG_USER | - | 数据库用户 |
PG_PASSWORD | - | 数据库密码 |
PG_DATABASE | - | 数据库名称 |
PG_ALLOW_WRITE | false | 设为 true 时,execute 会执行写入,读取操作会直接发送。关闭(默认)时为只读:execute 会拒绝写入,且每次读取都会在 READ ONLY 事务中执行 |
PG_SSLMODE | - | disable | allow | prefer | require | verify-ca | verify-full。require/allow/prefer 会加密但不验证证书;verify-ca/verify-full 会验证证书(通过 PG_SSL_CA 提供 CA)。无法识别的值会导致启动失败。**限制:**与 libpq 不同,allow/prefer 不会回退到明文连接(node-postgres 不支持机会性 SSL),因此不支持 TLS 的服务器需要使用 disable。 |
PG_SSL_CA | - | CA 证书文件的路径。单独设置此项会隐含启用 verify-full |
PG_ENABLE_RUNTIME_CONNECT | false | 注册 connect_db 工具(运行时切换凭据) |
PG_MAX_RESULT_BYTES | 32768 | 发送给模型的 query 结果的字节数上限。只要完整的行能放入上限内,就会保留这些行;超出上限时,returnedRows < rowCount 且 truncated: true(如果连第一行都放不下,returnedRows 为 0,并附带提示)。约 32 KiB ≈ 8k 个 token;严格客户端可调低,客户端允许更多时可调高。 |
PG_STATEMENT_TIMEOUT | 30000 | 语句超时时间(毫秒),应用于每个会话 |
PG_CONNECT_TIMEOUT | 10000 | 单次连接尝试的超时时间(毫秒)(网络链路较慢或使用 SSH 隧道时可调高) |
如需连接只能通过堡垒机访问的数据库,请参阅 SSH 隧道(会添加 PG_SSH_* 变量)。
功能
- 默认只读;写入需显式启用(
PG_ALLOW_WRITE=true) - 由引擎强制执行只读(
BEGIN READ ONLY),而非通过客户端 SQL 解析实现 - 数据访问通过小型类型化接口进行;
pg驱动不会泄漏到接口之外 - 支持带 SSL 的
DATABASE_URL(sslmode=disable|allow|prefer|require|verify-ca|verify-full,以及自定义 CA) - 预处理语句参数:
$1样式的占位符,由驱动绑定 - 限制结果大小(字节数上限),并明确标记
truncated,而非让结果淹没模型上下文 - 会话语句超时加客户端截止时间;事务池化器可能不会保留会话设置
- 以易读的工具结果形式返回错误,并提供基于 SQLSTATE 的提示,帮助模型自行纠正
- 连接断开后仍可继续工作——按需重新连接,而不会崩溃
- 可选 SSH 隧道(
PG_SSH_*),强制验证主机密钥,仅在配置时加载 - 按规范 2025-11-25 提供 MCP 工具注解(只读/破坏性提示)
- 支持数据库操作的多模式
安全性
威胁模型和披露流程等完整信息,请参阅 SECURITY.md。简而言之:
-
最小权限数据库角色才是真正的边界。 MCP 使用现有凭据;无需创建或更改角色。只有专用角色才能真正保证无法写入。 在 PostgreSQL 14+ 上,以下内容可作为起点:
CREATE ROLE mcp_readonly LOGIN PASSWORD 'change-me'; GRANT CONNECT ON DATABASE your_database TO mcp_readonly; GRANT pg_read_all_data TO mcp_readonly; -- adds read privileges ALTER ROLE mcp_readonly SET default_transaction_read_only = on; -- read-only by default(在 PostgreSQL 13 或更早版本上,请显式授予
SELECT,而不是使用pg_read_all_data——详见 SECURITY.md。)如果你以超级用户身份连接,服务会在 stderr 上发出警告。读取权限不会撤销现有权限,默认设置仍可更改;可用函数、所有权和继承的权限也很重要。 -
引擎会强制执行只读。 不会在客户端解析 SQL。在只读模式下,每次读取都会在回滚的
BEGIN READ ONLY事务中运行,因此 PostgreSQL 本身——只有它才知道函数、视图或规则的实际行为——会使用 SQLSTATE 25006 拒绝任何写入,并撤销语句所做的任何会话更改。扩展协议会拒绝包含多条命令的字符串。
**准确地说:**只读事务是在角色之上的纵深防御,而非角色的替代方案。只读模式可以阻止被误导或遭到提示词注入的模型向数据库写入;但无法阻止查询返回的行数据中携带的提示词注入。不要将此服务指向生产环境——请使用副本、快照或严格限定权限的角色。详见 SECURITY.md。
SSH 隧道
设置 PG_SSH_HOST(以及身份验证和主机密钥验证),即可连接只能通过堡垒机(SSH 跳板主机)访问的数据库。连接字符串 / PG_* 字段描述的是从堡垒机看来的数据库:
{
"mcpServers": {
"postgres": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mcp-postgres-server"],
"env": {
"DATABASE_URL": "postgres://mcp_readonly:[email protected]:5432/mydb?sslmode=verify-full",
"PG_SSH_HOST": "bastion.example.com",
"PG_SSH_USER": "jump",
"PG_SSH_PRIVATE_KEY": "/home/me/.ssh/id_ed25519",
"PG_SSH_FINGERPRINT": "SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}
| 变量 | 默认值 | 说明 |
|---|---|---|
PG_SSH_HOST | - | SSH 堡垒机主机。设置此项即可启用隧道:服务只能通过到此主机的 SSH 隧道访问数据库(见下文)。可选功能;需要可选依赖项 ssh2。 |
PG_SSH_PORT | 22 | SSH 堡垒机端口 |
PG_SSH_USER | - | SSH 用户名 |
PG_SSH_PRIVATE_KEY | - | 私钥文件的路径。若未设置,身份验证将像 ssh 一样依次尝试:正在运行的 Agent(SSH_AUTH_SOCK),然后是默认密钥(~/.ssh/id_ed25519、id_rsa、id_ecdsa) |
PG_SSH_PASSPHRASE | - | 加密私钥的密码短语 |
PG_SSH_AGENT | - | 使用当前 Agent(SSH_AUTH_SOCK)时设为 true,也可指定套接字路径 / Windows 命名管道(\\.\pipe\openssh-ssh-agent) |
PG_SSH_PASSWORD | - | SSH 登录密码。需主动启用;优先使用密钥或 Agent。建议使用密钥——堡垒机通常会禁用密码身份验证。 |
PG_SSH_FINGERPRINT | - | 固定的主机密钥指纹(SHA256:...)。必须通过此项进行主机密钥验证:若未设置,隧道将拒绝连接(故障时关闭)。可使用 ssh-keygen -lF host 获取(读取你的 known_hosts),或使用 ssh-keyscan host | ssh-keygen -lf - 获取(参见下方的信任说明) |
PG_SSH_KEEPALIVE_INTERVAL | 15000 | SSH 保活间隔,单位为毫秒;连续 3 次保活无响应后隧道将断开,下次调用时重新连接 |
- SSH 只改变传输方式。 只读限制、结果大小上限、超时和
connect_db的行为与直接连接完全相同,并且每次查询都不会额外发送 SQL。 - 必须通过固定的
PG_SSH_FINGERPRINT进行主机密钥验证——未设置时隧道不会连接,因此会拒绝中间人控制的堡垒机。请通过可信渠道获取指纹,以下方式按可信度从高到低排列:- 在堡垒机上或向其管理员获取:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub(不涉及网络); - 从现有的
~/.ssh/known_hosts中获取,前提是你已通过ssh连接过该主机:ssh-keygen -lF bastion.example.com; - 从主机获取:
ssh-keyscan bastion.example.com | ssh-keygen -lf -(仅在可信的网络环境中运行时才可信——此命令会接受主机返回的任何内容)。
- 在堡垒机上或向其管理员获取:
- TLS 会验证真实的数据库主机名。 使用
verify-full时,证书会根据数据库自身的主机名(例如db.internal)进行验证,而不是根据隧道在本地绑定的环回地址;同时会固定启用rejectUnauthorized,防止继承的NODE_TLS_REJECT_UNAUTHORIZED=0将其禁用。 ssh2是可选依赖项,仅在设置PG_SSH_HOST时加载,因此直接连接时绝不会初始化它。npm 默认会安装可选依赖项;运行npm install --omit=optional可完全跳过安装(直接连接不需要它)。
隧道连接失败时会返回稳定的 SSH_* 错误代码——参见错误处理。
错误处理
SQL 和连接失败会作为工具结果返回(isError: true),
其中包含消息、SQLSTATE 代码和提示。如果 PostgreSQL 服务器提供了提示,则使用该提示;
否则使用以下备用提示:
| code | 含义 | 首先检查 |
|---|---|---|
28P01 | 身份验证失败 | PG_USER / PG_PASSWORD |
3D000 | 数据库不存在 | PG_DATABASE |
42P01 | 未找到关系 | 调用 list_tables |
42703 | 未找到列 | 调用 describe_table |
57014 | 查询已取消(超时或收到取消请求) | 如果是超时,添加 LIMIT / 简化查询,或提高 PG_STATEMENT_TIMEOUT |
25006 | 事务为只读 | 来源可能是只读角色、副本、服务器默认设置,或(对于 query)只读包装器;execute 写入操作需要设置 PG_ALLOW_WRITE=true |
ECONNREFUSED / ENOTFOUND | 无法连接到数据库主机或解析其地址 | PG_HOST / PG_PORT / DATABASE_URL |
通过 SSH 隧道 连接时,失败会携带稳定的 code(如果原因明确,还会提供指出需修正设置的提示),因此可以明确判断失败阶段:
| code | 含义 | 首先检查 |
|---|---|---|
SSH_CONFIG_INVALID | SSH 配置无效,包括格式错误的 PG_SSH_FINGERPRINT | PG_SSH_* 值 |
SSH_KEY_INVALID | 密钥不可读、无法解析、是公钥,或已加密但没有正确的密码短语(使用正确的 PG_SSH_PASSPHRASE 即可使用加密密钥) | PG_SSH_PRIVATE_KEY、PG_SSH_PASSPHRASE |
SSH_CONNECT_FAILED | 无法连接到堡垒机,或 SSH 设置因未分类原因失败 | PG_SSH_HOST、PG_SSH_PORT、网络可达性 |
SSH_TIMEOUT | 堡垒机未能及时响应 | 网络/防火墙、PG_CONNECT_TIMEOUT |
SSH_AUTH_FAILED | 堡垒机拒绝了身份验证 | PG_SSH_USER 以及当前使用的密钥/代理/密码 |
SSH_HOST_KEY_MISMATCH | 主机密钥与 PG_SSH_FINGERPRINT 不匹配(值已过期或遭遇中间人攻击) | 重新获取指纹 |
SSH_FORWARD_FAILED | 隧道已建立,但堡垒机无法连接到数据库 | 从堡垒机视角看到的数据库主机和端口 |
SSH_CONNECTION_LOST | 已建立的隧道在会话中途断开 | 暂时性问题;下次调用时会重新连接 |
通过正常工作的隧道传递的真实 PostgreSQL 错误仍会保留其自身代码(例如,数据库凭据错误会返回 28P01),而不是 SSH 代码。
从 0.1.x 迁移
新安装无需迁移。自 0.1.x 起有两项行为变更:
- 默认只读。
execute工具始终可见,但除非设置PG_ALLOW_WRITE=true,否则会拒绝写入(并指出相应标志);所有读取操作都会在引擎强制执行的READ ONLY事务中运行。如果工作流会写入数据库,请设置"PG_ALLOW_WRITE": "true"以恢复 0.1.x 的行为。 - 默认禁用
connect_db。 运行时切换连接(通过工具参数传递凭据)需要设置PG_ENABLE_RUNTIME_CONNECT=true;否则,连接详情只会从环境中读取。
工具名称、参数名称和 PG_* 变量均未更改。现在,每个工具的结果负载都是结构化的紧凑 JSON(例如,query 返回 {rows, rowCount, returnedRows, truncated},而不是裸行数组)——在更新任何解析工具输出的内容之前,请参阅 CHANGELOG.md 了解确切的数据结构。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。