
PostgreSQL
io.github.antonorlov由 GitHub 帳號 antonorlov 發布v0.3.1更新於 Nov 3, 2026
MCP server for PostgreSQL: local, Docker, RDS, Neon, Supabase, or behind an SSH bastion.
概覽
本機 MCP 伺服器,讓助理查詢與檢視 PostgreSQL 資料庫,預設唯讀,可選用 SSH 通道連線。
- 可以做什麼
- 執行唯讀 SQL(SELECT、WITH、EXPLAIN、SHOW),支援 $1 式綁定參數,結果依位元組上限截斷
- 瀏覽資料庫結構:列出 schema、列出某個 schema 中的資料表、檢視資料表的欄位、型別、預設值與主鍵
- 透過 execute 執行 INSERT、UPDATE、DELETE 或 DDL,未明確開啟寫入時會拒絕
- 在啟用該工具時,用 connect_db 於執行階段切換到另一個資料庫
- 透過固定主機金鑰指紋的 SSH 通道存取位於跳板主機後方的資料庫
- 適用情境
- 適合讓助理在不預設給予寫入權限的前提下檢視或查詢 PostgreSQL 資料庫(本機、Docker、RDS、Neon、Supabase)。適用於結構探查、臨時唯讀查詢與資料問題;只有確實需要修改資料時才開啟寫入。
- 執行需求
- 透過 npx 以 stdio 在本機執行,需要 Node.js 20 或更新版本。需要資料庫憑證:DATABASE_URL,或 PG_HOST、PG_PORT、PG_USER、PG_PASSWORD、PG_DATABASE 變數。選用設定涵蓋 TLS(PG_SSLMODE、PG_SSL_CA)、逾時、結果大小、執行階段連線,以及 SSH 通道(PG_SSH_HOST、PG_SSH_USER、PG_SSH_FINGERPRINT 與金鑰或 agent 驗證)。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 PostgreSQL,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
MCP PostgreSQL Server
A Model Context Protocol (MCP) server for PostgreSQL: local, Docker, RDS, Neon, and Supabase databases.
The server is small and auditable, with four runtime dependencies: the MCP SDK,
pg, pg-connection-string, and zod (plus ssh2, an optional dependency used
only for SSH tunneling).
Requires Node.js 20 or newer.
Quick start
The preferred way to configure the server is a single DATABASE_URL:
With PG_ALLOW_WRITE set to "false" the server has read-only access to the
database. This is the default; set it to "true" only if the model must write.
The same JSON works in any MCP client that speaks stdio: VS Code, Cursor, Claude Code, Codex, Windsurf.
Alternatively, set the individual PG_* variables; they are used when
DATABASE_URL is not set:
Manual Installation
Or run directly with:
Connect to your database
Local Postgres:
Postgres in Docker: if the database runs in a container with a published
port, connect to localhost:<published-port> as usual. If the MCP server
itself runs inside a container and the database runs on your host machine,
use host.docker.internal instead of localhost:
Amazon RDS:
Neon:
Supabase:
Tools
Tool availability depends on configuration:
1. query
Execute a read-only SQL statement. Accepts SELECT, WITH ... SELECT,
EXPLAIN, and SHOW. One statement per call - multi-statement input is rejected
by the extended query protocol. In read-only mode (the default) the statement runs
as BEGIN READ ONLY, the query, and ROLLBACK - three commands, roughly two
network round trips with pipelining - so the database itself refuses any write.
With PG_ALLOW_WRITE=true the statement is sent directly, without that wrapper, so a
write run through query would execute - use execute for writes.
Supports PostgreSQL-style $1, $2 prepared-statement parameters; values are bound
by the driver and never spliced into the SQL text.
Returns compact JSON: {"rows": [...], "rowCount": n, "returnedRows": n, "truncated": false}.
When the serialized rows exceed PG_MAX_RESULT_BYTES, only the rows that fit are returned
(returnedRows < rowCount), truncated is true, and a hint suggests adding LIMIT/WHERE
or selecting fewer columns.
2. list_schemas
List all schemas in the connected database.
3. list_tables
List tables in the connected database. Accepts an optional schema parameter (defaults to 'public').
4. describe_table
Get the structure of a specific table (columns, types, nullability, defaults, primary keys). Accepts an optional schema parameter (defaults to 'public').
5. execute - requires PG_ALLOW_WRITE=true
Execute an INSERT, UPDATE, DELETE, or DDL statement. Always registered, but
in read-only mode (the default) it refuses with an error naming PG_ALLOW_WRITE
and changes nothing - the statement never reaches the database. With
PG_ALLOW_WRITE=true it runs: same $1, $2 parameter handling as query, one
complete statement per call, and the connecting role governs what it may do.
Returns {"rowCount": n, "command": "INSERT"}.
6. connect_db - requires PG_ENABLE_RUNTIME_CONNECT=true
Connect to a different PostgreSQL database at runtime using provided
credentials. Not registered by default - prefer configuring credentials
through the environment so they never pass through model-visible arguments.
Session limits (statement_timeout, idle_in_transaction_session_timeout) are
re-applied after every reconnect; read-only reads enforce read-only in their own
BEGIN READ ONLY transaction.
Configuration reference
To reach a database only accessible through a bastion, see SSH tunneling (adds PG_SSH_* variables).
Features
- Read-only by default; writes are an explicit opt-in (
PG_ALLOW_WRITE=true) - Read-only enforced by the engine (
BEGIN READ ONLY), never by client-side SQL parsing - Data access behind a small typed interface; the
pgdriver never leaks past it DATABASE_URLsupport with SSL (sslmode=disable|allow|prefer|require|verify-ca|verify-full, custom CA)- Prepared-statement parameters:
$1-style placeholders, bound by the driver - Result size cap (byte budget) with an explicit
truncatedflag instead of flooding the model's context - Session statement timeout plus a client deadline; transaction poolers may not preserve session settings
- Errors returned as readable tool results with SQLSTATE-based hints, so the model can self-correct
- Survives dropped connections - reconnects lazily instead of crashing
- Optional SSH tunneling (
PG_SSH_*) with mandatory host-key verification, loaded only when configured - MCP tool annotations (read-only / destructive hints) per spec 2025-11-25
- Multi-schema support for database operations
Security
Full details, including the threat model and disclosure process, are in SECURITY.md. The short version:
-
A least-privilege database role is the real boundary. The MCP works with existing credentials; creating or changing roles is not required. A dedicated role is what actually guarantees writes are impossible. On PostgreSQL 14+, the following is a starting point:
(On PostgreSQL 13 or older, grant
SELECTexplicitly instead ofpg_read_all_data- see SECURITY.md.) The server warns on stderr if you connect as a superuser. Read grants do not revoke existing privileges, and defaults remain mutable; available functions, ownership and inherited privileges also matter. -
The engine enforces read-only. There is no client-side SQL parsing. In read-only mode every read runs in a rolled-back
BEGIN READ ONLYtransaction, so PostgreSQL itself - which alone knows what a function, view, or rule does - refuses any write with SQLSTATE 25006 and reverts any session change the statement made. The extended protocol rejects multi-command strings.
Honest framing: the read-only transaction is defense-in-depth on top of the role, not a replacement for it. Read-only mode stops a confused or prompt-injected model from writing to your database; it does not stop prompt injection carried in the row data a query returns. Don't point this server at production - use a replica, a snapshot, or a tightly scoped role. See SECURITY.md.
SSH tunneling
Set PG_SSH_HOST (plus auth and host-key verification) to reach a database that is only accessible
through a bastion (an SSH jump host). The connection string / PG_* fields then describe the
database as seen from the bastion:
- SSH changes only the transport. Read-only enforcement, the result size cap, timeouts, and
connect_dbbehave exactly as on a direct connection, and no extra SQL is sent per query. - Host-key verification is mandatory via a pinned
PG_SSH_FINGERPRINT- the tunnel will not connect without it, so a man-in-the-middle bastion is refused. Get the fingerprint over a channel you trust, most trustworthy first:- on the bastion itself, or from its admin:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub(no network involved); - from your existing
~/.ssh/known_hosts, if you already reach the host overssh:ssh-keygen -lF bastion.example.com; - fetched from the host:
ssh-keyscan bastion.example.com | ssh-keygen -lf -(trust this only when run from a network position you trust - it accepts whatever the host returns).
- on the bastion itself, or from its admin:
- TLS validates the real database hostname. With
verify-full, the certificate is checked against the database's own hostname (e.g.db.internal), not the loopback the tunnel binds locally, andrejectUnauthorizedis pinned on so an inheritedNODE_TLS_REJECT_UNAUTHORIZED=0cannot disable it. ssh2is an optional dependency, loaded only whenPG_SSH_HOSTis set, so a direct connection never initializes it. npm installs optional dependencies by default; runnpm install --omit=optionalto skip it entirely (a direct connection does not need it).
A tunneled connection that fails reports a stable SSH_* code - see Error Handling.
Error Handling
SQL and connection failures are returned as tool results (isError: true)
with a message, the SQLSTATE code, and a hint. PostgreSQL's own server hint is
used when present; otherwise these fallbacks apply:
Over an SSH tunnel, a failure carries a stable code (and, where
the cause is determinate, a hint naming the setting to fix), so the failing phase is unambiguous:
A genuine PostgreSQL error through a healthy tunnel keeps its own code (e.g. 28P01 for wrong
database credentials), not an SSH code.
Migrating from 0.1.x
Not needed for new installs. Two behavior changes since 0.1.x:
- Read-only by default. The
executetool is always visible but refuses writes (with an error naming the flag) unlessPG_ALLOW_WRITE=true, and every read runs inside an engine-enforcedREAD ONLYtransaction. If your workflow writes to the database, set"PG_ALLOW_WRITE": "true"to restore 0.1.x behavior. connect_dbis disabled by default. Runtime connection switching (passing credentials through tool arguments) requiresPG_ENABLE_RUNTIME_CONNECT=true; otherwise connection details come only from the environment.
Tool names, parameter names, and PG_* variables are unchanged. Result payloads
are now structured compact JSON for every tool (e.g. query returns
{rows, rowCount, returnedRows, truncated} instead of a bare row array) - see
CHANGELOG.md for the exact shapes before updating anything that
parses tool output.
License
MIT
來源:README.md,提交 d75a277
工具
0版本歷史
1- v0.3.1最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分