Skip to main content
Glama
eric-patton

postgres-schema-mcp

by eric-patton

postgres-schema-mcp

An MCP server that gives an AI agent read-only access to a PostgreSQL database. Browse the schema, follow foreign keys, search columns across hundreds of tables, run capped SELECTs, and export an offline data dictionary.

Writes are rejected, and there are tests that prove it.

It runs over stdio for one developer and over authenticated HTTP for a team.

npx postgres-schema-mcp

An agent chaining find_columns, table_relationships and run_select to answer one question, then being refused a DELETE

Three calls to answer a question no single tool answers: find the join column, follow the keys, then write the query. No schema pasted into the prompt and no column names guessed. The last few seconds are the part that matters more than the answer.

Nothing in that recording is staged. It is scripts/demo.mjs, a real MCP client driving the real server against the sample database below, and scripts/record-demo.ps1 re-records it. Both are committed so the GIF cannot quietly start showing something that is no longer true.

Why this one

Most database MCP servers hand an agent a connection and hope. This one assumes the agent will eventually be asked to do something destructive, by a confused user or a poisoned document, and is built so that the attempt fails three separate times.

The three layers are independent, and each is enough on its own:

  1. The query is parsed and refused unless it is a single SELECT or WITH. Stacked statements, DDL, DML, SELECT INTO, data-modifying CTEs, DO blocks and functions that execute SQL passed as text are all refused. Thirty hostile statements are asserted rejected in test/injection.test.ts.

  2. Every query runs inside BEGIN READ ONLY with a statement timeout and an idle-in-transaction timeout, and the transaction is always rolled back, never committed.

  3. The role you connect as holds SELECT and nothing else. The GRANT statements are below.

The test suite proves layers 2 and 3 separately rather than together. One test connects as a superuser and confirms a write is still refused, which can only be the read-only transaction doing it. Another connects as the least-privileged role and confirms a sequence advance is refused there too, which the keyword parser never sees.

There is no READ_ONLY=false escape hatch. Setting READ_ONLY, PGSM_READ_ONLY, ALLOW_WRITES or PGSM_ALLOW_WRITES to anything at all makes the server refuse to start, with a message saying the switch does not exist. If you need writes, use a different server.

Related MCP server: PostgreSQL MCP Server

Install

Claude Code

claude mcp add postgres-schema \
  --env DATABASE_URL=postgres://mcp_reader:PASSWORD@localhost:5432/yourdb \
  -- npx -y postgres-schema-mcp

Claude Desktop, Cursor, and anything else taking JSON

{
  "mcpServers": {
    "postgres-schema": {
      "command": "npx",
      "args": ["-y", "postgres-schema-mcp"],
      "env": {
        "DATABASE_URL": "postgres://mcp_reader:PASSWORD@localhost:5432/yourdb"
      }
    }
  }
}

As a desktop bundle

Clients that install a single file rather than run npx can use the .mcpb bundle from the releases page. It carries its own dependencies, so there is no install step, and it prompts for the connection string rather than having it pasted into a config file. Build one yourself with npm run bundle.

Set up the role first

Do not point this at a superuser. Create a role that can only read, and let the database enforce what the server also enforces:

CREATE ROLE mcp_reader LOGIN PASSWORD 'a long random password';

GRANT CONNECT ON DATABASE yourdb TO mcp_reader;
GRANT USAGE ON SCHEMA public TO mcp_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_reader;

-- So tables created later are readable too, without another grant.
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_reader;

Grant nothing else. No INSERT, no USAGE on sequences, no EXECUTE on functions you have not read. If a column holds something the agent should never see, do not grant SELECT on the table and expose a view instead: the redaction described below matches column names, which is a convenience, not a boundary.

The tools

Tool

What it does

list_schemas

Schemas with a count of what each holds. Start here.

list_tables

Tables and views in one schema, largest first, with estimated rows and on-disk size

describe_table

Columns, types, nullability, defaults, keys, indexes, constraints and comments

find_columns

Search column names, and optionally types, across every schema

table_relationships

Follow foreign keys in both directions, N hops deep

sample_rows

The first N rows of a table, redacted and capped

run_select

One read-only query, with the guard, the timeout and the caps

explain_query

The plan for a query. ANALYZE is off by default and opt-in

export_data_dictionary

Write a Markdown data dictionary to a file

find_columns is the one that matters in a large database. Nobody browses a thousand tables, but everybody knows they are looking for something called customer_id.

export_data_dictionary is the one that changes how the server is used. Once the file exists, an agent working on that codebase can read the schema from disk with no connection and no credentials, which is the common case for someone writing a migration on a laptop that cannot reach production. It is also the only tool here that writes anything anywhere, and it only writes to the path you give it, which must end in .md.

Configuration

Variable

Default

What it does

DATABASE_URL

required

Connection string. Point it at the read-only role.

PGSM_MAX_ROWS

200

Row cap on every result

PGSM_MAX_BYTES

100000

Size cap on every result, which is the one that protects the agent's context

PGSM_STATEMENT_TIMEOUT_MS

10000

Per-statement timeout

PGSM_IDLE_TX_TIMEOUT_MS

15000

Idle-in-transaction timeout

PGSM_MAX_POOL

4

Connection pool size

PGSM_ALLOWED_SCHEMAS

all

Comma-separated allowlist. Everything else becomes invisible.

PGSM_REDACT_PATTERN

see below

Regular expression matched against column names

Both caps report when they bite. A truncated result says so in words, because an agent that silently receives half a result will reason confidently about the wrong answer.

Redaction

Columns whose name matches PGSM_REDACT_PATTERN come back as [redacted] from sample_rows and run_select alike. The default covers password, secret, token, ssn, credit_card, api_key, private_key and similar.

Be clear about what this is: it matches the name, not the value, so it will not notice a password stored in a column called notes. It is a guard against the ordinary mistake, not a classifier. The boundary is the GRANT.

HTTP mode, for a team

PGSM_TOKENS_FILE=./tokens.json PGSM_HTTP_PORT=3000 npx postgres-schema-mcp-http

Every request needs Authorization: Bearer <token>. There is no unauthenticated HTTP mode, and the server will not start without at least one token.

[
  {
    "name": "analytics",
    "token": "generate with: openssl rand -hex 32",
    "schemas": ["public", "reporting"],
    "tools": ["list_schemas", "list_tables", "describe_table", "find_columns", "run_select"]
  }
]

schemas and tools are both optional; omitting one means "everything the server exposes". A token can only ever be more restricted than the server it talks to, never less.

Scope is enforced by absence. A tool outside a token's scope is never registered on that session, so it does not appear in tools/list and calling it returns "unknown tool" rather than "forbidden". A refusal that says "forbidden" confirms the tool exists, and a token holder should not be able to map the rest of the server by reading the shape of its refusals. Every authentication failure returns the same 401 body for the same reason.

Tokens are compared by SHA-256 digest in constant time, and every configured token is checked even after one matches, so response time does not depend on a token's position in the list.

Put TLS and a reverse proxy in front of this. It binds to 127.0.0.1 unless you set PGSM_HTTP_HOST, and that default is deliberate.

Try it without a database of your own

docker compose -f examples/demo/docker-compose.yml up -d

DATABASE_URL='postgres://mcp_reader:demo_password_not_for_production@localhost:55432/bookshop' \
  npx postgres-schema-mcp

That starts PostgreSQL with a small bookshop schema: five tables, a view, a four-level foreign key chain, comments, and a password_hash column so redaction is visible in real output. It is written for this repository, so there is no licence question about redistributing it. The container keeps its data in tmpfs and forgets everything when it stops.

Pagila and Chinook both work fine too if you want something larger.

A question worth asking it, because no single tool answers it:

Which tables reference the customers table, and what is the average order total per customer?

The agent has to chain find_columns, table_relationships and run_select to get there.

Development

npm install
docker compose -f examples/demo/docker-compose.yml up -d
npm run build      # the protocol tests spawn dist/index.js, so build first
npm test
npm run bundle     # optional: builds the .mcpb into bundle/

182 tests. The integration suites skip themselves when no database is reachable, so npm test works on a laptop without Docker; CI asserts they did not skip, because a silent skip there would look exactly like a pass.

File

What it covers

test/injection.test.ts

Thirty hostile statements, each refused, grouped by technique

test/guard.test.ts

The queries that must be allowed, several containing the words the guard looks for

test/safety.test.ts

Redaction and the row and byte caps

test/tokens.test.ts

Token parsing, scope, and the write-mode switch that does not exist

test/cli.test.ts

--help and --version on both binaries, run with a deliberately empty environment

test/protocol.test.ts

A real MCP handshake over stdio against a real PostgreSQL, every tool

test/auth.test.ts

HTTP transport: valid, missing, wrong and out-of-scope tokens

guard.test.ts is there because a filter that refuses everything passes all thirty hostile cases and is useless. It asserts that SELECT 'drop table users', a column named updated_at, and a LIKE pattern containing ; DROP TABLE all still work.

Licence

MIT. See LICENSE.

Available Tools

9 tools
describe_tableDescribe tableA
Read-onlyIdempotent

Full description of one table: every column with its type, nullability and default, plus primary keys, foreign keys, unique and check constraints, indexes and any comments. This is the core tool once you know which table you want.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableYesTable or view name, unqualified.
schemaYesSchema name.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare the tool read-only, idempotent, and non-destructive, so safety is covered. The description adds substantial value by detailing the return payload (columns, constraints, indexes, comments), which is especially important since no output schema exists.

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 with no filler. The first sentence front-loads the tool's core purpose and return details, and the second explains when to use it. Every clause 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?

With 2 simple parameters, annotations covering safety, and a detailed description of the return contents, nothing essential is missing. The lack of an output schema is compensated by the explicit list of returned metadata.

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 100%, and the schema already documents both parameters ('Table or view name, unqualified' and 'Schema name.'). The description does not add parameter-level meaning, but it doesn't need to; the baseline of 3 applies.

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 uses a specific verb and resource ('Full description of one table') and enumerates the exact metadata returned (columns, types, nullability, defaults, keys, constraints, indexes, comments). It is clearly distinct from list_schemas/list_tables, but does not explicitly separate itself from table_relationships, even though foreign keys are included.

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 'This is the core tool once you know which table you want' gives clear contextual guidance: use it after table discovery, not for browsing schemas or tables. It does not name alternatives or state when-not-to-use, so it falls just short of explicit routing.

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

explain_queryExplain queryA
Read-onlyIdempotent

Show the query plan for a SELECT without running it. Pass analyze: true to execute it and get measured timings instead of estimates. Use this to tune a query before running it against a large table.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYesA single SELECT or WITH statement.
analyzeNoRun the query to collect real timings. Off by default.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations declare readOnly and idempotent, and the description adds the key behavioral nuance that analyze: true executes the statement and returns measured timings instead of estimates. This is useful context beyond the structured annotations.

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 short sentences with no filler: primary behavior, parameter behavior, and usage guidance are each given one sentence in logical order.

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 two-parameter tool with rich annotations, the description says everything needed to select and use it: default plan-only behavior, analyze=true behavior, and the intended use case. No output schema is required; 'query plan' sufficiently describes the result.

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 100%, so the schema already documents both parameters. The description adds value by explaining that analyze toggles between estimates and measured timings and reinforces that sql must be a SELECT or WITH statement.

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?

States a specific verb and resource: show the query plan for a SELECT, and clarifies that the default does not run it. The 'tune before running' phrasing differentiates it from running actual queries via siblings like run_select.

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?

Gives actionable usage context: use it to tune a query before running it against a large table. It does not explicitly name run_select as the alternative or state when not to use it, so it falls just short of a 5.

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

export_data_dictionaryExport data dictionaryA
Idempotent

Write a Markdown data dictionary for one schema to a file: every table, every column with type and nullability, and every key and constraint. Once written, you can read the schema from disk with no database connection. This is the only tool here that writes anything, and it writes only to the path you give it.

ParametersJSON Schema
NameRequiredDescriptionDefault
schemaYesSchema name to document.
output_pathYesWhere to write the file. Must end in .md.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already indicate this is a mutating but idempotent and non-destructive action; the description adds meaningful behavioral context by stating it writes only to the given path and produces a Markdown file. It does not explicitly address overwrite behavior or error conditions, but the annotations plus the explicit path boundary largely cover the typical concerns for a file-writing tool.

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 concise sentences, each earning its place: the first defines the action and output content, the second explains a practical benefit, and the third provides safety and sibling differentiation. It is front-loaded and free of filler.

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 low parameter count, full schema coverage, and annotations covering the safety profile, this description is complete for correct invocation. An agent knows exactly what will be written, where it will be written, and that no other tool in this set performs writes. No output schema is needed for a write action, and no required information 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?

Both parameters are fully described in the input schema (schema name and output_path with the .md requirement). The description reinforces these with 'one schema' and 'the path you give it,' but adds little semantic value beyond what the schema already provides, so the baseline of 3 is appropriate.

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 opens with a specific verb and resource: 'Write a Markdown data dictionary for one schema to a file,' and enumerates exactly what the document includes (every table, column, type, nullability, key, constraint). It also distinguishes itself from siblings by stating 'This is the only tool here that writes anything,' so an agent can tell it apart from the read-only introspection tools at a glance.

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 useful context: it explains the benefit of using this tool ('Once written, you can read the schema from disk with no database connection') and explicitly notes it is the only sibling that writes, which frames when to pick this over the other read-only tools. It does not explicitly name alternative tools to use instead for specific cases, so it falls short of a 5.

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

find_columnsFind columnsA
Read-onlyIdempotent

Search for columns by name across every schema, optionally filtered by type. Use this instead of listing tables when the database is large: searching for "customer_id" finds every table that carries it in one call.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesSubstring of the column name. Matched case-insensitively.
typeNoOptional substring of the type, for example "uuid" or "timestamp".

TDQS

A4/5.0
Behavior3/5

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

Annotations already establish read-only, idempotent, and non-destructive behavior. The description adds cross-schema scope and the 'every table that carries it in one call' behavior, but it does not mention limits, ordering, or result shape; this is useful but not rich 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?

Two tightly written sentences front-load the core capability, then add a targeted usage rationale with a concrete example. Every clause earns its place; there is no filler.

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 two-parameter search tool with safety annotations, the description is largely complete: it states scope, optional filter, and the intended efficiency benefit. There is no output schema and the exact return format is implied rather than stated, but an agent can infer it will see the matching columns and tables.

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 100%, with clear definitions for name and the optional type substring. The description's 'optionally filtered by type' and customer_id example mirror the schema rather than adding new semantic meaning, so the baseline 3 applies.

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 opens with a specific verb and resource: 'Search for columns by name across every schema, optionally filtered by type.' It clearly distinguishes the tool from sibling listing tools by emphasizing cross-schema column search rather than table or schema enumeration.

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?

It gives explicit guidance to use this instead of listing tables when the database is large, with a concrete customer_id example. It does not spell out exclusions relative to describe_table or table_relationships, so it stops short of a full when/when-not matrix.

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

list_schemasList schemasA
Read-onlyIdempotent

List the schemas in the database with how many tables and views each holds. Start here when you do not know the shape of the database yet.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already communicate read-only, idempotent, non-destructive behavior. The description adds genuine output context—that results include per-schema table and view counts—which is useful.

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 with the core operation front-loaded and the usage cue in the second sentence. No filler.

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 discovery/list tool, the description tells an agent what it will get (schemas with table and view counts) and when to call it. No output schema is present, but the description supplies the essential return shape.

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?

No parameters exist, so the schema covers everything; per the rubric the baseline is a 4. The description doesn't need to add parameter-level detail.

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?

Verb 'List' plus direct object 'schemas in the database' makes the operation unambiguous. The added detail about table/view counts and the 'Start here' guidance distinguishes it from sibling table-level tools.

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 positioned as the starting point when database shape is unknown, giving a clear precondition. It does not name alternatives or state when not to use it, so not a full 5.

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

list_tablesList tablesA
Read-onlyIdempotent

List the tables and views in one schema, largest first, with an estimated row count and total on-disk size. Use this to find out what is expensive before you query it. Row counts are planner estimates, not exact counts.

ParametersJSON Schema
NameRequiredDescriptionDefault
schemaYesSchema name, for example "public".

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare read-only/idempotent/non-destructive behavior, so the description adds beyond them by disclosing that row counts are planner estimates rather than exact numbers and that views are included. This is useful non-obvious 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?

Two compact sentences: the first states the core behavior and output, the second adds a use case and a critical caveat. No filler or redundant restating of the tool name.

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 one-parameter listing tool with no output schema, the description conveys what is returned (tables and views, estimated row counts, on-disk size), the ordering, and the estimation caveat. Nothing essential is missing 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?

The input schema already fully describes the single 'schema' parameter with an example, and schema description coverage is 100%. The description adds no parameter-level detail beyond confirming the scope is one schema, so the baseline of 3 is appropriate.

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') with a concrete resource ('tables and views in one schema') and adds distinctive return details (ordering by size, estimated row count, on-disk size). This clearly separates it from siblings like list_schemas and describe_table.

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?

It gives an explicit use case: 'Use this to find out what is expensive before you query it.' It does not explicitly state when not to use it or name alternatives, but the intended context is clear enough for an agent to select this tool.

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

run_selectRun a read-only queryA
Read-onlyIdempotent

Run one SELECT or WITH statement. Anything else is refused, including stacked statements, DDL, DML and SELECT INTO. The query runs in a read-only transaction with a statement timeout, results are capped and secret-looking columns masked. There is no write mode.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYesA single SELECT or WITH statement. No trailing second statement.

TDQS

A4.1/5.0
Behavior5/5

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

Annotations already mark it read-only/idempotent/non-destructive, and the description adds meaningful runtime behavior: read-only transaction, statement timeout, result cap, and masking of secret-looking columns. It also names specific refused statement classes beyond the annotation's safety profile.

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 pack accepted input, refusal classes, execution constraints, and output limits without fluff. A minor redundancy exists across 'no write mode,' readOnlyHint, and the refusal list, but overall the description remains tight and readable.

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 one-parameter query tool, the description covers allowed statements, refusals, execution context, timeout, cap, and masking, so an agent can invoke it correctly. It does not describe return shape, but with no output schema and query-dependent results this is a minor gap.

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?

The single sql parameter has 100% schema coverage, so the schema already documents 'a single SELECT or WITH statement. No trailing second statement.' The description reinforces the same constraint but does not materially add parameter-level meaning beyond the 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 opens with a specific verb+resource—'Run one SELECT or WITH statement'—and the title reinforces read-only. It clearly distinguishes run_select from the schema-discovery siblings by being the only arbitrary query tool.

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 clearly states what will be refused and that there is no write mode, so the agent knows when not to attempt DDL/DML. However, it never explicitly contrasts with sibling tools like list_tables or explain_query, leaving 'when to use this instead' to inference.

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

sample_rowsSample rowsA
Read-onlyIdempotent

Return the first few rows of a table so you can see the shape of the data. Columns whose names look like secrets are masked. Results are capped by row count and by size, and the response says when it truncated.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoHow many rows to return. Defaults to 10, and the server cap still applies.
tableYesTable name, unqualified.
schemaYesSchema name.

TDQS

A4.2/5.0
Behavior5/5

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

The annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description need not restate safety. It adds substantive behavioral detail: secret-looking columns are masked, results are capped by both row count and size, and truncation is reported. This meaningfully exceeds the structured annotations.

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 with no fluff. The core action is front-loaded, and each subsequent sentence adds distinct value: masking behavior, cap behavior, and truncation notification. Nothing extraneous is present.

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 simple 3-parameter tool with strong annotations, the description covers the important runtime behaviors: masking, cap limits, and truncation response. It could be slightly more explicit about the exact shape of the returned result (e.g., whether column names/types are included), but overall it is complete enough 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 description coverage is 100%, and the schema already documents limit (including default, min, and max), table, and schema. The description adds no parameter-level meaning beyond what the schema provides, so the baseline of 3 is appropriate.

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 and resource: 'Return the first few rows of a table'. This clearly distinguishes sampling data from sibling tools like describe_table (structure) and run_select (arbitrary queries), and the added 'shape of the data' purpose makes intent 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 'so you can see the shape of the data' clause gives a clear implied context, but the description never explicitly states when to use this tool versus alternatives like run_select or describe_table. There is no when-not guidance or named sibling fallback, so the agent has to infer selection criteria.

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

table_relationshipsTable relationshipsA
Read-onlyIdempotent

Follow foreign keys from one table, in both directions, up to a given depth. Outbound keys tell you what a row points at; inbound keys tell you what points at it. Use this to work out how to join instead of guessing from column names.

ParametersJSON Schema
NameRequiredDescriptionDefault
depthNoHow many foreign key hops to follow. Defaults to 2.
tableYesTable name, unqualified.
schemaYesSchema name.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already establish that this is read-only and idempotent. The description adds meaningful behavioral detail beyond that: it traverses foreign keys in both directions up to a depth, and defines what outbound versus inbound keys mean. This gives the agent a real sense of how results will be structured without needing the output 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?

Three short, purposeful sentences: the first states the core behavior, the second clarifies directional semantics, and the third gives practical guidance. There is no redundant text or repetition of the title.

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 read-only metadata traversal tool with three parameters and fully documented schema fields, the description is complete enough for an agent to decide when and how to call it. The only gap is that there is no output schema or example return shape, so an agent may be unsure exactly what the result payload looks like, though the description's directional explanation mitigates this.

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 100%, so the input schema already documents schema, table, and depth well. The description reinforces the depth concept and directional behavior but does not add significant new parameter meaning beyond what the schema provides. Baseline 3 is appropriate.

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, 'follow', and a precise resource, foreign keys, with direction and depth scoping. It clearly distinguishes this relationship-traversal tool from siblings like describe_table or find_columns by focusing on join discovery rather than table structure or column lookup.

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 explicitly says 'Use this to work out how to join instead of guessing from column names,' providing clear context for when the tool is appropriate. It gives a when-not condition but does not explicitly name alternative sibling tools, so it stops just short of a full alternative-routing explanation.

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. 9 tool updatesv0.1.1
    • First observeddescribe_table
    • First observedexplain_query
    • First observedexport_data_dictionary
    • First observedfind_columns
    • First observedlist_schemas
    • First observedlist_tables
    • First observedrun_select
    • First observedsample_rows
    • First observedtable_relationships

TDQS

A4.3/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: schema discovery, table listing, detailed table description, column search, relationship traversal, data preview, query execution, query planning, and documentation export. There is no practical overlap; even sample_rows and run_select differ in that one is a convenience for previewing a table and the other is for arbitrary read-only queries.

Naming Consistency4/5

Eight of nine tools follow a clear verb_noun snake_case pattern (list_schemas, describe_table, run_select, etc.), making the set predictable. The single exception is table_relationships, which uses a noun_noun form, creating a minor inconsistency without causing confusion.

Tool Count5/5

Nine tools is well-scoped for a PostgreSQL schema and querying server. Each tool fills a distinct role in the workflow from schema discovery to query tuning, and none feel redundant or bolted on.

Completeness5/5

The tool surface covers the full read-only lifecycle: schema/table discovery, column search, relationship mapping, data sampling, safe SELECT execution, query planning, and exporting a data dictionary. There are no obvious dead ends for an agent exploring or querying a database, and the explicit lack of write mode is a deliberate boundary rather than a gap.

Maintenance

ActivityMaintained
ResponsivenessSyncing

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

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides read-only access to PostgreSQL databases, enabling LLMs to inspect database schemas and execute read-only SQL queries.
    100,745
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to safely interact with PostgreSQL databases through read-only operations, providing schema discovery, table inspection, and query execution capabilities with structured context awareness.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables secure read-only access to PostgreSQL databases, allowing users to list tables, query schemas, execute SELECT statements, and inspect table structures through natural language interactions.
    751
    4
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI agents to inspect and query PostgreSQL databases safely, with features like listing tables, retrieving schemas, and running read-only SQL queries.
    3
    -

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/eric-patton/postgres-schema-mcp'

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