Skip to main content
Glama
mahin1995

postgres-mcp-readonly

by mahin1995

PostgreSQL MCP Server

A secure, read-only PostgreSQL Model Context Protocol (MCP) server that provides safe database introspection and querying capabilities. Built with TypeScript for enhanced type safety and reliability.

Overview

This MCP server enables AI assistants and other MCP clients to safely interact with PostgreSQL databases through a read-only interface. It provides schema inspection, parameterized queries, table previews, change tracking, and row counting while preventing any data modifications.

Related MCP server: mcp-postgres

Quick Start

Get started in seconds with npx (no installation required):

# Set your database connection
export DATABASE_URL="postgres://user:password@localhost:5432/dbname"

# Run the server
npx -y postgres-mcp-readonly

For Claude Desktop, add this to your claude_desktop_config.json:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "postgres-mcp-readonly"],
      "env": {
        "DATABASE_URL": "postgres://user:pass@localhost:5432/mydb"
      }
    }
  }
}

Restart Claude Desktop, and you'll have database access in your conversations! 🎉

Features

🔒 Security First

  • Read-only enforcement - Blocks all write operations (INSERT, UPDATE, DELETE, etc.)

  • SQL injection protection - Validates identifiers and sanitizes queries

  • Automatic LIMIT enforcement - Prevents unbounded result sets

  • Agent-friendly SQL handling - Accepts single or batched read-only SELECT queries while still blocking writes

  • Non-executing validation - Validates SELECT/INSERT/UPDATE/DELETE statement shape with EXPLAIN

  • Catalog inspection - Exposes table info, indexes, constraints, relationships, and sample values

  • Query timeouts - Prevents long-running queries from blocking resources

  • Error sanitization - Prevents leakage of sensitive connection details

  • Transaction isolation - All queries run in READ ONLY transactions

🛠️ Tools Provided

  1. db.databases - List configured database aliases

  2. db.schema - Inspect database structure

  3. db.query - Execute single or batched SELECT queries

  4. db.validate_insert - Non-executing INSERT statement validation

  5. db.validate_sql - Non-executing SELECT/INSERT/UPDATE/DELETE validation

  6. db.explain - Explain SELECT plans without executing queries

  7. db.table_info - Inspect one table in detail

  8. db.indexes - List indexes

  9. db.constraints - List table constraints

  10. db.relationships - List foreign-key relationships

  11. db.sample_values - Fetch safe distinct sample values

  12. db.preview - Quick table preview

  13. db.watch - Poll for incremental changes

  14. db.count - Get exact row counts

📊 Resources

  • schema-summary (pg://schema/summary) - Table list with approximate row counts

  • schema-full (pg://schema/full) - Complete schema with columns, keys, and relationships

Installation & Usage

Prerequisites

  • Node.js 18+

  • PostgreSQL database (accessible via network)

No installation required! Use directly with npx:

# Run with environment variables
export DATABASE_URL="postgres://user:pass@localhost:5432/mydb"
npx -y postgres-mcp-readonly

For Windows PowerShell:

$env:DATABASE_URL="postgres://user:pass@localhost:5432/mydb"
npx -y postgres-mcp-readonly

With Claude Desktop - Add to claude_desktop_config.json:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "postgres-mcp-readonly"],
      "env": {
        "DATABASE_URL": "postgres://user:pass@localhost:5432/mydb",
        "STATEMENT_TIMEOUT_MS": "5000",
        "MAX_ROWS": "500"
      }
    }
  }
}

With MCP Inspector:

npx @modelcontextprotocol/inspector npx -y postgres-mcp-readonly

Option 2: Global Installation

Install once, use everywhere:

npm install -g postgres-mcp-readonly

Then run:

export DATABASE_URL="postgres://user:pass@localhost:5432/mydb"
postgres-mcp-readonly

With Claude Desktop:

{
  "mcpServers": {
    "postgres": {
      "command": "postgres-mcp-readonly",
      "env": {
        "DATABASE_URL": "postgres://user:pass@localhost:5432/mydb"
      }
    }
  }
}

Option 3: Local Development

For contributing or customizing:

  1. Clone the repository

    git clone https://github.com/mahin1995/postgres-mcp-readonly.git
    cd postgres-mcp-readonly
  2. Install dependencies

    npm install
  3. Build the TypeScript code

    npm run build
  4. Configure environment variables

    Create a .env file:

    DATABASE_URL=postgres://username:password@localhost:5432/database_name
    STATEMENT_TIMEOUT_MS=5000
    MAX_ROWS=500
  5. Test the connection

    npm start

With Claude Desktop (local development):

{
  "mcpServers": {
    "postgres": {
      "command": "node",
      "args": ["/absolute/path/to/postgres-mcp-readonly/dist/server.js"],
      "env": {
        "DATABASE_URL": "postgres://user:pass@localhost:5432/mydb"
      }
    }
  }
}

Configuration

Environment Variables

Variable

Required

Default

Description

DATABASE_URL

Conditional

-

Single PostgreSQL connection string (backward compatible)

DATABASE_URLS

Conditional

-

Multiple PostgreSQL URLs as alias=url pairs or JSON

DEFAULT_DATABASE

default

Default alias used when tool input omits database

STATEMENT_TIMEOUT_MS

5000

Query timeout in milliseconds

MAX_ROWS

500

Default maximum rows returned

MAX_STATEMENTS

10

Maximum semicolon-separated statements per multi-statement tool call

AUDIT_LOG

false

Set to true to write JSON audit events to stderr

At least one of DATABASE_URL or DATABASE_URLS must be configured.

Multi-Database Support

This package now supports multiple database connections without breaking existing single-database usage.

  • Existing setup continues to work with only DATABASE_URL.

  • To use multiple databases, set DATABASE_URLS as comma-separated alias=url pairs.

  • JSON is still supported for backward compatibility.

  • Each DB tool accepts an optional database alias. If omitted, DEFAULT_DATABASE is used.

Example environment:

DATABASE_URLS=default=postgres://user:pass@localhost:5432/app,analytics=postgres://user:pass@localhost:5432/analytics
DEFAULT_DATABASE=default

JSON format also works if your environment supports it:

DATABASE_URLS={"default":"postgres://user:pass@localhost:5432/app","analytics":"postgres://user:pass@localhost:5432/analytics"}
DEFAULT_DATABASE=default

List configured aliases:

// db.databases
{}

Use a specific alias in any DB tool:

{
  "database": "analytics",
  "sql": "SELECT * FROM events ORDER BY created_at DESC LIMIT 20"
}

Connection String Format

postgres://username:password@host:5432/database_name
postgresql://username:password@host:5432/database_name

Tools Documentation

All DB tools support an optional database parameter to select a configured alias.

0. db.databases

List configured database aliases and current default alias.

Parameters:

  • None

Response:

{
  "defaultDatabase": "default",
  "databases": ["analytics", "default"]
}

1. db.schema

Inspect database schema information.

Parameters:

  • mode (optional): "summary" or "full" (default: "summary")

  • filter (optional): Filter tables by name or schema (case-insensitive)

  • database (optional): Database alias from DATABASE_URLS (or default)

Examples:

// Get table list with row counts
{
  "mode": "summary"
}

// Get full schema with columns and keys
{
  "mode": "full"
}

// Filter specific tables
{
  "mode": "full",
  "filter": "users"
}

Response (summary):

{
  "mode": "summary",
  "tables": [
    {
      "schema": "public",
      "table": "users",
      "approxRows": 1250
    }
  ]
}

Response (full):

{
  "mode": "full",
  "schemas": {
    "public": {
      "users": {
        "columns": [
          {
            "name": "id",
            "dataType": "integer",
            "udtName": "int4",
            "nullable": false,
            "default": "nextval('users_id_seq'::regclass)",
            "position": 1
          }
        ],
        "primaryKey": ["id"],
        "foreignKeys": []
      }
    }
  }
}

2. db.query

Execute one or more read-only SELECT queries. Single-statement calls keep the original response shape; multi-statement calls return one result object per statement.

Parameters:

  • sql (required): One SELECT query or multiple semicolon-separated SELECT queries

  • params (optional): Array of parameter values for $1, $2, etc.

  • maxRows (optional): Maximum rows to return (1-5000, default: 500)

  • database (optional): Database alias from DATABASE_URLS (or default)

Examples:

// Simple query
{
  "sql": "SELECT * FROM users WHERE active = true"
}

// Parameterized query
{
  "sql": "SELECT id, name, email FROM users WHERE country = $1 AND age > $2",
  "params": ["USA", 25],
  "maxRows": 100
}

// Query with existing LIMIT (will be honored if <= maxRows)
{
  "sql": "SELECT * FROM orders ORDER BY created_at DESC LIMIT 10"
}

// Multiple non-parameterized SELECT queries in one call
{
  "sql": "SELECT COUNT(*) AS users_count FROM users; SELECT COUNT(*) AS orders_count FROM orders;"
}

Response (single statement):

{
  "rowCount": 10,
  "fields": ["id", "name", "email"],
  "rows": [{ "id": 1, "name": "John Doe", "email": "john@example.com" }]
}

Response (multiple statements):

{
  "statementCount": 2,
  "results": [
    {
      "statement": 1,
      "rowCount": 1,
      "fields": ["users_count"],
      "rows": [{ "users_count": "1250" }]
    },
    {
      "statement": 2,
      "rowCount": 1,
      "fields": ["orders_count"],
      "rows": [{ "orders_count": "8421" }]
    }
  ]
}

Security Notes:

  • Only SELECT and WITH (CTE) queries allowed

  • Multi-statement calls are allowed only when every statement is read-only

  • Parameterized queries must be single-statement

  • Automatic LIMIT enforcement applies to every statement if not specified

  • Query timeout: 5 seconds (default)

3. db.validate_insert

Validate INSERT SQL without performing the INSERT. This tool uses EXPLAIN (FORMAT JSON) without ANALYZE, so PostgreSQL parses and plans the INSERT but does not insert rows.

Parameters:

  • sql (required): One INSERT statement or multiple semicolon-separated INSERT statements

  • params (optional): Array of parameter values for $1, $2, etc.

  • database (optional): Database alias from DATABASE_URLS (or default)

Examples:

// Validate a single INSERT
{
  "sql": "INSERT INTO users (name, email) VALUES ($1, $2)",
  "params": ["Alice", "alice@example.com"]
}

// Validate multiple non-parameterized INSERT statements
{
  "sql": "INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'); INSERT INTO audit_logs (action) VALUES ('test');"
}

Response:

{
  "valid": true,
  "executed": false,
  "validatedBy": "EXPLAIN (FORMAT JSON)",
  "statementCount": 1,
  "results": [
    {
      "statement": 1,
      "valid": true,
      "sql": "INSERT INTO users (name, email) VALUES ($1, $2)",
      "planNode": "ModifyTable"
    }
  ]
}

Validation Notes:

  • This checks syntax, table names, column names, type compatibility, and permissions needed to plan the INSERT

  • This does not perform any INSERT operation and does not persist rows

  • This cannot detect runtime-only errors such as unique conflicts, foreign-key violations, trigger errors, not-null/check failures that depend on runtime values, or defaults that fail during execution

  • Parameterized validation must be single-statement

  • The tool only accepts statements starting with INSERT

4. db.validate_sql

Validate SQL statement shape without executing it. This uses EXPLAIN (FORMAT JSON) without ANALYZE.

Parameters:

  • mode (required): "select", "insert", "update", or "delete"

  • sql (required): SQL statement matching the selected mode

  • params (optional): Array of parameter values for $1, $2, etc.

  • database (optional): Database alias from DATABASE_URLS (or default)

Example:

{
  "mode": "update",
  "sql": "UPDATE users SET last_seen_at = now() WHERE id = $1",
  "params": [123]
}

5. db.explain

Return PostgreSQL query plans for SELECT/WITH statements without executing them.

Parameters:

  • sql (required): One SELECT/WITH statement or multiple semicolon-separated SELECT/WITH statements

  • params (optional): Array of parameter values for $1, $2, etc.

  • database (optional): Database alias from DATABASE_URLS (or default)

Example:

{
  "sql": "SELECT * FROM orders WHERE user_id = $1 ORDER BY created_at DESC LIMIT 20",
  "params": [123]
}

6. db.table_info

Inspect one table's columns, indexes, constraints, foreign-key relationships, and triggers.

Parameters:

  • table (required): Table name (use schema.table or just table)

  • database (optional): Database alias from DATABASE_URLS (or default)

7. db.indexes

List indexes for all user tables or a single table.

Parameters:

  • table (optional): Table name (use schema.table or just table)

  • database (optional): Database alias from DATABASE_URLS (or default)

8. db.constraints

List primary-key, foreign-key, unique, check, and exclusion constraints.

Parameters:

  • table (optional): Table name (use schema.table or just table)

  • database (optional): Database alias from DATABASE_URLS (or default)

9. db.relationships

List foreign-key relationships for all user tables or a single table.

Parameters:

  • table (optional): Table name (use schema.table or just table)

  • database (optional): Database alias from DATABASE_URLS (or default)

10. db.sample_values

Return small distinct non-null sample values for selected columns.

Parameters:

  • table (required): Table name (use schema.table or just table)

  • columns (required): Array of 1-20 column names

  • limit (optional): Number of values per column (1-100, default: 10)

  • database (optional): Database alias from DATABASE_URLS (or default)

11. db.preview

Quick preview of table rows.

Parameters:

  • table (required): Table name (use schema.table or just table)

  • limit (optional): Number of rows (1-500, default: 50)

  • database (optional): Database alias from DATABASE_URLS (or default)

Examples:

// Preview public.users table
{
  "table": "users",
  "limit": 20
}

// Preview from specific schema
{
  "table": "analytics.events"
}

Response:

{
  "table": "public.users",
  "rowCount": 20,
  "rows": [{ "id": 1, "name": "Alice", "created_at": "2024-01-15T10:30:00Z" }]
}

12. db.watch

Poll for incremental changes using cursor-based pagination.

Parameters:

  • table (required): Table name

  • cursorColumn (optional): Column to track (default: "updated_at")

  • lastCursor (optional): Last cursor value from previous call

  • batchSize (optional): Rows per batch (1-1000, default: 200)

  • database (optional): Database alias from DATABASE_URLS (or default)

Examples:

// Initial fetch (gets oldest records first)
{
  "table": "orders",
  "cursorColumn": "created_at"
}

// Subsequent fetch (pass lastCursor from previous response)
{
  "table": "orders",
  "cursorColumn": "created_at",
  "lastCursor": "2024-01-15T14:23:45.123Z",
  "batchSize": 100
}

// Track by numeric ID
{
  "table": "logs",
  "cursorColumn": "id",
  "lastCursor": 5042
}

Response:

{
  "table": "public.orders",
  "cursorColumn": "created_at",
  "cursorType": "timestamp with time zone",
  "lastCursor": "2024-01-15T15:30:00Z",
  "rows": [...]
}

Use Case:

  • Real-time monitoring

  • ETL/sync processes

  • Audit log tracking

  • Event streaming

13. db.count

Get exact row count for a table.

Parameters:

  • table (required): Table name (use schema.table or just table)

  • database (optional): Database alias from DATABASE_URLS (or default)

Examples:

// Count rows in public.users
{
  "table": "users"
}

// Count in specific schema
{
  "table": "analytics.pageviews"
}

Response:

{
  "table": "public.users",
  "count": 15247
}

Usage Examples

Quick Start with npx

# Set your database URL
export DATABASE_URL="postgres://user:pass@localhost:5432/mydb"

# Run the server
npx -y postgres-mcp-readonly

The server will start and wait for MCP protocol messages. Press Ctrl+C to stop.

Testing with MCP Inspector

The MCP Inspector provides a web UI to test your server:

# Set environment first
export DATABASE_URL="postgres://user:pass@localhost:5432/mydb"

# Launch inspector with your server
npx @modelcontextprotocol/inspector npx -y postgres-mcp-readonly

This opens a browser where you can:

  • View all available tools

  • Call tools with parameters

  • See responses in real-time

With Claude Desktop

Claude Desktop is the primary way to use MCP servers with AI assistants.

Using npx (recommended):

Edit claude_desktop_config.json:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "postgres-mcp-readonly"],
      "env": {
        "DATABASE_URL": "postgres://user:pass@localhost:5432/mydb",
        "STATEMENT_TIMEOUT_MS": "5000",
        "MAX_ROWS": "500"
      }
    }
  }
}

Using global install:

{
  "mcpServers": {
    "postgres": {
      "command": "postgres-mcp-readonly",
      "env": {
        "DATABASE_URL": "postgres://user:pass@localhost:5432/mydb"
      }
    }
  }
}

Example Conversation Flow

User: "Show me the database schema"

AI uses: db.schema with mode: "summary"


User: "How many users do we have?"

AI uses: db.count with table: "users"


User: "Show me the 10 most recent orders"

AI uses: db.query with SQL:

SELECT * FROM orders ORDER BY created_at DESC LIMIT 10

User: "Watch for new signups"

AI uses: db.watch with table: "users", cursorColumn: "created_at"

Security Features

Query Validation

The server performs multiple security checks:

  1. Keyword Blocklist for db.query - Prevents write and unsafe commands in read-query execution: INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, GRANT, REVOKE, VACUUM, ANALYZE, REINDEX, COPY, CALL, DO, EXECUTE

  2. Comment Stripping - Removes SQL comments to prevent obfuscation

  3. Read-only Statements - Single or multi-statement query requests are allowed when every statement is SELECT/WITH only

  4. Non-executing INSERT Validation - db.validate_insert uses EXPLAIN without ANALYZE to validate INSERT shape without performing insert operations

  5. SELECT-only for Queries - db.query statements must start with SELECT or WITH

  6. Identifier Validation - Table/column names must match [a-zA-Z_][a-zA-Z0-9_]*

  7. Statement Limits - Multi-statement tools are capped by MAX_STATEMENTS

  8. Parameterization - Supports bind parameters ($1, $2, etc.) to prevent injection

Error Sanitization

Database errors are sanitized to prevent leaking:

  • Connection strings and passwords

  • Server hostnames

  • File system paths

  • Overly verbose stack traces

Connection Safety

  • Connection pooling with max 10 connections

  • Statement timeout (5s default) prevents runaway queries

  • Lock timeout (1s) prevents deadlock situations

  • Idle transaction timeout (5s) frees stuck connections

  • Graceful shutdown on SIGINT/SIGTERM

Best Practices

For AI Assistants

  1. Always check schema first - Use db.schema before querying unknown tables

  2. Use parameterization - Never concatenate user input into SQL strings

  3. Start with small limits - Use low maxRows for exploratory queries

  4. Use db.count for totals - Don't SELECT COUNT(*) manually

  5. Handle errors gracefully - Sanitized errors are safe to show users

For Database Admins

  1. Use read-only database user - Grant only SELECT permissions

  2. Monitor connection usage - Set appropriate pool size

  3. Adjust timeouts - Based on your query complexity

  4. Enable query logging - In PostgreSQL for audit trail

  5. Use SSL connections - Add ?sslmode=require to DATABASE_URL

Performance Tips

  1. Ensure indexed columns - Especially for db.watch cursor columns

  2. Use filters in db.schema - Don't fetch full schema repeatedly

  3. Keep maxRows reasonable - Large result sets slow serialization

  4. Add indexes on sort columns - For ORDER BY performance

Troubleshooting

Connection Issues

Problem: Missing DATABASE_URL error

Solution: Create .env file with valid connection string


Problem: ECONNREFUSED or connection timeout

Solution:

  • Verify PostgreSQL is running

  • Check host/port in DATABASE_URL

  • Ensure firewall allows connections

  • Test with psql command line first


Problem: password authentication failed

Solution: Verify username/password in DATABASE_URL

Query Errors

Problem: Blocked keyword detected: insert

Solution: This is intentional - only SELECT queries are allowed


Problem: Only SELECT queries are allowed

Solution: Ensure query starts with SELECT or WITH, not EXPLAIN, SHOW, etc.


Problem: statement timeout

Solution:

  • Increase STATEMENT_TIMEOUT_MS

  • Optimize query with indexes

  • Reduce dataset with WHERE clause

Schema Issues

Problem: relation "table_name" does not exist

Solution:

  • Check table name spelling

  • Use schema.table if not in public schema

  • Run db.schema to see available tables

Development

This section is for contributors working on the package itself.

Setting Up Development Environment

# Clone the repository
git clone https://github.com/mahin1995/postgres-mcp-readonly.git
cd postgres-mcp-readonly

# Install dependencies
npm install

# Set up environment
cp .env.example .env
# Edit .env with your database credentials

Running Locally

# Build TypeScript
npm run build

# Run the server
npm start

# Or use dev mode (builds and runs)
npm run dev

# Watch mode (auto-rebuild on changes)
npm run build:watch

Testing

Quick Connection Test:

node test-client.js

This runs a basic test to verify:

  • Server starts successfully

  • MCP protocol communication works

  • All tools are registered

Interactive Testing with MCP Inspector:

npm run build
npx @modelcontextprotocol/inspector node dist/server.js

Publishing

# Build first
npm run build

# Publish to npm (requires authentication)
npm publish --otp=YOUR_2FA_CODE

License

MIT

Contributing

Contributions welcome! Please ensure:

  • Security best practices maintained

  • All tools remain read-only

  • Tests pass (if added)

  • Documentation updated

Support

For issues or questions:

  1. Check this README first

  2. Review PostgreSQL connection docs

  3. Test with psql to isolate database issues

  4. Open an issue with sanitized error messages


Remember: This server is read-only by design. For database modifications, use traditional database tools or separate admin interfaces.

Available Tools

14 tools
db.constraintsA

List constraints for all user tables or one table, including primary keys, foreign keys, unique constraints, and checks.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableNo
databaseNo

TDQS

A3.6/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It discloses the read-only nature implicitly by 'List' and explains the optional table scoping, but it does not mention output format, error handling, permissions, or behavior when the table does not exist. Adequate but lacks depth.

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 concise sentence that front-loads the action ('List constraints'), specifies the target resource, and enumerates the included constraint types. Every phrase adds value with no redundancy or filler.

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?

For a simple list operation with only two optional parameters and no output schema, the description covers the core functionality. However, it omits explanation of the 'database' parameter, the meaning of 'user tables' (as opposed to system tables), and any return structure. This leaves some gaps for an agent to resolve.

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?

Schema description coverage is 0%, so the description must compensate for parameter semantics. It indirectly references the 'table' parameter ('one table'), but the 'database' parameter is not explained at all. There is no mention of parameter optionality, allowed values, or defaults, leaving significant ambiguity.

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 uses a specific verb ('List') and clearly identifies the resource (constraints for user tables). It further specifies the scope ('all user tables or one table') and enumerates the constraint types (primary keys, foreign keys, unique constraints, checks), distinguishing it from sibling tools like db.indexes and db.relationships.

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 retrieving constraints, with an optional 'table' parameter to target a single table. However, it provides no explicit guidance on when to use this tool versus alternatives, and no exclusion criteria or prerequisites are mentioned. The context is clear but not fully specified.

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

db.countA

Get exact row count for a table. Use table or schema.table name.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableYes
databaseNo

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations, the description must carry the behavioral burden. It notes 'exact' row count, implying precision, but does not disclose return format, performance implications, or side effects. For a simple read-only operation, this is minimal but lacks richer behavioral context.

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, front-loaded sentence: 'Get exact row count for a table. Use table or schema.table name.' No wasted words; every clause contributes either purpose or parameter 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?

For a simple count tool, the description omits the return type (e.g., integer), the semantics of the `database` parameter, and any usage guidance relative to sibling tools. Given no annotations and no output schema, the description leaves notable gaps in the full context an agent might need.

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

Parameters3/5

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

Schema description coverage is 0%, so the description must compensate. It clarifies that `table` accepts either a table name or schema.table format, which adds value. However, the optional `database` parameter is not mentioned, leaving its meaning ambiguous. Thus, partial compensation only.

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 'Get exact row count for a table' clearly states the action (get), the resource (row count for a table), and the specificity ('exact' distinguishes from estimates). It differentiates from siblings like db.preview or db.sample_values by focusing specifically on count.

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 provides no explicit when-to-use or alternative comparisons. It only gives parameter format guidance ('Use table or schema.table name'), which is not usage context. The absence of exclusions or alternative references leaves the agent to infer when this tool is appropriate.

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

db.databasesA

List configured database aliases and the currently selected default alias.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.1/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden. It transparently indicates a read-only listing operation ('List') and mentions the default alias, but it does not disclose potential details like whether the output includes connection strings, sorting order, or how the default is highlighted. For a simple listing tool, this is adequate but not rich.

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, concise sentence that front-loads the main purpose. Every word adds value, with no redundancy or filler. It is an exemplary model of efficient communication.

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

Completeness5/5

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

Given the tool's low complexity (no parameters, no output schema, simple read-only listing), the description is complete. It covers what the tool does (list aliases) and the special aspect (default alias), which is all a user needs to know for invocation and interpretation.

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 input schema has zero parameters and 100% schema coverage, so there are no parameter semantics to clarify. The baseline for 0 params is 4, and the description appropriately adds context about what will be listed (aliases and default), which is useful beyond the empty schema.

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 uses a specific verb 'List' and a distinct resource 'configured database aliases', and adds the important nuance of 'currently selected default alias'. This clearly distinguishes it from sibling tools like db.schema or db.query, which operate on database structures and data.

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: to see available database aliases and the default one, use this tool. However, it does not explicitly state when to prefer this over alternatives, nor does it mention any exclusions or related tools. The usage context is clear but not elaborated.

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

db.explainA

Return PostgreSQL EXPLAIN plans for one or more SELECT/WITH statements without executing them.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
paramsNo
databaseNo

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It discloses the key non-execution behavior, which is valuable safety information. However, it omits return format, handling of multiple statements, database selection behavior, and potential errors, leaving transparency incomplete.

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 sentence with no redundant words. It is front-loaded with the core function and immediately states the input scope, making it highly concise and well-structured.

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

Completeness2/5

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

Given the tool has 3 parameters, no annotations, and no output schema, the description is too thin. It omits parameter semantics, output format, and any constraints beyond SELECT/WITH. The agent would need to infer too much about how to use the tool correctly.

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?

Schema description coverage is 0%, so the description must explain all three parameters. It only hints at `sql` via 'statements' but does not clarify the meaning of `params` or `database`. This is insufficient for correct invocation.

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 function: returning PostgreSQL EXPLAIN plans for SELECT/WITH statements. The phrase 'without executing them' distinguishes it from query-executing tools like db.query, making the purpose unmistakable.

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 this tool should be used when non-executing query plans are needed, but it does not explicitly name alternatives or provide when-to-use vs when-not-to-use guidance. The distinction from db.query is implicit via 'without executing them' but never stated as a comparison.

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

db.indexesA

List PostgreSQL indexes for all user tables or one table using table or schema.table name.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableNo
databaseNo

TDQS

A3.6/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden. It clarifies that the tool lists indexes for 'user tables' (implying exclusion of system tables), which is useful scope context. However, it does not disclose the return format, behavior for invalid table names, or any permission requirements, leaving some behavioral aspects undisclosed.

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 sentence that is concise, front-loaded, and free of redundancy. It conveys the core information efficiently, earning a top score for conciseness.

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 simplicity of the tool, the description covers the main purpose and table parameter usage, but it is incomplete in explaining the 'database' parameter and the output structure. With no output schema or annotations, the description should provide more detail about what the listing returns and how the database parameter affects the query.

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?

Since schema description coverage is 0%, the description must compensate. It explains the 'table' parameter (accepts table or schema.table name) and implies that omitting it lists all user tables. However, the 'database' parameter is not mentioned at all, leaving its semantics completely unexplained.

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 function: 'List PostgreSQL indexes for all user tables or one table'. It specifies the resource (PostgreSQL indexes) and scope (all user tables or one table), and even mentions how to specify the table ('table or schema.table name'). This distinguishes it from sibling tools like db.constraints or db.table_info.

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 gives some usage context (e.g., listing for all tables or a specific table) but does not explicitly mention when to use this tool versus alternatives, nor does it provide exclusions or when-not-to-use guidance. It implies usage for index listing but lacks comparisons to sibling tools.

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

db.previewC

Preview rows from a table using table or schema.table name.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
tableYes
databaseNo

TDQS

C2.7/5.0
Behavior2/5

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

With no annotations, the description carries the full burden of behavioral disclosure. It does not mention how the limit parameter affects results, whether all columns are returned, the ordering of rows, or the default behavior. This is a significant gap for a data-access tool.

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

Conciseness4/5

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

The description is a single efficient sentence, front-loaded with the verb. It earns its place, but omits information about the other parameters and behavioral details, so it is concise rather than comprehensive.

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

Completeness2/5

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

For a tool with no output schema and no annotations, the description is too sparse. It does not explain return format, default limit, or database behavior. The presence of three parameters and a rich sibling context demands more detail.

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?

Schema coverage is 0%, so the description must explain parameters. It adds meaning to the 'table' parameter by noting it can be schema-qualified, but the 'limit' and 'database' parameters are completely undocumented. This is partial compensation at best.

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

Purpose4/5

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

The description clearly states the tool's action ('Preview rows from a table') and specifies the input format ('using table or schema.table name'). It is distinguishable from siblings like db.query and db.count based on the verb 'preview', though it doesn't explicitly name alternatives.

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?

There is no guidance on when to use this tool versus alternatives. The context is implied by the name 'preview', but the description does not state exclusions, prerequisites, or when to prefer db.query or other siblings.

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

db.queryA

Run one or more read-only SELECT queries with optional row limits. Multi-statement calls are allowed for non-parameterized SELECT/WITH statements; parameterized queries must be single-statement.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
paramsNo
maxRowsNo
databaseNo

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden and does well by disclosing read-only behavior, support for multi-statement non-parameterized queries, and the constraint that parameterized queries must be single-statement. It adds meaningful behavioral context beyond the bare schema.

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, front-loaded with the purpose, and each sentence adds distinct value—first stating what it does, second stating a key constraint. No waste.

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?

For a 4-parameter tool with no output schema, the description covers the main behaviors and constraints well. It does not describe the database parameter or result format, but the core usage is clear and sufficiently complete.

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?

Schema description coverage is 0%, so the description must compensate. It explains 'sql' as SELECT/WITH statements, 'params' as parameterized query values, and 'maxRows' as optional row limits. 'database' is not explicitly described, but the overall parameter meaning is significantly enriched.

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 runs one or more read-only SELECT queries, which is a specific verb+resource action. It distinguishes from siblings like db.count, db.explain, and db.validate_sql by focusing on executing SELECT queries directly.

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 provides context on when multi-statement queries are allowed (non-parameterized SELECT/WITH) and requires single-statement for parameterized queries. However, it does not explicitly mention alternatives or when to prefer other sibling tools like db.preview or db.count, so usage guidance is implied rather than explicit.

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

db.relationshipsA

List foreign-key relationships for all user tables or one table.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableNo
databaseNo

TDQS

A3.7/5.0
Behavior3/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 transparently indicates a read-only listing operation, but it does not describe output format, database parameter behavior, or whether system tables are excluded. The behavior is straightforward and consistent with the description, though minimal.

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 with no filler. It front-loads the verb 'List' and immediately states the resource and scope, making it extremely concise and easy to parse.

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

Completeness2/5

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

Given the absence of annotations, output schema, and parameter descriptions, the tool is simple but still leaves gaps. The database parameter is unexplained, and the return format is unspecified. The description is a bare minimum, not a complete guide for an agent to invoke the tool with confidence.

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?

Schema description coverage is 0%, so the description must compensate. It clarifies that the table parameter is optional, allowing 'all user tables or one table,' but it provides no explanation of the database parameter. This leaves one of two parameters semantically undocumented, which is a significant gap.

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 action (List) and resource (foreign-key relationships), and specifies the scope as all user tables or one table. This distinguishes it from sibling tools like db.constraints and db.schema, which cover broader constraint or schema information.

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 this tool: to list foreign-key relationships, either across all user tables or for a single table. It does not explicitly name alternatives or exclusions, but the usage intent is evident and directly communicated.

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

db.sample_valuesB

Return small distinct non-null sample values for selected columns in a table.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
tableYes
columnsYes
databaseNo

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 disclosing behavior. It reveals that values are distinct and non-null, which is useful, but it does not mention whether sampling is random, how ordering works, what happens for columns with no non-null values, or if database parameter is required. The behavior is partially transparent but not comprehensive.

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

Conciseness4/5

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

The description is a single sentence that is grammatically clear and front-loaded with the main verb. It is concise and free of fluff, but it could benefit from additional structural elements like examples or parameter explanations to aid understanding.

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

Completeness2/5

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

This tool has 4 parameters, no output schema, and no annotations. The description is too brief to convey the expected return structure (e.g., mapping of column to sample values), edge cases, or the role of the 'database' parameter. It is not complete enough for an agent to correctly invoke this tool without additional inference.

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?

Schema description coverage is 0%, and the description does not explain the 'limit' or 'database' parameters. It only hints at 'columns' via 'selected columns'. The description fails to compensate for the lack of schema descriptions, leaving two parameters semantically unexplained.

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 uses a specific verb ('Return') and clearly identifies the resource ('small distinct non-null sample values for selected columns in a table'). It distinguishes this tool from siblings like db.query (full query execution) and db.preview (likely raw row preview) by emphasizing sampling of distinct non-null values per column.

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 implied usage is to explore actual data values in columns, but there is no explicit statement about when to use this over alternatives (e.g., db.preview, db.query). No exclusions or alternative tool names are mentioned, so guidance is only implicit.

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

db.schemaB

Inspect database schema. Use mode='summary' for table list or mode='full' for columns and keys.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNo
filterNo
databaseNo

TDQS

B3.3/5.0
Behavior3/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 that the tool returns different output depending on mode, but does not explicitly state that the operation is read-only, nor does it explain behavior around the 'filter' or 'database' parameters. The term 'Inspect' implies non-mutating behavior, but some edge cases remain undisclosed.

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 extremely concise: two short sentences that immediately convey the core purpose and the two key usage modes. Every word earns its place, and the most important information is front-loaded.

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?

For a tool with no output schema, no annotations, and 3 unspecified parameters, the description only partially completes the picture. It explains what the tool does and the mode options, but lacks details on 'filter' and 'database' parameters, default behavior, and any side effects. It is adequate for a simple inspection tool but leaves 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 input schema has 3 parameters with 0% schema description coverage, so the description must compensate for all parameter meanings. It only explains the 'mode' parameter ('summary' vs 'full') and leaves 'filter' and 'database' entirely unexplained. This is a significant gap given the lack of schema descriptions.

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

Purpose4/5

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

The description clearly states a specific verb ('Inspect') and resource ('database schema'), and distinguishes the two modes ('summary' for table list, 'full' for columns and keys). It is easily distinguishable from sibling tools like db.table_info, though it does not explicitly call out the difference.

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 gives clear guidance on when to use each mode ('Use mode='summary' for table list or mode='full' for columns and keys'), which is useful. However, it does not explain when this tool should be preferred over sibling tools like db.table_info or db.indexes, leaving the cross-tool decision to the agent.

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

db.table_infoA

Inspect one table's columns, indexes, constraints, foreign-key relationships, and triggers.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableYes
databaseNo

TDQS

A3.9/5.0
Behavior4/5

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

Without annotations, the description carries the transparency burden. The verb 'Inspect' strongly conveys a read-only, non-destructive operation, and the list of inspected elements adds behavioral context about the scope of the operation. However, it does not mention return format or potential errors, leaving a small gap.

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, front-loaded sentence that lists all relevant outputs without filler. Every word contributes to the tool's purpose, and it is immediately scannable.

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?

Given the tool's simplicity (2 parameters, no output schema) and the absence of annotations, the description provides adequate context by enumerating the exact metadata returned. It lacks detail on return structure, but the list of items is sufficient for an agent to understand what to expect.

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 0% description coverage, so the description must compensate. It explicitly refers to 'one table' which clarifies the 'table' parameter, but gives no guidance on the 'database' parameter, including its optionality or purpose. The description adds minimal value beyond the parameter names themselves.

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 uses a specific verb ('Inspect') and clearly identifies the resource ('one table') and the exact information returned: columns, indexes, constraints, foreign-key relationships, and triggers. This distinguishes it from sibling tools like db.indexes or db.constraints, which each cover only one aspect.

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 when to use this tool (when you need comprehensive metadata about a single table) but does not explicitly contrast it with specialized siblings such as db.indexes or db.schema. No when-not guidance or alternative tools are mentioned.

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

db.validate_insertA

Validate one or more INSERT statements without executing them. Uses EXPLAIN without ANALYZE, so rows are never inserted. Parameterized validation must be single-statement.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
paramsNo
databaseNo

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 burden and it delivers: it states that rows are never inserted via EXPLAIN without ANALYZE, and adds a behavioral constraint about parameterized validation being single-statement. This provides substantial transparency beyond the raw schema.

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-loaded with the main purpose and immediately followed by the key constraint. Every sentence adds value, with no fluff or repetition of schema details.

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 core purpose and safety guarantee, but lacks details on return behavior (there is no output schema) and does not explain the 'database' parameter. Given the moderate complexity and absence of annotations, this leaves notable 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?

Schema description coverage is 0%, so the description must compensate. It only mentions 'parameterized validation' as a concept but does not explain the meaning or usage of the 'params' array or the 'database' parameter. This is insufficient for the three parameters present.

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 validates INSERT statements without executing them, using a specific verb ('Validate') and resource ('INSERT statements'). This distinguishes it from sibling tools like db.validate_sql and db.explain by focusing specifically on INSERT statements.

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 gives clear context: use this to validate INSERT statements without side effects, and notes a key constraint that parameterized validation must be single-statement. It does not explicitly name alternatives or exclusions, but the dedicated purpose is evident.

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

db.validate_sqlB

Validate SELECT, INSERT, UPDATE, or DELETE statements without executing them by using EXPLAIN without ANALYZE.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
modeYes
paramsNo
databaseNo

TDQS

B3.4/5.0
Behavior3/5

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

No annotations are provided, so the description carries the burden of behavioral disclosure. It clearly states that statements are not executed, which is a key safety behavior. However, it does not disclose what happens on success/failure (e.g., return format, errors), or any potential side effects like lock acquisition or permission checks during EXPLAIN.

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?

A single concise sentence that states the action, scope, and mechanism. Every word earns its place; there is no filler or redundancy.

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

Completeness2/5

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

The tool has 4 parameters (2 required), no output schema, and no annotations. The description covers core intent but omits important operational details such as return behavior, error handling, and the role of optional parameters. Given the sibling tools and complexity, the description is not complete enough for reliable invocation.

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?

Schema description coverage is 0%, so the description must compensate. It explains the 'mode' values (SELECT, INSERT, UPDATE, DELETE) and implies the 'sql' parameter is the statement. However, it provides no guidance on the optional 'params' (bind parameters) or 'database' parameters, which are left entirely to the schema.

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

Purpose4/5

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

The description identifies a specific verb ('Validate') and resource ('SELECT, INSERT, UPDATE, or DELETE statements'), and clearly distinguishes from execution by noting it validates 'without executing them'. However, it does not explicitly differentiate from the sibling tool db.validate_insert, which may overlap for INSERT statements.

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: use when you want to validate SQL statements without executing them. It does not mention explicit alternatives or exclusions, but the mechanism (EXPLAIN without ANALYZE) implies a safe, non-mutating validation approach. No when-not-to-use guidance is given.

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

db.watchA

Fetch one incremental batch where cursorColumn > lastCursor. Repeat client-side for polling.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableYes
databaseNo
batchSizeNo
lastCursorNo
cursorColumnNo

TDQS

A3.8/5.0
Behavior3/5

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

With no annotations, the description carries the full burden of behavioral disclosure. It explains the stateless incremental fetch pattern, but omits important traits: what happens when lastCursor is null, how to derive the next cursor from the response, behavior for deletions or out-of-order inserts, and any rate limiting or consistency guarantees.

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 short sentences, front-loaded with the core behavior and usage pattern. Every word earns its place with no redundant or filler content.

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

Completeness2/5

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

Given 5 parameters, no annotations, no output schema, and the complexity of cursor-based polling, the description is under-specified. It does not explain the return shape, how to obtain the next cursor, handling of initial lastCursor=null, or potential pitfalls (e.g., non-unique cursorColumn). This leaves significant ambiguity for correct invocation.

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

Parameters3/5

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

Schema has 0% description coverage, so the description must compensate. It explicitly explains the relationship between cursorColumn and lastCursor, but leaves batchSize, database, and the default/purpose of lastCursor (null case) unexplained. Partial compensation for the two key cursor parameters.

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 uses a specific verb ('Fetch') and resource ('one incremental batch'), and clearly states the core mechanism (cursorColumn > lastCursor). It distinguishes db.watch from general query tools like db.query by emphasizing incremental, cursor-based fetching.

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 phrase 'Repeat client-side for polling' explicitly frames this as a polling tool and indicates a client-driven loop. It does not name alternative tools or list exclusions, but the incremental polling context is clear enough to imply when this tool is appropriate.

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. Dates show when Glama detected each change.

  1. 14 tool updatesv1.1.1
    • First observeddb.constraints
    • First observeddb.count
    • First observeddb.databases
    • First observeddb.explain
    • First observeddb.indexes
    • First observeddb.preview
    • First observeddb.query
    • First observeddb.relationships
    • First observeddb.sample_values
    • First observeddb.schema
    • First observeddb.table_info
    • First observeddb.validate_insert
    • First observeddb.validate_sql
    • First observeddb.watch

TDQS

A3.6/5.0
Disambiguation4/5

Most tools have clearly distinct purposes (querying, counting, previewing, explaining, validating). However, validate_insert is a subset of validate_sql, and table_info can duplicate indexes/constraints/relationships for a single table, creating minor confusion.

Naming Consistency4/5

All tools use the same 'db.' prefix and snake_case, which is consistent. However, the second part mixes nouns (databases, schema, query) and verbs (validate_insert, explain, watch), so the pattern is not strictly verb_noun but still predictable.

Tool Count5/5

14 tools is well within the ideal range for a dedicated read-only database server. Each tool addresses a distinct need without excessive redundancy, and the count feels appropriate for the scope.

Completeness5/5

The server covers all typical read-only operations: listing databases, inspecting schema, querying, counting, previewing, sampling, explaining, and validating writes without executing. It also includes incremental polling, making it a comprehensive surface for a read-only Postgres MCP server.

Maintenance

ActivityInactive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A secure MCP server that enables querying PostgreSQL databases through an SSH tunnel with enforced read-only access, connection pooling, and comprehensive data exploration tools.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Read-only PostgreSQL MCP server that enables running SELECT queries, listing tables and schemas, and describing columns, with built-in protection against writes and malicious SQL attacks.
    751
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A read-only MCP server for PostgreSQL that enables safe database introspection and querying via natural language.
    751
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for PostgreSQL that enables safe read-only database queries, table schema inspection, and query execution planning.
    6
    29
    BSD 3-Clause

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/mahin1995/postgres-mcp-readonly'

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