Skip to main content
Glama
kenningai

Kenning PG MCP

by kenningai

Kenning PG MCP

A PostgreSQL Model Context Protocol server built on two convictions:

  1. Dependencies are pinned exactly. Every dependency is resolved once, recorded in a committed lockfile, and upgraded only as a deliberate, reviewed act. The published package carries == pins; the Docker image is built with uv sync --frozen. Nothing resolves at launch time.

  2. Read-only means the database says no — not a regex. Access control is transaction- and role-based. The server never inspects SQL text to decide whether a statement is "safe," because that model is unwinnable: a data-modifying CTE, a VOLATILE function that writes, or COPY ... TO PROGRAM all pass keyword filters. PostgreSQL itself is the enforcement.

Built on the MCP Python SDK v2 (2026-07-28 stateless protocol revision), psycopg 3, and pydantic-settings. Serves stdio and streamable HTTP from one set of handlers.

The security model

Four layers, none of which parse SQL:

  • Read-only transactions. Every read path runs inside BEGIN ... READ ONLY. PostgreSQL rejects any write attempt with SQLSTATE 25006 — including data-modifying CTEs, SELECT ... FOR UPDATE, and volatile functions that write.

  • One statement per call, enforced by the server. Every user statement is executed through the extended query protocol, where PostgreSQL rejects multi-command strings outright. Statement stacking dies in the database, not in a parser.

  • A purpose-built role, checked at startup. Connect as a minimal role (SQL below). This is what blocks COPY ... TO PROGRAM, pg_read_file(), lo_export(), and pg_terminate_backend() — capabilities that begin with SELECT or COPY and would sail through any keyword guard. A read-only transaction does not stop them: none writes to a relation, so 25006 never fires (verified against PostgreSQL 18, where COPY (SELECT ...) TO PROGRAM executes arbitrary commands inside BEGIN TRANSACTION READ ONLY as a superuser). Because documentation is not enforcement, the server verifies the role itself rather than trusting the deployment to have followed it. Privilege, not pattern matching.

  • Timeouts on every session. statement_timeout and idle_in_transaction_session_timeout are set at connection time, so a badly planned query cannot pin a connection indefinitely.

On startup (in restricted mode) the server runs two probes before serving a single query, and exits non-zero rather than silently serving a read-only server that isn't:

  1. A write inside a read-only transaction must fail with 25006.

  2. The connection role must not be a superuser and must hold none of pg_read_server_files, pg_write_server_files, or pg_execute_server_program. Override with PG_MCP_ALLOW_SUPERUSER=true on a trusted, disposable database; the override logs a prominent warning.

In unrestricted mode the privilege probe warns rather than refuses: enabling writes is consent to modify data, not consent to read server files or execute programs as the database OS user.

An adversarial test suite attempts every bypass listed above against a real PostgreSQL as a low-privilege role; every case must fail at the database.

Write access is never inferred. In the default restricted mode the write tool is not merely refused — it is not registered, so it never appears in tools/list. Setting PG_MCP_ACCESS_MODE=unrestricted registers a single DML tool; read tools still run read-only transactions.

The role

The requirement is negative: do not connect as a superuser. An ordinary application or reporting role already satisfies it — not a superuser, no filesystem roles — and needs no configuration. restricted mode still blocks every write such a role could otherwise make, because the transaction layer does not care what the role is permitted to do. Point the server at the least-privileged existing role that can see your data.

Creating a dedicated role, below, narrows what is visible. It is a refinement for organizations that provision service accounts per consumer, not a prerequisite for read-only safety:

CREATE ROLE mcp_ro LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE mydb TO mcp_ro;
GRANT USAGE ON SCHEMA public TO mcp_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_ro;
ALTER ROLE mcp_ro SET default_transaction_read_only = on;
ALTER ROLE mcp_ro SET statement_timeout = '30s';
ALTER ROLE mcp_ro SET idle_in_transaction_session_timeout = '60s';

For read-write deployments, the equivalent role carries INSERT, UPDATE, DELETE and nothing more. DDL is an operator decision, not a server feature.

Related MCP server: PostgreSQL Multi-Schema MCP Server

Install

The server is a deployable tool, not a library — install it isolated, where exact pins are a feature:

uv tool install kenning-pg-mcp        # or: pipx install kenning-pg-mcp

Or use the Docker image (the primary distribution artifact — resolution happens at build time, never at launch):

docker build -t kenning-pg-mcp:0.2.0 .

Do not run this server via uvx. uvx re-resolves against PyPI on every invocation, which is the exact failure mode this project exists to eliminate. Install once, pin the version, upgrade deliberately.

Configuration

Setting

Env var

Default

Connection URI (required)

DATABASE_URI

Access mode

PG_MCP_ACCESS_MODE

restricted

Allow a privileged role

PG_MCP_ALLOW_SUPERUSER

false

Transport

PG_MCP_TRANSPORT

stdio

HTTP bind host / port

PG_MCP_HOST / PG_MCP_PORT

127.0.0.1 / 8000

Max rows / response bytes

PG_MCP_MAX_ROWS / PG_MCP_MAX_BYTES

1000 / 50000

Statement timeout

PG_MCP_STATEMENT_TIMEOUT

30s

Pool min / max

PG_MCP_POOL_MIN / PG_MCP_POOL_MAX

1 / 5

Schema allowlist (comma-sep)

PG_MCP_SCHEMAS

all non-system

Log level

PG_MCP_LOG_LEVEL

INFO

Flags --access-mode, --transport, --host, --port override the environment. The effective configuration is logged at startup with the connection password redacted.

Tools

Tool

Purpose

list_schemas

Schemas, honoring the allowlist.

list_objects

Tables, views, matviews, sequences in a schema.

describe_object

Columns, PK, FKs both directions, indexes, constraints, comments, approximate row count.

execute_query

One read statement in a read-only transaction; capped results with an explicit truncation notice (no LIMIT is ever injected into your SQL).

explain_query

EXPLAIN (FORMAT JSON); analyze=true always runs inside a rolled-back transaction.

list_extensions

Installed and available extensions.

server_info

Version, role, database, access mode, key settings.

execute_statement

Single DML statement — registered only in unrestricted mode.

Results serialize honestly: numeric → string (never float), timestamps → ISO 8601 with timezone, bytea → base64 with a length note, json/jsonb → nested structures, NULL → null.

max_bytes bounds the result as the model receives it — the pretty-printed text block, columns, truncation object and notice included — not the row payload and not compact JSON, both of which understate the real cost. The default is sized against the model's context rather than the transport: 50 KB is roughly 12k tokens, where the 1 MiB response limit hosts commonly enforce would be ~250k — a result that transits successfully and then consumes the conversation it was meant to inform. Truncation is self-correcting, since the notice tells the model to add LIMIT, filter, or aggregate.

Claude Desktop

{
  "mcpServers": {
    "postgres": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "DATABASE_URI", "kenning-pg-mcp:0.2.0"],
      "env": {
        "DATABASE_URI": "postgresql://mcp_ro:PASSWORD@host.docker.internal:5432/mydb"
      }
    }
  }
}

Or with a tool install:

{
  "mcpServers": {
    "postgres": {
      "command": "/absolute/path/to/kenning-pg-mcp",
      "env": {
        "DATABASE_URI": "postgresql://mcp_ro:PASSWORD@localhost:5432/mydb"
      }
    }
  }
}

HTTP mode

PG_MCP_TRANSPORT=http kenning-pg-mcp

Clients connect to http://127.0.0.1:8000/mcp. Binding beyond loopback requires PG_MCP_ALLOW_REMOTE=true, and there is no built-in authentication — put the server behind a reverse proxy that authenticates, and set PG_MCP_ALLOWED_HOSTS / PG_MCP_ALLOWED_ORIGINS to match your deployment.

Development

uv sync --frozen
make check          # lint + type-check + full test suite

The test suite has three layers: unit (no database), integration against a real PostgreSQL via testcontainers, and an adversarial layer that attempts every write-bypass in the threat model as a low-privilege role — each case must fail at the database. Docker is required for the latter two.

License

Licensed under the MIT License. Use it for anything.

Available Tools

7 tools
describe_objectA

Describe one relation: columns (name, type, nullable, default, comment), primary key, foreign keys in both directions, indexes, check and unique constraints, and an approximate row count from pg_class.reltuples. Cheap. Prefer this over querying catalogs by hand; use it before writing queries against unfamiliar tables.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
schemaYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/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 that the operation is cheap/read-only, that row counts are approximate (from reltuples, not exact), and enumerates the full scope of what's returned. This is strong transparency for an introspection tool with zero annotation support.

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?

Three sentences, all high-value: what it returns, cost signal, and when to use. Front-loaded with the core purpose, no wasted words.

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?

There is an output schema (covering return values), so the description need not enumerate the response format. The tool is simple (2 params, no nesting) and the description fully covers behavioral caveats (approximate count, cheap) and usage context. Nothing substantive is missing.

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 coverage is 0% for two trivial parameters (schema, name). The description explains what the tool does but doesn't elaborate on the parameters themselves beyond what's obvious from their names and types. However, for introspection tools, schema and name are self-evident; the baseline 3 is acceptable since the description doesn't add semantics the names don't already convey.

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?

Specific verb+resource: 'Describe one relation' followed by an exhaustive enumeration of what it returns (columns, PK, FKs both directions, indexes, constraints, row count). Clearly distinguishes from siblings like execute_query and list_objects by being a dedicated introspection tool.

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

Usage Guidelines5/5

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

Provides explicit guidance: 'Prefer this over querying catalogs by hand; use it before writing queries against unfamiliar tables.' Also notes cheapness ('Cheap'), giving clear cost-based rationale for use. Mentions pg_class.reltuples for approximate counts, setting expectations.

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

execute_queryA

Run a single read-only SQL statement inside a READ ONLY transaction and return {columns, rows, row_count, truncated, notice?}. Exactly one statement per call. Use %s placeholders with the params list for user-supplied values. Results are capped at the configured row and byte limits with an explicit truncation notice when more data exists — no LIMIT is ever injected into your SQL. Cost depends entirely on the query; run explain_query first for anything potentially expensive.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
paramsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/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. It discloses key behaviors: read-only nature, single-statement enforcement, result capping with truncation notices, no injected LIMIT, and cost dependency on the query. It doesn't mention permission requirements or what happens on SQL errors, but covers the significant behavioral traits well.

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?

Compact multi-line description with zero wasted words. Front-loaded with the core action, then the return contract, then params usage, then the truncation/cost caveats. Every sentence earns its place — no filler or repetition of schema fields.

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 tool with an output schema present and several behavioral nuances, the description is thorough. It covers the single-statement constraint, placeholder usage, truncation semantics, and cost guidance. It's slightly shy of complete — could mention error handling and permissions — but given the complexity and the presence of an output schema, this is well covered.

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 coverage is 0% and there are 2 params with an empty schema (sql and params have no descriptions). The description compensates well: it explains the %s placeholder mechanism for params and the placeholder-binding pattern. It doesn't detail param type constraints beyond 'user-supplied values', but adds meaningful semantics to an otherwise bare 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?

Description states a specific verb+resource: 'Run a single read-only SQL statement' and explicitly frames it as READ ONLY within a transaction. It specifies the return shape ({columns, rows, row_count, truncated, notice?}) and distinguishes itself by requiring 'Exactly one statement per call' — differentiating from siblings like describe_object and list_objects.

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?

Description gives strong usage context: how to use %s placeholders with params, that results are capped with truncation notice, and that no LIMIT is injected. It explicitly says to 'run explain_query first for anything potentially expensive', which advises on when to use a sibling tool. It could add explicit when-not-to-use conditions but the guidance is substantive.

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

explain_queryA

Return the PostgreSQL execution plan (EXPLAIN, FORMAT JSON) for a single statement. Cheap without analyze. With analyze=true the statement is actually executed to collect real timing — the transaction is always rolled back, so even in read-write mode nothing persists, but the statement's runtime cost is fully paid. Parameters are not supported here; inline literal values instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
analyzeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations provided, the description carries full burden and excels at it. It transparently discloses that analyze=true actually executes the statement, that the transaction always rolls back, and that despite rollback the runtime cost is incurred. This is exactly the kind of behavioral nuance an agent needs to make safe decisions about using analyze mode.

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 three sentences, front-loaded with the core purpose, and every sentence adds value. It's compact but covers the essential caveats. Minor inefficiency: 'for a single statement' is slightly redundant with EXPLAIN semantics, but this is a minor nit.

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?

Despite no annotations and 0% schema coverage, the description thoroughly covers the critical safety context (transaction rollback, real execution cost), parameter constraints (inline literals only), and purpose. With an output schema present and only 2 simple parameters, this description is fully adequate for safe and correct tool 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 coverage is 0%, so description must compensate. The description explains the analyze parameter's semantics well (executes for real timing, rolls back, costs runtime) and notes sql takes inline literals not parameters. However, it doesn't detail the sql parameter's format expectations beyond that, leaving the agent to infer SQL syntax requirements.

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 returns a PostgreSQL EXPLAIN execution plan in JSON format for a single statement. It distinguishes itself from execute_query (which actually runs queries) by emphasizing this is EXPLAIN only, and the verb+resource ('Return the PostgreSQL execution plan') is specific and accurate.

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

Usage Guidelines5/5

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

The description explicitly explains when to use analyze=true vs false, notes that parameters are not supported (inline literals required), and clarifies the transactional rollback behavior. This gives clear guidance on how to invoke the tool correctly, particularly the important caveat that runtime cost is 'fully paid' even though the transaction rolls back.

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

list_extensionsA

List installed and available PostgreSQL extensions with versions and descriptions. Cheap. Check here whether an extension (pg_stat_statements, postgis, hypopg, ...) exists before writing queries that depend on it.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

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

No annotations provided, so the description carries the disclosure burden. It signals the tool is 'Cheap' (low cost), disclosing performance characteristics. The read-only nature is implicit from 'list installed and available extensions.' It doesn't describe the output format, but with an output schema present and a 0-param read operation, the behavioral disclosure is adequate.

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?

Three sentences, zero waste. The first sentence states purpose and contents, the second notes cost, the third gives a concrete usage scenario. Every sentence earns its place and the actionable guidance is front-loaded and clear.

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?

For a 0-parameter introspection tool with an output schema present, the description is complete. It explains what data is returned (versions, descriptions), notes cost, and gives a practical use case. No missing prerequisites, parameters, or behavioral caveats are relevant here.

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 0 parameters, so there is nothing to document. Schema coverage is 100% (trivially). The baseline for 0-param tools is 4, and the description doesn't need to add parameter semantics since none exist. The examples enumerate extensions it will surface, adding semantic color 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?

Specific verb+resource (list extensions) with clear scope: 'installed and available PostgreSQL extensions with versions and descriptions.' The examples (pg_stat_statements, postgis, hypopg) and the phrase 'Cheap' add useful distinctiveness. It's clearly differentiated from sibling list_schemas/list_objects.

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

Usage Guidelines5/5

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

Explicit guidance on when to use: 'Check here whether an extension exists before writing queries that depend on it.' This is a clear usage directive with a concrete scenario. Though it doesn't name alternatives, the purpose (introspection-check before query) is unambiguous for a 0-param read tool.

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

list_objectsA

List tables, views, materialized views, sequences, and foreign tables in a schema, with comments and approximate row counts. Cheap. Filter by object_type and/or a SQL LIKE name_pattern (e.g. 'order%'). Prefer describe_object for the full shape of a single relation.

ParametersJSON Schema
NameRequiredDescriptionDefault
schemaYes
object_typeNo
name_patternNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

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

No annotations are provided, so the description carries the full behavioral burden. It discloses that the tool returns approximate row counts (not exact), mentions it is 'Cheap' (a performance trait), and lists the scope of object types covered. It doesn't discuss permission requirements or error behavior, but the 'Cheap' and approximate-count disclosures are genuinely useful behavioral context beyond schema.

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?

Three sentences, each adding value: scope+behavior, filtering instructions with example, and sibling differentiation. The front-loaded first sentence is information-dense. Minor deduction for somewhat technical phrasing ('a SQL LIKE name_pattern') that could be more direct, but it's economical and well-organized.

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 has an output schema (so return values are covered there) and 3 params with 0% schema coverage, but the description documents the main semantics of the two filter params and the scoping behavior. It's complete enough for an agent to select and call correctly. Minor gaps: no mention of whether schema must exist, ordering of results, or pagination/limits, but the 'Cheap' note and existing structure make this adequate.

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 coverage is 0%, so the description must compensate. The description explains the semantics of object_type (filter by type, with allowed values implied by the sibling mention of table/view/etc.) and name_pattern (SQL LIKE pattern, with example 'order%'). However, the 'schema' parameter is never described beyond being the target namespace, and the anyOf/null structure isn't fully clarified. The description adds meaningful value but doesn't fully cover all 3 params.

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 specific verbs and enumerates the exact resource types (tables, views, materialized views, sequences, foreign tables) in a schema. It clearly distinguishes from siblings by mentioning the full shape of a single relation belongs to describe_object, and the general-purpose execute_query is implied as an alternative for arbitrary queries.

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

Usage Guidelines5/5

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

The description gives explicit guidance on when to use this tool vs describe_object ('Prefer describe_object for the full shape of a single relation'), provides filtering examples with object_type and SQL LIKE name_pattern ('order%'), and notes it is 'Cheap' so agents know it's safe to call. The when/when-not guidance is explicit and actionable.

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

list_schemasA

List database schemas visible to this server, honoring the configured schema allowlist. Cheap. Call this first to see what exists; then use list_objects to look inside a schema.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/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 that the operation is 'Cheap' (performance characteristic) and that output respects an allowlist filter. These are genuinely useful behavioral traits beyond what schema/annotations convey.

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?

Three sentences, zero wasted words. The description front-loads the core purpose, adds the allowlist behavioral note, flags cost ('Cheap'), and ends with actionable next-step guidance. Every sentence earns its place.

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?

For a zero-parameter listing tool with an output schema present, the description is fully complete. It declares purpose, scoping behavior, cost profile, and the follow-up tool to use. The output schema handles return-value documentation, so nothing critical is missing.

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 schema coverage is 100% (trivially, since there are no params to document). The baseline for 0-param tools is 4, and the description appropriately adds no parameter noise while providing purpose context that helps the agent understand what the (empty) invocation will return.

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 states a specific verb+resource ('List database schemas visible to this server') with precise scope ('honoring the configured schema allowlist'). It clearly distinguishes from siblings by pointing to list_objects as the tool for looking inside a schema, positioning list_schemas as the top-level listing operation.

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

Usage Guidelines5/5

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

Explicit guidance is provided: 'Call this first to see what exists; then use list_objects to look inside a schema.' This tells the agent when to invoke it (as an entry point) and directs to the appropriate alternative (list_objects) for the next step.

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

server_infoA

Report server version, current role and database, effective access mode, and key settings (timeouts, search_path, recovery state). Cheap. Useful for orientation and for diagnosing permission or timeout surprises.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/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 that the tool is read-only-ish ('Report'), 'Cheap' (low cost/low latency expectation), and non-destructive in nature, which is appropriate for what appears to be a diagnostic read operation. The 'Cheap' disclosure is behavioral context beyond what schema conveys. It doesn't mention error conditions or response shape, but the output schema exists to cover that.

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?

Three sentences, all earning their place: the first enumerates the reported fields, the second notes the cost profile, the third gives usage guidance. Slightly dense opening sentence but efficient overall. No filler or redundancy.

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 zero-parameter, zero-tool diagnostic with a rich output schema present, the description is complete: it enumerates what will be returned, signals cost, and gives usage intent. The output schema covers return structure. The only minor gap is that it doesn't explicitly note this is read-only/safe, but the verb 'Report' and 'Cheap' reasonably imply that.

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, so the baseline is 4 per the rubric. Schema coverage is 100% and there is nothing to document param-wise. The description adds all necessary context about what is reported without needing any parameter explanation.

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 states a specific verb ('Report') with a clear resource (server info) and enumerates the exact content items: version, role, database, access mode, timeouts, search_path, recovery state. It clearly distinguishes itself from siblings like list_schemas/list_objects/list_extensions by focusing on server-level metadata, and uses the qualifier 'Cheap' to differentiate cost profile.

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?

Explicitly states when to use it: 'Useful for orientation and for diagnosing permission or timeout surprises.' It doesn't explicitly name alternatives or when-not-to-use, but the 'orientation' framing plus 'Cheap' cost note effectively guides an agent toward this for quick diagnostics over heavier query tools. A clear exclusions list would push this to 5.

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. 7 tool updatesv0.1.0
    • First observeddescribe_object
    • First observedexecute_query
    • First observedexplain_query
    • First observedlist_extensions
    • First observedlist_objects
    • First observedlist_schemas
    • First observedserver_info

TDQS

A4.5/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: describe_object inspects a single relation's shape, execute_query runs SQL, explain_query plans SQL, list_extensions and list_schemas enumerate namespaces, list_objects lists relations in a schema, and server_info reports environment. No two tools overlap in function.

Naming Consistency4/5

Most tools follow a consistent verb_object pattern (describe_object, execute_query, explain_query, list_extensions, list_schemas, list_objects, server_info). The only slight deviation is the phrase-based server_info which could be get_server_info, but it's still clearly readable and consistent with the snake_case convention.

Tool Count5/5

Seven tools is a well-scoped count for a PostgreSQL inspection server. Each tool earns its place covering discovery, planning, execution, and environment introspection without bloat.

Completeness5/5

The surface covers the full inspection lifecycle: orientation (server_info, list_schemas, list_extensions), table discovery (list_objects), full schema detail (describe_object), planning (explain_query), and execution (execute_query). The guidance embedded in descriptions (e.g., run explain first, check extensions before depending on them) chains the tools into a complete workflow with no dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • -
    license
    Not graded
    quality
    A
    maintenance
    A Model Context Protocol server that provides read-only access to PostgreSQL databases. This server enables LLMs to inspect database schemas and execute read-only queries.
    93,517 npm
    90,399
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol server that provides read-only access to PostgreSQL databases with enhanced multi-schema support, allowing LLMs to inspect database schemas across multiple namespaces and execute read-only queries while maintaining schema isolation.
    67 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol server that provides read-only access to PostgreSQL databases, enabling LLMs to inspect database schemas and execute read-only queries.
    93,517 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol server that provides AI assistants with secure, read-only access to PostgreSQL databases while offering comprehensive tools for schema exploration, query validation, and performance optimization.
    MIT