@yawlabs/postgres-mcpBLOCK
Read-only-by-default MCP server for PostgreSQL. Query, introspect schemas, explain plans, health checks.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
[](https://yaw.sh/mcp/install?name=Postgres&command=npx&args=-y%2C%40yawlabs%2Fpostgres-mcp&description=Query%20PostgreSQL%20-%20schema%20introspection%2C%20EXPLAIN%20plans%2C%20health%20diagnostics%2C%20read-only%20by%20default&source=https%3A%2F%2Fgithub.com%2FYawLabs%2Fpostgres-mcp)
One click adds this to your local Yaw MCP config so it's available in every Yaw Terminal session. Or install manually below.
[](https://www.npmjs.com/package/@yawlabs/postgres-mcp) [](https://opensource.org/licenses/MIT)
Query a PostgreSQL database from Claude Code, Cursor, and any MCP client. Read-only by default - writes opt in via a single env var - so an agent can't silently drop your tables.
Built and maintained by Yaw Labs.
What's new in 0.12
An index advisor, opt-in audit logging, structured tool output, and support for current-revision MCP clients. Full detail in the CHANGELOG.
- `pg_index_advisor` recommends indexes for a workload and keeps only the ones that measurably lower estimated cost. Candidates are costed with HypoPG hypothetical indexes, never created on disk, and the search knows that PostgreSQL 18's skip scan changes which multi-column indexes are useful.
- Opt-in audit logging of the SQL tools send: one JSON line per audited statement, to stderr or a file. Bound parameter values are never recorded. Off by default, and not a complete record -- see Audit logging.
- Structured tool output. Every tool declares an
outputSchemaand returnsstructuredContentalongside the unchanged text block, so anything reading the text today keeps working. - Both MCP protocol eras. The server used to speak only the legacy (2025) protocol revisions, which a client on the current 2026-07-28 revisi
ec971717547bOBSERVED · 2026-10-12Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add postgres-mcp -- npx -y @yawlabs/[email protected]
Exposed tools (23)
19 read · 2 write · 2 destructive. Blast radius: 2 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
pg_advisor | read | Rolled-up DBA lint pass. One call returns four categories of findings:\n |
pg_describe_table | read | Describe a relation: kind (table / view / materialized_view / partitioned_table / foreign_table), |
pg_explain | read | Get the query plan for a SQL statement. By default, this uses plain EXPLAIN (no execution). |
pg_health | read | Quick health snapshot: server version, database size, connection counts measured against |
pg_index_advisor | read | Recommend indexes for a workload, and prove each one pays for itself before recommending it. |
pg_inspect_locks | read | Show current lock contention: which sessions are blocked and who is blocking them. |
pg_io_stats | read | I/O observability: cumulative per-backend-type I/O from |
pg_kill | destructive | Cancel a running query (SIGINT-equivalent) or terminate a backend connection (SIGTERM- |
pg_list_extensions | read | List installed PostgreSQL extensions. Returns name, version, schema, and description. |
pg_list_functions | read | List functions, procedures, and aggregates in a schema. Returns name, arguments, return type, |
pg_list_roles | read | List database roles (users and groups) with their login/superuser/createdb/createrole |
pg_list_schemas | read | List non-system schemas in the database. Excludes |
pg_list_tables | read | List tables (and optionally views) in a schema. Returns name, type (table/view/materialized |
pg_list_views | read | List views and materialized views in a schema with their SQL definitions. Use this over |
pg_query | write | Run a SQL query against the configured PostgreSQL database. Postgres itself is the |
pg_readonly | write | Run a SQL statement with no persistent data changes. Always executes inside a |
pg_replication_status | read | Replication overview: configured replication slots, connected replicas (from |
pg_search_columns | read | Search for columns by name across all user schemas. Supports SQL LIKE patterns |
pg_seq_scan_tables | read | Tables with high sequential-scan counts relative to index scans - the first place to |
pg_table_bloat | read | Estimate table bloat (dead tuples + free space) for tables in a schema. Returns live |
pg_table_privileges | destructive | Show which roles have which privileges (SELECT, INSERT, UPDATE, DELETE, TRUNCATE, |
pg_top_queries | read | Top N queries by total or mean execution time. Requires the |
pg_unused_indexes | read | Indexes that have never been scanned or have very low usage, largest first. Each unused |
Trust audit
BLOCKgrade D · trust 69/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (3 observation(s))
- Network
- declared (7 observation(s))
- Shell
- declared (3 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (17)
const SSH = 'ssh -i ~/.ssh/gh_woods -o IdentitiesOnly=yes';
if (raw === "0" || raw === "false") return { rejectUnauthorized: false };`postgres://u:[email protected]:1/x` with `POSTGRES_AUDIT_LOG=stderr` (24 calls;
const SANDBOX_DSN = "postgres://u:hunter2@stub-host:6543/db";
pg_kill, pg_table_privileges
return new Function(`${pieces}\nreturn { pickNewest, floor: OAM_MIN };`)() as {return new Function(`${pieces}\nreturn runtimePlan;`)() as RuntimePlan;return new Function(
const remedyFor = new Function(
const { stripPermissionOptions, withoutPermissionOptions, permissionReachesChildren } = new Function(const LAUNCHER = fileURLToPath(new URL("../../bin/postgres-mcp.mjs", import.meta.url));const readme = readFileSync(new URL("../../README.md", import.meta.url), "utf8");const srcRoot = new URL("../../src/", import.meta.url);const readme = readFileSync(new URL("../../README.md", import.meta.url), "utf8");assert.deepEqual(getSslConfig(), { rejectUnauthorized: false });assert.deepEqual(getSslConfig(), { rejectUnauthorized: false });@biomejs/biome, @modelcontextprotocol/server, @types/node, @types/pg, esbuild, pg, postject, typescript
Gates applied: no_behavioural_pass.
ec971717547bfull audit observations/trust-audit/mcp-server/yawlabs__postgres-mcp.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-12 | ec971717547b | BLOCK | D | 69 | first audit |
Questions
What is the @yawlabs/postgres-mcp MCP server?
Read-only-by-default MCP server for PostgreSQL. Query, introspect schemas, explain plans, health checks.
What tools does @yawlabs/postgres-mcp expose?
23 in total: 19 read-only, 2 that write, and 2 that can delete or overwrite (pg_kill, pg_table_privileges). Every one is listed on this page with its risk.
Is @yawlabs/postgres-mcp safe to connect to an agent?
No — not without reading the findings first. The audit graded it D (69/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 2 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does @yawlabs/postgres-mcp need?
It reads GH_TOKEN, GITHUB_TOKEN and POSTGRES_SSL_REJECT_UNAUTHORIZED from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does @yawlabs/postgres-mcp run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as @yawlabs/postgres-mcp at 0.13.9.
How current is this page?
The grade is for one exact copy of the source (ec971717547b), read on 2026-10-12. The repository is watched and re-audited when it changes.