Kenning PG MCP
Provides tools for interacting with a PostgreSQL database, including listing schemas and objects, describing table structures, executing read-only queries, explaining query plans, listing extensions, and (in unrestricted mode) executing DML statements.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Kenning PG MCPshow me the schema of the orders table"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Kenning PG MCP
A PostgreSQL Model Context Protocol server built on two convictions:
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 withuv sync --frozen. Nothing resolves at launch time.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
VOLATILEfunction that writes, orCOPY ... TO PROGRAMall 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 SQLSTATE25006— 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(), andpg_terminate_backend()— capabilities that begin withSELECTorCOPYand would sail through any keyword guard. A read-only transaction does not stop them: none writes to a relation, so25006never fires (verified against PostgreSQL 18, whereCOPY (SELECT ...) TO PROGRAMexecutes arbitrary commands insideBEGIN TRANSACTION READ ONLYas 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_timeoutandidle_in_transaction_session_timeoutare 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:
A write inside a read-only transaction must fail with
25006.The connection role must not be a superuser and must hold none of
pg_read_server_files,pg_write_server_files, orpg_execute_server_program. Override withPG_MCP_ALLOW_SUPERUSER=trueon 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-mcpOr 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) |
| — |
Access mode |
|
|
Allow a privileged role |
|
|
Transport |
|
|
HTTP bind host / port |
|
|
Max rows / response bytes |
|
|
Statement timeout |
|
|
Pool min / max |
|
|
Schema allowlist (comma-sep) |
| all non-system |
Log level |
|
|
Flags --access-mode, --transport, --host, --port override the
environment. The effective configuration is logged at startup with the
connection password redacted.
Tools
Tool | Purpose |
| Schemas, honoring the allowlist. |
| Tables, views, matviews, sequences in a schema. |
| Columns, PK, FKs both directions, indexes, constraints, comments, approximate row count. |
| One read statement in a read-only transaction; capped results with an explicit truncation notice (no |
|
|
| Installed and available extensions. |
| Version, role, database, access mode, key settings. |
| Single DML statement — registered only in |
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-mcpClients 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 suiteThe 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 toolsdescribe_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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| schema | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| params | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| analyze | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| schema | Yes | ||
| object_type | No | ||
| name_pattern | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
7 tool updates
v0.1.0- First observed
describe_object - First observed
execute_query - First observed
explain_query - First observed
list_extensions - First observed
list_objects - First observed
list_schemas - First observed
server_info
TDQS
Scored across 7 tools
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.
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.
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.
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
Related MCP Connectors
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Hosted MCP server for PostgreSQL diagnostics: slow queries, missing indexes, connection pressure.
Query your Postgres from ChatGPT or Claude without exposing the database or handing over credentials. Run npx boltschema connect next to your database and it dials out over HTTPS — no inbound firewall rule, no open port, works with localhost and VPC-private databases. Read-only is enforced by a SQL guard, a Postgres READ ONLY transaction, and a scoped role generated for you.
Draxlr's remote MCP server connects AI assistants to your SQL databases and dashboards. Explore schemas, run read-only queries, manage saved queries and dashboards, and export results, all with row-level security so each user sees only their own data.
Related MCP Servers
- -licenseNot gradedqualityAmaintenanceA 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 npm90,399MIT
- AlicenseNot gradedqualityDmaintenanceA 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 npm3MIT
- AlicenseNot gradedqualityDmaintenanceA 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 npmMIT
- AlicenseNot gradedqualityDmaintenanceA 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