Atlas / MCP servers / yawlabs / @yawlabs/postgres-mcp

@yawlabs/postgres-mcpBLOCK

mcp/yawlabs/postgres-mcp

Read-only-by-default MCP server for PostgreSQL. Query, introspect schemas, explain plans, health checks.

Verdict
BLOCK
Grade
D
Trust score
69 /100
Exposed tools
23 19r · 2w · 2d
Transport
stdio
License
MIT
Stars
7
01

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 outputSchema and returns structuredContent alongside 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
Read from source at commit ec971717547bOBSERVED · 2026-10-12
02

Connect

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-code (npm)
claude mcp add postgres-mcp -- npx -y @yawlabs/[email protected]
03

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.

ToolRiskDescription
pg_advisorreadRolled-up DBA lint pass. One call returns four categories of findings:\n
pg_describe_tablereadDescribe a relation: kind (table / view / materialized_view / partitioned_table / foreign_table),
pg_explainreadGet the query plan for a SQL statement. By default, this uses plain EXPLAIN (no execution).
pg_healthreadQuick health snapshot: server version, database size, connection counts measured against
pg_index_advisorreadRecommend indexes for a workload, and prove each one pays for itself before recommending it.
pg_inspect_locksreadShow current lock contention: which sessions are blocked and who is blocking them.
pg_io_statsreadI/O observability: cumulative per-backend-type I/O from
pg_killdestructiveCancel a running query (SIGINT-equivalent) or terminate a backend connection (SIGTERM-
pg_list_extensionsreadList installed PostgreSQL extensions. Returns name, version, schema, and description.
pg_list_functionsreadList functions, procedures, and aggregates in a schema. Returns name, arguments, return type,
pg_list_rolesreadList database roles (users and groups) with their login/superuser/createdb/createrole
pg_list_schemasreadList non-system schemas in the database. Excludes
pg_list_tablesreadList tables (and optionally views) in a schema. Returns name, type (table/view/materialized
pg_list_viewsreadList views and materialized views in a schema with their SQL definitions. Use this over
pg_querywriteRun a SQL query against the configured PostgreSQL database. Postgres itself is the
pg_readonlywriteRun a SQL statement with no persistent data changes. Always executes inside a
pg_replication_statusreadReplication overview: configured replication slots, connected replicas (from
pg_search_columnsreadSearch for columns by name across all user schemas. Supports SQL LIKE patterns
pg_seq_scan_tablesreadTables with high sequential-scan counts relative to index scans - the first place to
pg_table_bloatreadEstimate table bloat (dead tuples + free space) for tables in a schema. Returns live
pg_table_privilegesdestructiveShow which roles have which privileges (SELECT, INSERT, UPDATE, DELETE, TRUNCATE,
pg_top_queriesreadTop N queries by total or mean execution time. Requires the
pg_unused_indexesreadIndexes that have never been scanned or have very low usage, largest first. Each unused
04

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.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (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)

HIGHFilesystem / path · fs.credential_store · CWE-22, CWE-59
scripts/update-manifests.mjs:220
const SSH = 'ssh -i ~/.ssh/gh_woods -o IdentitiesOnly=yes';
Why it matters. touches a credential store
HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
src/api.ts:294
if (raw === "0" || raw === "false") return { rejectUnauthorized: false };
Why it matters. certificate verification is disabled
Fix. leave verification on
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
CHANGELOG.md:186
`postgres://u:[email protected]:1/x` with `POSTGRES_AUDIT_LOG=stderr` (24 calls;
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
src/index.test.ts:1583
const SANDBOX_DSN = "postgres://u:hunter2@stub-host:6543/db";
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
pg_kill, pg_table_privileges
Why it matters. 2 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/index.test.ts:669
return new Function(`${pieces}\nreturn { pickNewest, floor: OAM_MIN };`)() as {
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/index.test.ts:818
return new Function(`${pieces}\nreturn runtimePlan;`)() as RuntimePlan;
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/index.test.ts:969
return new Function(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/index.test.ts:1908
const remedyFor = new Function(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/index.test.ts:1954
const { stripPermissionOptions, withoutPermissionOptions, permissionReachesChildren } = new Function(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/integration/launcher-sandbox.integration.test.ts:25
const LAUNCHER = fileURLToPath(new URL("../../bin/postgres-mcp.mjs", import.meta.url));
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/tools/admin.test.ts:317
const readme = readFileSync(new URL("../../README.md", import.meta.url), "utf8");
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/tools/admin.test.ts:501
const srcRoot = new URL("../../src/", import.meta.url);
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/tools/readme-gating.test.ts:36
const readme = readFileSync(new URL("../../README.md", import.meta.url), "utf8");
LOWNetwork egress · net.tls_off · CWE-200, CWE-319
src/api.test.ts:190
assert.deepEqual(getSslConfig(), { rejectUnauthorized: false });
Why it matters. certificate verification is disabled
Fix. leave verification on
LOWNetwork egress · net.tls_off · CWE-200, CWE-319
src/api.test.ts:195
assert.deepEqual(getSslConfig(), { rejectUnauthorized: false });
Why it matters. certificate verification is disabled
Fix. leave verification on
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@biomejs/biome, @modelcontextprotocol/server, @types/node, @types/pg, esbuild, pg, postject, typescript
Why it matters. 9 dependency range(s) float
Fix. pin exact versions or ship a lockfile

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha ec971717547bfull audit observations/trust-audit/mcp-server/yawlabs__postgres-mcp.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-12ec971717547bBLOCKD69first audit
06

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.

Advertisement