
Postgres (read-only transactions)
io.github.Poudel0由 GitHub 帳號 Poudel0 發布v0.1.3更新於 Nov 3, 2026
Drop-in replacement for @modelcontextprotocol/server-postgres that is actually read-only.
概覽
Postgres (read-only transactions) 的本機 MCP 服務;無需登入;STDIO。
暫無 AI 概覽:以下資訊來自註冊中心條目和服務本身。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Postgres (read-only transactions),將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
postgres-mcp-safe
A drop-in replacement for the deprecated @modelcontextprotocol/server-postgres, but actually read-only.
Lets AI tools (Claude, Cursor, Zed, ...) query a Postgres database, read its schema and explain queries. Swap the package name in your MCP config and keep everything else.
[Postgres (read-only transactions) MCP server]
Migrating from server-postgres
Docker: docker run -i --rm ghcr.io/poudel0/postgres-mcp-safe postgresql://host.docker.internal:5432/mydb.
Binaries for Linux, macOS and Windows are on the releases page.
One catch: if your URL logs in as a superuser (like Docker's default postgres user), every call is refused
until you either create a read-only role (recommended) or add --allow-superuser
before the URL. A superuser can get around a read-only transaction, so we won't pretend otherwise.
The old server's query tool and postgres://.../<table>/schema resources work the same. See
Differences for the small, deliberate changes.
Why
The old server's "read-only" mode can be broken with COMMIT; DROP TABLE ...
(Datadog Security Labs, 2025-08-21).
A fix was merged upstream but never published, and the package is deprecated with no official successor.
Flags
Flags go before the URL.
Each call opens a fresh connection (that's part of the safety model). Against a remote database over TLS that costs a
few round trips: about 0.5 s per call at 50 ms latency. On Postgres 17+ you can save one round trip by adding
sslnegotiation=direct to the URL.
Limits can't be turned off; 0 is an error. The URL can also be a keyword DSN (host=db dbname=app), and the
standard PG* environment variables (PGPASSWORD, ...) are read as libpq would.
Tools
How read-only is enforced
Postgres enforces it, not a SQL parser. Every call:
- Opens a fresh connection (no session state survives a call) and starts a
READ ONLYtransaction. - Sends your SQL as a single protocol-level Parse message. Postgres rejects more than one statement there, so
COMMIT; ...fails before anything runs. - Runs it only if Postgres says it returns rows.
COMMIT,SET,DO,COPY,CALL,PREPAREand friends are rejected without running. - Applies
statement_timeout, a client deadline, and row and byte caps. - Closes the connection, which ends the transaction.
The bypass suite runs every known payload against a real database and checks a canary table after each one:
Found a bypass? Open an issue. It becomes a test row before the fix.
Use a read-only role too
This server makes each call read-only at the transaction level. Some things are out of a transaction's reach, and only the database role stops them:
dblink_exec(...)opens a separate session that isn't read-only.pg_terminate_backend(...)kills other connections.- A superuser can read server files (
pg_read_file,pg_ls_dir): read-only stops writes, not reads. - A superuser can write server files with
lo_export, even inside a read-only transaction.
So connect as a role that can only read:
Because of the last two, the server refuses superuser roles (and members of them) unless you pass --allow-superuser.
Differences from server-postgres
- Errors in a tool call come back as a tool result with
isError: trueand the Postgres message and SQLSTATE, so the model can fix its SQL. The old server sent a JSON-RPC error. resources/readonly shows columns of thepublictable, in column order. The old one mixed in columns from same-named tables in other schemas.- Percent-encoded table names in resource URIs are decoded (the old server never matched them).
- Values are what Postgres prints, typed where it's clear: booleans, numbers (including
bigintandnumeric) andjsonare JSON values; everything else is a string such as"2026-01-02 03:04:05+00","\\x0102"or"{x,y}".NaNis"NaN"(the old server gavenull). - Statements that return no rows (
SET,DO,COPY, ...) are rejected. The old server ran them and returned[].
Development
DATABASE_URL must be a superuser: the fixture resets the public schema and creates the mcp_ro role. Use a
throwaway database.
來源:README.md,提交 b7e7ce5
工具
0版本歷史
2- v0.1.3最新Nov 3, 2026
- v0.1.2Nov 1, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分
