Skip to main content
Glama
pgtriage

pgtriage

Official
by pgtriage

pgtriage

CI PyPI Python License

MCP server for PostgreSQL performance auditing. Connect it to Claude Code (or any MCP client) and say "audit my database" to get actionable performance findings with exact fixes.

Not related to the pgAudit logging extension. pgtriage does performance triage, not compliance logging.

Why I built this

Built after diagnosing implicit type casts and missing indexes on multi-million-row tables in production fintech systems. The fixes were simple (one CREATE INDEX CONCURRENTLY statement each), but finding them required reading query plans most engineers never look at. pgtriage automates that diagnostic process and lets any AI client explain the results.

Related MCP server: postgres-mcp-server

How it works

Any MCP Client (Claude Code / Cursor / Windsurf / VS Code)
       |  MCP (stdio)
       v
pgtriage (data collection + pattern detection)
       |  psycopg3 (read-only)
       v
PostgreSQL database

pgtriage connects to your PostgreSQL database and exposes performance auditing tools via the Model Context Protocol. It collects metrics from PostgreSQL system views, runs deterministic pattern detection, and returns structured findings. The MCP client provides the AI layer, interpreting results and explaining fixes in plain English.

No API keys required. No AI costs. No vendor lock-in. The intelligence comes from your MCP client.

Example output

{
  "severity": "high",
  "category": "connection_pressure",
  "detail": "Connection utilization at 104% (104/100). Approaching max_connections limit.",
  "suggested_fix": "Consider using a connection pooler (PgBouncer) or increasing max_connections if RAM allows.",
  "evidence": {
    "total_connections": 104,
    "max_connections": 100,
    "utilization_pct": 104.0
  }
}
{
  "severity": "medium",
  "category": "duplicate_index",
  "table": "account",
  "detail": "Duplicate indexes on 'account': 'account_title_reverse_index' (16 kB) and 'account_group_reverse_index' (16 kB). Same column definition. One can be dropped.",
  "suggested_fix": "DROP INDEX CONCURRENTLY account_group_reverse_index;"
}

From a real audit: 118 tables scanned, 88 findings, prioritized by severity.

What it finds

  • Sequential scans on large tables with missing index suggestions

  • Type casts on indexed columns that suppress index usage, verified against PostgreSQL catalog metadata and the observed query plan

  • Dead tuple buildup and autovacuum health issues

  • Unused and duplicate indexes wasting disk and slowing writes

  • N+1 query patterns from pg_stat_statements analysis

  • Stale table statistics causing bad query plans

  • TOAST table bloat from large JSONB/TEXT columns

  • Configuration issues (shared_buffers, work_mem, autovacuum tuning)

  • Connection pressure approaching max_connections

  • Long-running queries holding locks

Quick start

Install

pip install pgtriage

Configure Claude Code

Add to your MCP settings (.claude/settings.json or project settings):

{
  "mcpServers": {
    "pgtriage": {
      "command": "python",
      "args": ["-m", "pgtriage"],
      "env": {
        "PGTRIAGE_CONNECTION_STRING": "postgres://user:pass@localhost:5432/dbname"
      }
    }
  }
}

Recommended: Use a dedicated read-only database role:

CREATE ROLE pgtriage_reader LOGIN PASSWORD 'secure_password';
GRANT pg_read_all_stats TO pgtriage_reader;
GRANT USAGE ON SCHEMA public TO pgtriage_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO pgtriage_reader;

Use

> audit my database

> check table health for the users table

> are there any unused indexes?

> review my PostgreSQL configuration

> find slow queries

> audit only the accounts schema

Tools

full_audit

Run a comprehensive performance audit covering table health, slow queries, index health, and configuration. Pass the optional schema_name argument to scope table, plan, and index findings to one user schema; omit it to audit every non-system schema. Configuration findings remain database-wide. Returns all findings sorted by severity.

check_table_health

Analyze dead tuples, autovacuum stats, sequential scan ratios, and TOAST bloat. Optionally filter to a specific user schema and/or table.

analyze_slow_queries

Pull the slowest queries from pg_stat_statements, inspect their execution plans, and detect patterns like indexed-column type casts, sequential scans, stale statistics, and N+1 queries. An optional schema_name filter uses verbose execution-plan metadata rather than parsing SQL text. Literal queries use bounded EXPLAIN ANALYZE; normalized queries containing placeholders use a non-executing generic plan.

check_index_health

Find unused indexes (zero scans), duplicate indexes (same column definition), and tables that likely need indexes based on scan patterns. Optionally scope the analysis to one user schema.

check_config

Review PostgreSQL settings (shared_buffers, work_mem, autovacuum_vacuum_scale_factor, random_page_cost, etc.) and flag suboptimal values. Checks connection utilization and long-running queries.

Agent runtime integration

pgtriage publishes MCP safety annotations for every tool. All tools are marked read-only and non-destructive; tools that can run bounded EXPLAIN ANALYZE are deliberately not marked idempotent. Agent runtimes must still allowlist, authorize, and validate every call because MCP annotations are descriptive hints, not permissions. See Agent Runtime Integration for the complete contract, schema-scoped audit behavior, and retry guidance.

Resources

Resource

Description

pgtriage://status

Connection status, PostgreSQL version, loaded extensions

pgtriage://tables

All tables with sizes and approximate row counts

Requirements

  • Python 3.11+

  • PostgreSQL 12+

  • pg_stat_statements extension (recommended for slow query analysis, not required for other tools)

  • Database user with read access to pg_stat_* views

Safety

pgtriage is designed for read-only production use and does not issue write SQL. Three independent layers protect database state:

  1. Session-level read-only: SET default_transaction_read_only = true on every connection. PostgreSQL rejects any write attempt at the server level.

  2. Query validation: EXPLAIN ANALYZE only runs on SELECT statements. INSERT, UPDATE, DELETE, DROP, SELECT INTO, SELECT FOR UPDATE, and stacked queries are all rejected before execution.

  3. Transaction rollback: Every EXPLAIN ANALYZE runs inside an explicit BEGIN/ROLLBACK block with a 10-second statement_timeout. Transactional database changes are rolled back and long-running queries are canceled. Rollback cannot undo external side effects triggered by database extensions or functions, so the dedicated read-only role and session-level read-only enforcement remain essential.

Additionally:

  • Connection strings are never exposed in tool outputs

  • Suggested fixes are advisory and are never executed by pgtriage; findings default to safe_to_apply: false

  • All database access is single-connection, no pooling

Development

git clone https://github.com/pgtriage/pgtriage.git
cd pgtriage
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest

License

MIT

Available Tools

5 tools
analyze_slow_queriesA

Find and analyze slow queries from pg_stat_statements. Runs EXPLAIN ANALYZE on top slow SELECT queries and detects performance patterns like sequential scans and missing indexes.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
min_callsNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full disclosure burden. It explicitly reveals that the tool runs EXPLAIN ANALYZE on top slow SELECT queries, which is an important behavioral trait with potential performance implications, and it describes the detection patterns. It stops short of noting any side effects or limitations, but the core behavior is clearly disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler. The first sentence states the purpose, and the second adds the method and detection details. Each clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the main functionality and output patterns, but it leaves parameter semantics unexplained and does not mention potential performance impact of running EXPLAIN ANALYZE. Without an output schema, this tool would benefit from a bit more context, yet the overall complexity is low, making this adequate with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides no descriptions and coverage is 0%, so the description must compensate. While 'limit' is somewhat intuitive from 'top slow SELECT queries', 'min_calls' is not explained, and no parameter details are provided. The description adds minimal value for understanding parameter meaning beyond the raw names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('Find and analyze') and a specific resource ('slow queries from pg_stat_statements'), and further details the method ('Runs EXPLAIN ANALYZE') and detection patterns. This distinguishes it from sibling tools like check_table_health and check_config.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool: analyzing slow queries and performance patterns. However, it does not explicitly state when not to use it or name alternatives, though the behavior described is distinct from the sibling health-check tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_configA

Review PostgreSQL configuration settings and flag suboptimal values for shared_buffers, work_mem, max_connections, and autovacuum parameters.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the responsibility for behavioral disclosure. Reviewing and flagging suboptimal values strongly implies a read-only, non-destructive analysis, but the description does not explicitly state whether it modifies anything, what permissions are needed, or what form the 'flags' take. This is adequate but lacks explicit safety confirmation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, focused sentence that immediately conveys the tool's purpose and scope. It is front-loaded with the action ('Review') and resource ('PostgreSQL configuration settings'), and every phrase adds value without unnecessary detail. No redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple, has no parameters, and no output schema, so the description covers the essential information about what it does and what it checks. It could benefit from a note about being read-only or returning a report, but the core purpose is sufficiently complete for an agent to select it appropriately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and the schema is trivially covered at 100%. There is nothing to explain beyond what the schema already indicates, so the baseline of 4 for zero-parameter tools is appropriate. The description adds context by listing the specific parameters checked (shared_buffers, work_mem, max_connections, autovacuum), which is useful.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reviews PostgreSQL configuration settings and flags suboptimal values for specific parameters. It uses a specific verb ('flag') and resource, and it is distinct from sibling tools focused on table health, slow queries, index health, and full audit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for checking PostgreSQL configuration, but it does not explicitly state when to use this tool versus alternatives like full_audit or check_table_health. There are no direct comparisons or exclusions, leaving usage somewhat inferred rather than explicitly guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_index_healthB

Find unused indexes, duplicate indexes, and missing index opportunities based on sequential scan patterns.

ParametersJSON Schema
NameRequiredDescriptionDefault
schema_nameNopublic

TDQS

B3.4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It reveals the detection method ('based on sequential scan patterns') but does not state whether the tool is read-only, whether it returns recommendations, or if any side effects or permissions are needed. The name implies a check, but that is not explicitly stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, direct sentence that states the primary function and adds a relevant methodological detail. It is front-loaded, contains no filler, and every part of the sentence contributes to understanding the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is relatively simple with one parameter, but the description omits what kind of output to expect (e.g., a list of recommendations, a health score, or a report). Since there is no output schema, the description should at least hint at the return value. It also does not mention prerequisites or permissions, leaving some gaps for an agent that needs to invoke it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has one parameter (schema_name) with 0% description coverage. The tool description does not explain this parameter or its purpose. While the name 'schema_name' is fairly self-explanatory, the description should compensate for the lack of schema-level detail, especially if the default value might not be obvious. It does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: finding unused, duplicate, and missing indexes. It uses a specific verb 'Find' and names the exact resource ('unused indexes, duplicate indexes, and missing index opportunities'). It also distinguishes this tool from siblings like check_table_health, which would target table-level issues, and analyze_slow_queries, which targets query-level performance.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for analyzing index health when sequential scan patterns are a concern, but it does not explicitly state when to use this tool versus alternatives or provide any exclusions. No sibling tools are mentioned, so the agent must infer the use case from the name and description alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_table_healthA

Check table health: dead tuples, bloat, vacuum stats, scan ratios. Optionally filter to a specific table by name.

ParametersJSON Schema
NameRequiredDescriptionDefault
table_nameNo

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full responsibility for behavioral disclosure. It lists the metrics checked but does not state whether the operation is read-only, whether it has performance implications, or how it handles invalid table names. This leaves significant transparency gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences: the first states the core purpose and metrics, the second adds the optional filter. Every word is informative and there is no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the minimal schema, no output schema, and no annotations, the description covers the tool's purpose and the main parameter adequately. However, it omits return value structure, permission requirements, and any operational cautions, leaving it incomplete for a tool with no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has one parameter (table_name) with no description, but the description explicitly explains that it is an optional filter. This compensates for the 0% schema description coverage, though it does not specify exact matching semantics or behavior when omitted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool checks table health, enumerating specific metrics (dead tuples, bloat, vacuum stats, scan ratios) and mentions an optional filter. This distinguishes it from sibling tools like check_index_health or check_config.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for assessing table health but does not explicitly state when to use it over alternatives, nor does it mention any exclusions or prerequisites. The optional filter suggests targeted use, but general guidance on when to choose this tool is absent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

full_auditB

Run a comprehensive performance audit: table health, slow queries, index health, and configuration review. Returns a unified report with all findings sorted by severity.

ParametersJSON Schema
NameRequiredDescriptionDefault
slow_query_limitNo

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of behavioral disclosure. It adds value by stating the tool returns a unified report sorted by severity, giving insight into output format. However, it does not mention whether the audit is read-only, any permission requirements, or potential performance impacts, leaving notable gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loading the purpose and then describing the output. Every word contributes, with no fluff or repetition. It efficiently conveys scope and result format.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool combines four audit areas and lacks an output schema, the description provides basic context but omits details about how the parameter affects the audit, any prerequisites, or expected behavior nuances. It is adequate for understanding the high-level purpose but not fully complete for a complex audit tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has one parameter, slow_query_limit, with 0% description coverage. The description does not mention this parameter at all, failing to explain how it influences the audit (e.g., number of slow queries included). The parameter name is somewhat self-explanatory, but the description should compensate for the low schema coverage and does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the tool runs a comprehensive performance audit covering table health, slow queries, index health, and configuration review, and returns a unified report sorted by severity. This clearly distinguishes it from the sibling tools that handle individual audit areas, as it combines all of them into one operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use for comprehensive audits but provides no explicit guidance on when to choose this tool over the individual sibling tools. It does not state exclusions or mention that individual checks can be run separately, so the agent is left without clear decision-making context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.2
    • First observedanalyze_slow_queries
    • First observedcheck_config
    • First observedcheck_index_health
    • First observedcheck_table_health
    • First observedfull_audit

TDQS

A4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct performance domain: table health, slow queries, index health, and configuration. The full_audit tool is clearly positioned as a comprehensive wrapper, not a duplicate, so there is no ambiguity.

Naming Consistency4/5

Most tools follow a verb_noun pattern (check_table_health, check_index_health, check_config, analyze_slow_queries), but 'full_audit' breaks the pattern by being a noun phrase instead of a verb-led name. This is a minor inconsistency in an otherwise predictable scheme.

Tool Count5/5

Five tools is well-scoped for a PostgreSQL performance triage server. Each tool covers a major diagnostic area, and the full_audit tool provides an integrated option without bloating the surface.

Completeness5/5

The toolset covers all key aspects of a performance triage workflow: table health, slow queries, index efficiency, and configuration review. The full_audit tool ties everything together, leaving no obvious operational gaps for the stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Read-only PostgreSQL analytics MCP server — query plans, slow queries, index usage, table bloat, vacuum status. No DDL/DML/writes. Curated by Archimedes Market with a verified Trust Report.
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Provides PostgreSQL database management and analysis via MCP, enabling schema exploration, query execution, performance monitoring, and database health checks.
    36
    22 npm
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Governed PostgreSQL DBA operations — slow-query, bloat, and blocking-lock RCA, index management, vacuum/analyze, and replication lag, with unbypassable audit logging (MCP + CLI), budget/runaway guards, dry-run, and undo/rollback.
    35
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides a read-only PostgreSQL MCP server with schema introspection. Enforces least-privilege database roles to prevent any writes, even from malicious SQL.
    MIT