Skip to main content
Glama

Postgres Scout MCP

Scout your PostgreSQL databases with AI - A production-ready Model Context Protocol server with built-in safety features, monitoring, and data quality tools.

npm License

What You Get

You ask:

"How healthy is my production database? Any urgent issues?"

Postgres Scout returns:


Overall Health Score: 78/100

Component Breakdown

Component

Score

Status

Cache Performance

94/100

Healthy

Index Efficiency

82/100

Good

Table Bloat

61/100

Needs Attention

Connection Usage

75/100

Fair

Issues Found

  • HIGH — Table orders has 34% bloat (2.1 GB wasted). VACUUM FULL recommended.

  • MEDIUM — 3 unused indexes on sessions consuming 890 MB.

  • LOW — Cache hit ratio for analytics_events is 71% (target: >90%).

Recommendations

  • Run VACUUM FULL orders during maintenance window

  • Drop unused indexes: idx_sessions_legacy, idx_sessions_old_token, idx_sessions_temp

  • Consider adding analytics_events to shared_buffers or partitioning by date


That's getHealthScore — one of 38 tools covering exploration, diagnostics, optimization, monitoring, data quality, and safe writes.

Quick Start

Claude Code

claude mcp add postgres-scout -- npx -y postgres-scout-mcp postgresql://localhost:5432/mydb

Then ask: "Show me the largest tables and whether they have any bloat issues."

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "postgres-scout": {
      "command": "npx",
      "args": ["-y", "postgres-scout-mcp", "postgresql://localhost:5432/mydb"],
      "type": "stdio"
    }
  }
}

Add to your MCP settings:

{
  "postgres-scout": {
    "command": "npx",
    "args": ["-y", "postgres-scout-mcp", "postgresql://localhost:5432/mydb"]
  }
}

The server runs in read-only mode by default. For write operations, run a separate instance:

{
  "mcpServers": {
    "postgres-scout-readonly": {
      "command": "npx",
      "args": ["-y", "postgres-scout-mcp", "--read-only", "postgresql://localhost:5432/production"],
      "type": "stdio"
    },
    "postgres-scout-readwrite": {
      "command": "npx",
      "args": ["-y", "postgres-scout-mcp", "--read-write", "postgresql://localhost:5432/development"],
      "type": "stdio"
    }
  }
}
  • postgres-scout-readonly: Safe exploration, no risk of data modification

  • postgres-scout-readwrite: Write operations when explicitly needed

Tools

Explore — understand your database

  • listDatabases — databases the user has access to

  • getDatabaseStats — size, cache hit ratio, connection info

  • listSchemas — all schemas in the current database

  • listTables — tables with size and row statistics

  • describeTable — columns, constraints, indexes, and more

Query — run and analyze

  • executeQuery — run SELECT queries (or writes in read-write mode)

  • explainQuery — EXPLAIN plans for performance analysis

  • optimizeQuery — optimization recommendations for a specific query

Diagnose — find problems before they find you

  • getHealthScore — overall health score with component breakdown

  • detectAnomalies — anomalies in performance, connections, and data

  • analyzeTableBloat — bloat analysis for VACUUM planning

  • getSlowQueries — slow query analysis (requires pg_stat_statements)

  • suggestVacuum — VACUUM recommendations based on dead tuples and bloat

Optimize — make it faster

  • suggestIndexes — missing index recommendations from query patterns

  • suggestPartitioning — partitioning strategies for large tables

  • getIndexUsage — identify unused or underused indexes

Monitor — watch it live

  • getCurrentActivity — active queries and connections

  • analyzeLocks — lock contention and blocking queries

  • getLiveMetrics — real-time metrics over a time window

  • getHottestTables — tables with highest activity

  • getTableMetrics — comprehensive per-table I/O and scan stats

Data Quality — trust your data

  • findDuplicates — duplicate rows by column combination

  • findMissingValues — NULL analysis across columns

  • findOrphans — orphaned records with invalid foreign keys

  • checkConstraintViolations — test constraints before adding them

  • analyzeTypeConsistency — type inconsistencies in text columns

Relationships — follow the connections

  • exploreRelationships — multi-hop foreign key traversal

  • analyzeForeignKeys — foreign key health and performance

Time Series — temporal analysis

  • findRecent — rows within a time window

  • analyzeTimeSeries — window functions and anomaly detection

  • detectSeasonality — seasonal pattern detection

Export — get data out

  • exportTable — CSV, JSON, JSONL, or SQL

  • generateInsertStatements — INSERT statements for migration

Write (read-write only) — safe modifications

  • previewUpdate / previewDelete — see what would change before committing

  • safeUpdate — UPDATE with dry-run, row limits, empty WHERE protection

  • safeDelete — DELETE with dry-run, row limits, empty WHERE protection

  • safeInsert — INSERT with validation, batching, ON CONFLICT support

Security

  • Read-only by default — write operations must be explicitly enabled

  • All queries use parameterized values

  • SQL injection prevention with input validation and pattern detection

  • Identifier sanitization for table/column names

  • Rate limiting on all operations

  • Query timeouts to prevent long-running queries

  • Response size limits to prevent memory exhaustion

Examples

"What are the largest tables and do they have bloat?"

listTables({ schema: "public" })
analyzeTableBloat({ schema: "public", minSizeMb: 100 })

"Find duplicate emails in the users table."

findDuplicates({ table: "users", columns: ["email"] })

"Which queries are slowest and how can I speed them up?"

getSlowQueries({ minDurationMs: 100, limit: 10 })
suggestIndexes({ schema: "public" })

"Show me what's happening on the database right now."

getCurrentActivity()
getLiveMetrics({ metrics: ["queries", "connections", "cache"], duration: 30000, interval: 1000 })
getHottestTables({ limit: 5, orderBy: "seq_scan" })

"Find orphaned orders that reference deleted customers."

findOrphans({ table: "orders", foreignKey: "customer_id", referenceTable: "customers", referenceColumn: "id" })

Configuration

Variable

Default

Description

QUERY_TIMEOUT

30000

Query timeout in milliseconds

MAX_RESULT_ROWS

10000

Maximum rows returned per query

ENABLE_RATE_LIMIT

true

Enable rate limiting

RATE_LIMIT_MAX_REQUESTS

100

Requests per window

RATE_LIMIT_WINDOW_MS

60000

Rate limit window (ms)

PGMAXPOOLSIZE

10

Connection pool max size

PGMINPOOLSIZE

2

Connection pool min size

PGIDLETIMEOUT

10000

Idle connection timeout (ms)

ENABLE_LOGGING

false

Enable file logging

LOG_DIR

./logs

Log file directory

LOG_LEVEL

info

Log verbosity: debug, info, warn, error

CLI flags: --read-only (default), --read-write, --mode <mode>

Logging

File logging is disabled by default. Set ENABLE_LOGGING=true to enable. Two log files are created in LOG_DIR:

  • tool-usage.log — every tool call with timestamp, name, and arguments

  • error.log — errors with stack traces

Connection strings are automatically redacted in all output.

Development

git clone https://github.com/bluwork/postgres-scout-mcp.git
cd postgres-scout-mcp
pnpm install
pnpm build
pnpm test

License

Apache-2.0

A
license - permissive license
-
quality - not tested
D
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Issues opened vs closed

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bluwork/postgres-scout-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server