io.github.YawLabs/postgres-mcp
NPM · @YAWLABS/POSTGRES-MCP · SCANNED AUG 6
PostgreSQL MCP server - query, schema introspection, explain, and health checks for AI assistants
Available components
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score →
Supply Chain Security100
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- No install/post-install scripts declared.Pass
- No production dependencies, so there is no dependency health to assess. View diagnostics → Pass
Provenance & Transparency19
- Repository check failed: no source repository is declared. See how to fix → View diagnostics → Fail
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 15 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability71
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 3398 tokens (~161/item across 21 items; 21 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management33
- Stability observed for 10 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.
npm · @yawlabs/postgres-mcp
claude mcp add yawlabs-postgres-mcp -- npx -y @yawlabs/postgres-mcp
codex mcp add yawlabs-postgres-mcp -- npx -y @yawlabs/postgres-mcp
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"yawlabs-postgres-mcp": {
"type": "local",
"command": [
"npx",
"-y",
"@yawlabs/postgres-mcp"
],
"enabled": true
}
}
} openclaw mcp add yawlabs-postgres-mcp --command npx --arg -y --arg @yawlabs/postgres-mcp
mcp_servers:
yawlabs-postgres-mcp:
command: "npx"
args: ["-y", "@yawlabs/postgres-mcp"] {
"mcpServers": {
"yawlabs-postgres-mcp": {
"command": "npx",
"args": [
"-y",
"@yawlabs/postgres-mcp"
]
}
}
} Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 5 Aug 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.
- 4 Aug 26 +4
- Stability: unverified → 0.27 ▲ functional
- 2 Aug 26 +15
- Malware scan: unverified → pass ▲ security
- 31 Jul 26 −7
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 30 Jul 26 −18
- Malware scan: pass → unverified ▼ security
- 27 Jul 26 +32
- Tool coverage: unverified → 100 ▲ functional
- First check of Schema quality: fail functional
- First check of Tool coverage: 100 functional
- First check of Schema quality: fail functional
- First check of Schema quality: excellent functional
- 26 Jul 26 41
First indexed and scored.
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 6 Aug 2026 · Analysed npm/@yawlabs/[email protected]
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | npm |
Dependencies 0 packages
| Packages resolved | 0 |
|---|---|
| Tree resolution | Complete |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.
pg_advisor ~267
Rolled-up DBA lint pass. One call returns three categories of findings: - sequence_exhaustion: SERIAL / BIGSERIAL / IDENTITY sequences whose `last_value` is above `seqExhaustionThreshold` of `max_value`. The classic incident class. - tables_without_primary_key: user tables (plain and partitioned) with no PK defined. Bloat candidates and a sign of design drift; some replication setups also need PKs. Foreign tables are excluded -- PostgreSQL forbids declaring PKs on foreign tables. - public_tables_without_rls: tables in `public` (or any schema in `rlsSchemas`) with row-level security disabled. Useful as a security baseline check. Use this as the 'what should I be looking at?' starting point, then drill into `pg_unused_indexes`, `pg_table_bloat`, `pg_seq_scan_tables` for the perf side.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | — | Max rows per category (default 50). |
| rlsSchemas | array | — | Schemas where RLS-missing should be flagged. Defaults to ['public']. |
| seqExhaustionThreshold | number | — | Minimum used-fraction (last_value / max_value) to flag a sequence (default 0.5 = 50%). |
No output schema declared.
No examples provided.
pg_describe_table ~162
Describe a relation: kind (table / view / materialized_view / partitioned_table / foreign_table), columns (name, type, nullable, default), primary key, foreign keys (outgoing), `referenced_by` (other tables whose FKs point at this one), `constraints` (CHECK / UNIQUE non-PK / EXCLUDE), indexes, and partition info (`partition_of` parent, `partitions` children). Works on views and materialized views too -- PK/FK/constraint/index lists will simply be empty for a plain view. Use `kind` to disambiguate before assuming you can write to the relation.
| Name | Type | Req | Description |
|---|---|---|---|
| schema | string | — | Schema name (defaults to 'public'). |
| table | string | yes | Table name. |
No output schema declared.
No examples provided.
pg_explain ~313
Get the query plan for a SQL statement. By default, this uses plain EXPLAIN (no execution). Set `analyze: true` to run the query with EXPLAIN ANALYZE - for non-SELECT statements, ALLOW_WRITES=1 is required (since ANALYZE actually executes the statement). Writes executed during EXPLAIN ANALYZE are always rolled back, so you can inspect a plan for an INSERT/UPDATE/DELETE without persisting the mutation. Format is `text` (default) or `json`. Pass the raw SQL (not an EXPLAIN-prefixed statement). Set `hypothetical_indexes` to a list of `{table, columns, using?}` to ask the planner 'what would the plan be if these indexes existed?' -- requires the HypoPG extension (`CREATE EXTENSION hypopg`). The hypothetical indexes are torn down at the end of the call, never touching real disk.
| Name | Type | Req | Description |
|---|---|---|---|
| analyze | boolean | — | Run EXPLAIN ANALYZE (actually executes the query). |
| format | string | — | Output format. |
| hypothetical_indexes | array | — | List of indexes the planner should pretend exist for this EXPLAIN. Requires the HypoPG extension. Indexes are session-scoped and reset at the end of the call. |
| params | array | — | Positional parameters referenced as $1, $2, ... in the SQL. |
| sql | string | yes | The SQL statement to explain. Do NOT prefix with EXPLAIN. |
No output schema declared.
No examples provided.
pg_health ~62
Quick health snapshot: server version, database size, connection count, active queries, and table count. Useful as a connection sanity check and to spot runaway queries.
| Name | Type | Req | Description |
|---|---|---|---|
| activeQueryLimit | integer | — | Max active queries to return (default 10, max 100). |
No output schema declared.
No examples provided.
pg_inspect_locks ~210
Show current lock contention: which sessions are blocked and who is blocking them. Returns blocked PID, blocking PID, lock types, relation being contested, and the queries involved. Use this first when a tool call hangs or the app feels stuck - it's the fastest way to identify a long-held transaction holding a lock. Row shape: one row per (blocked_pid, blocking_pid) pair. A session waiting on multiple blockers appears on multiple rows -- group/deduplicate by `blocked_pid` if you want a per-blocked-session count. Caveat on `relation`: for non-relation waits (transactionid/virtualxid, where the wait is on the blocker's xid rather than a table) `relation` is a best-effort hint -- an alphabetical guess among the blocker's held write-intent locks -- not authoritative. Use the blocked/blocking query text to disambiguate which table is actually contested.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | — | Max blocked/blocker pairs (default 50). |
No output schema declared.
No examples provided.
pg_kill ~226
Cancel a running query (SIGINT-equivalent) or terminate a backend connection (SIGTERM-equivalent) by PID. Find the PID via `pg_health` active_queries or `pg_inspect_locks`. Requires ALLOW_WRITES=1 since this changes database session state. The role in DATABASE_URL must have permission - cancelling another user's query needs the `pg_signal_backend` role or superuser. Note: `pg_signal_backend` does NOT cover superuser-owned backends - only a superuser can signal another superuser's session. Cancel is graceful; terminate is forceful. When `signaled=false`, the `note` field surfaces postgres's NOTICE explaining why (e.g. 'not a PostgreSQL backend process' for a non-pg PID, 'must be a member of...' for permission denial) so an agent can act on the specific cause rather than guess from a three-way list.
| Name | Type | Req | Description |
|---|---|---|---|
| mode | string | — | `cancel` aborts the current query; `terminate` closes the connection entirely. |
| pid | integer | yes | Backend PID to signal. |
No output schema declared.
No examples provided.
pg_list_extensions ~54
List installed PostgreSQL extensions. Returns name, version, schema, and description. Useful to check for pgvector, postgis, pg_stat_statements, uuid-ossp, etc. before writing queries that rely on them.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
pg_list_functions ~55
List functions, procedures, and aggregates in a schema. Returns name, arguments, return type, kind (function/procedure/aggregate/window), and implementation language.
| Name | Type | Req | Description |
|---|---|---|---|
| schema | string | — | Schema name (defaults to 'public'). |
No output schema declared.
No examples provided.
pg_list_roles ~88
List database roles (users and groups) with their login/superuser/createdb/createrole attributes and inherited role memberships. Use this to answer 'who has access to this database?' without needing to read `pg_authid` directly.
| Name | Type | Req | Description |
|---|---|---|---|
| includeSystem | boolean | — | If true, include built-in `pg_*` roles (pg_read_all_data, pg_monitor, etc.). |
No output schema declared.
No examples provided.
pg_list_schemas ~37
List non-system schemas in the database. Excludes `pg_catalog`, `information_schema`, and other `pg_*` internals.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
pg_list_tables ~153
List tables (and optionally views) in a schema. Returns name, type (table/view/materialized view/foreign), and estimated row count (from `reltuples`; null = no ANALYZE yet on PG 14+; 0 may mean empty or unanalyzed on PG <= 13). Paginate via `limit`/`offset` on very large schemas.
| Name | Type | Req | Description |
|---|---|---|---|
| includeViews | boolean | — | If true, include views and materialized views. |
| limit | integer | — | Max rows to return (default 500, max 10000). |
| offset | integer | — | Rows to skip for pagination (default 0). |
| schema | string | — | Schema name (defaults to 'public'). |
No output schema declared.
No examples provided.
pg_list_views ~79
List views and materialized views in a schema with their SQL definitions. Use this over `pg_list_tables` with `includeViews: true` when you want the view body, not just names.
| Name | Type | Req | Description |
|---|---|---|---|
| includeMaterialized | boolean | — | If true, include materialized views. |
| schema | string | — | Schema name (defaults to 'public'). |
No output schema declared.
No examples provided.
pg_query ~267
Run a SQL query against the configured PostgreSQL database. Postgres itself is the primary safety gate: the role in `DATABASE_URL` enforces what queries can succeed. The recommended posture is a least-privileged role (e.g. one granted `pg_read_all_data`), which makes writes server-rejected regardless of any env var. `ALLOW_WRITES=1` is a secondary belt-and-braces gate - it lifts the in-server `BEGIN READ ONLY` wrapper, but it cannot grant privileges the role lacks. Useful for managed databases where creating a second role is awkward. For read-only access where you want the guarantee in the tool name, prefer `pg_readonly`. Use `params` for parameterized queries to avoid SQL injection. Params can be strings, numbers, booleans, null, arrays (for postgres arrays / ANY), or objects (for json/jsonb columns). Dates and UUIDs can be passed as ISO strings. Large result sets are truncated to POSTGRES_MAX_ROWS (default 1000) with a `truncated: true` flag.
| Name | Type | Req | Description |
|---|---|---|---|
| params | array | — | Positional parameters referenced as $1, $2, ... in the SQL. |
| sql | string | yes | The SQL statement to execute. Hard cap of 1 MB. |
No output schema declared.
No examples provided.
pg_readonly ~200
Run a SQL statement guaranteed read-only. Always executes inside a `BEGIN READ ONLY` transaction regardless of `ALLOW_WRITES`, so postgres itself rejects any write attempt. Use this whenever the goal is to read - SELECT, EXPLAIN, SHOW, VALUES, WITH ... SELECT, etc. Hosts that gate tools individually (Claude Code permissions, mcp.hosting) can safely auto-allow this one. Use `params` for parameterized queries to avoid SQL injection. Params can be strings, numbers, booleans, null, arrays (for postgres arrays / ANY), or objects (for json/jsonb columns). Large result sets are truncated to POSTGRES_MAX_ROWS (default 1000) with a `truncated: true` flag.
| Name | Type | Req | Description |
|---|---|---|---|
| params | array | — | Positional parameters referenced as $1, $2, ... in the SQL. |
| sql | string | yes | The SQL statement to execute. Hard cap of 1 MB. |
No output schema declared.
No examples provided.
pg_replication_status ~70
Replication overview: configured replication slots, connected replicas (from `pg_stat_replication`), and current WAL position. Use on primary to spot lagging or disconnected replicas, on replicas to see upstream status. Returns empty arrays on a standalone (non-replicated) database rather than erroring.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
pg_search_columns ~121
Search for columns by name across all user schemas. Supports SQL LIKE patterns (`%` matches any substring, `_` matches one character). Case-insensitive. Use this instead of iterating `pg_describe_table` when the user asks 'which tables have X'.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | — | Max rows to return (default 100). |
| pattern | string | yes | LIKE pattern. Use '%' for wildcard: 'user_id', '%email%', 'created_%'. |
| schema | string | — | Limit to this schema. If omitted, searches all user schemas. |
No output schema declared.
No examples provided.
pg_seq_scan_tables ~146
Tables with high sequential-scan counts relative to index scans - the first place to look for missing-index candidates. Returns seq_scans, idx_scans, live tuples, and the ratio. A high ratio on a large table usually means a query is reading the whole table where an index would suffice. Pair with `pg_top_queries` to find which query is doing it.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | — | Max rows to return (default 20). |
| minSize | integer | — | Minimum live tuple count to include (default 1000, filters out tiny/empty tables). |
| schema | string | — | Limit to one schema. If omitted, all user schemas are included. |
No output schema declared.
No examples provided.
pg_table_bloat ~362
Estimate table bloat (dead tuples + free space) for tables in a schema. Returns live tuples, dead tuples, dead-tuple ratio, last_vacuum / last_autovacuum timestamps, and total relation size. A high dead_ratio with a stale last_autovacuum is a sign a table needs VACUUM. Three methods are available via the `method` parameter: - `estimate` (default): reads pg_stat_user_tables -- fast, no extensions, ANALYZE-driven approximations. Use this first. - `approx`: uses pgstattuple_approx() -- fast sampling pass, more accurate than estimates, requires the pgstattuple extension. - `exact`: uses pgstattuple() -- full table scan, exact counts, slow on large tables, requires the pgstattuple extension. Always pass `schema` with method='exact' -- scanning all user tables in one statement will hit statement_timeout on non-trivial databases. Install pgstattuple with `CREATE EXTENSION pgstattuple` (requires superuser).
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | — | Max rows to return (default 50). |
| method | string | — | Bloat measurement method. 'estimate' (default) uses pg_stat_user_tables (fast, no extensions). 'approx' uses pgstattuple_approx() (fast sampling, more accurate). 'exact' uses pgstattuple() (full scan… |
| minDeadRatio | number | — | Minimum dead-tuple fraction to include - dead / (live + dead). Default 0.1 = 10%. |
| schema | string | — | Limit to one schema. If omitted, all user schemas are included. |
No output schema declared.
No examples provided.
pg_table_privileges ~185
Show which roles have which privileges (SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER) on a table or on every table in a schema. If `table` is omitted, the result spans every table in `schema`, ordered by table then grantee. Use this to answer 'who can write to this table?' or to audit schema-wide access before a migration. Visibility caveat: backed by `information_schema.table_privileges`, which postgres filters by what the calling role can see. A least-privileged role may not see grants involving unrelated third-party roles. For a complete picture, run as a superuser or a member of `pg_read_all_data`.
| Name | Type | Req | Description |
|---|---|---|---|
| schema | string | — | Schema name (defaults to 'public'). |
| table | string | — | Table name. Omit to list privileges for all tables in the schema. |
No output schema declared.
No examples provided.
pg_top_queries ~204
Top N queries by total or mean execution time. Requires the `pg_stat_statements` extension to be installed and enabled (most managed Postgres providers have it on by default). Returns normalized query text (constants replaced with `?`), call count, total/mean/min/max time in ms, rows returned, and cache hit ratio. Use this to find slow queries worth optimizing. On pg_stat_statements >= 1.10 (Postgres 15+), also returns `io_read_time_ms` and `io_write_time_ms` to separate IO-bound from CPU-bound queries (null when track_io_timing = off or the query did no measurable IO -- enable track_io_timing in postgresql.conf to get non-null values).
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | — | Number of rows to return (default 20). |
| orderBy | string | — | Ranking: total_time (cumulative impact), mean_time (worst per-call), or calls (hottest). |
No output schema declared.
No examples provided.
pg_unused_indexes ~137
Indexes that have never been scanned or have very low usage. Each unused index costs write amplification (every INSERT/UPDATE maintains it) and disk space. Excludes primary keys and unique constraints (which are load-bearing even with zero scans). Use this before adding new indexes - sometimes the fix is to drop a dead one.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | — | Max rows to return (default 50). |
| maxScans | integer | — | Include indexes with scan count <= this (default 10). Use 0 for 'never scanned'. |
| schema | string | — | Limit to one schema. If omitted, all user schemas are included. |
No output schema declared.
No examples provided.