Skip to main content
Glama
postgres-mcp-server

postgres-mcp-server

Postgres MCP Server

A Model Context Protocol (MCP) server for PostgreSQL databases. Connects AI assistants (Claude Desktop, Cursor, Antigravity, etc.) to a PostgreSQL database with schema discovery, catalog introspection, read-only analytical queries, and opt-in safe write operations.

Features

  • Schema Discovery: Inspect schemas, tables, views, column data types, primary keys, and uniqueness constraints (list_tables, describe_table).

  • Catalog & Governance Discovery: Discover visible databases, roles with attributes and memberships, and permissions across schemas, tables, and columns (list_databases, list_roles, list_permissions).

  • Bounded Read Queries: Run parameterized SQL queries with pagination (limit, offset), strict maximum row limits, and automatic truncation detection (run_query).

  • Gated Safe Writes: Write operations (run_write_query for INSERT, UPDATE, DELETE, DDL) are disabled by default and require explicit ALLOW_WRITE=1 configuration.

  • Security & Privacy First: Zero credential leakage. Connection strings, passwords, and internal stack traces are redacted from logs and tool responses. Parameterized SQL prevents SQL injection.

  • Stdio Transport: Seamlessly runs over stdio conforming to standard MCP protocol clients.


Related MCP server: PostgreSQL MCP Server

Quick Start

Running via NPX

Pass the connection string directly as a command-line argument or via environment variable:

# Read-only mode (default)
npx @allensandiego/postgres-mcp-server postgres://user:password@localhost:5432/mydb

# Enable write mode via CLI flag
npx @allensandiego/postgres-mcp-server postgres://user:password@localhost:5432/mydb --allow-write

# Or configure via environment variables
export DATABASE_URL="postgres://user:password@localhost:5432/mydb"
export ALLOW_WRITE=1   # Optional: enable write queries
npx @allensandiego/postgres-mcp-server

Global Installation

npm install -g @allensandiego/postgres-mcp-server

# Run read-only
postgres-mcp-server postgres://user:password@localhost:5432/mydb

# Run with write operations enabled
postgres-mcp-server postgres://user:password@localhost:5432/mydb --allow-write

Local Development

# Clone and install dependencies
git clone https://github.com/allensandiego/postgres-mcp-server.git
cd postgres-mcp-server
npm install

# Build
npm run build

# Run with tsx in development
npm run dev -- postgres://user:password@localhost:5432/mydb --allow-write

Configuration

The server can be configured via CLI flags or environment variables:

Connection String

You can provide the connection string in any of the following ways (in order of precedence):

  1. CLI Positional Argument: postgres-mcp-server postgres://user:password@host:port/db

  2. CLI Option: postgres-mcp-server --url=postgres://... or --connection-string=...

  3. Environment Variables: DATABASE_URL, POSTGRES_URL, POSTGRES_CONNECTION_STRING, PG_CONNECTION_STRING, DATABASE_URI, POSTGRES_URI, PGURL, or PG_URL

Enabling Write Operations (ALLOW_WRITE)

By default, the server runs in read-only mode (run_write_query will reject any destructive or mutating SQL). To enable write queries (INSERT, UPDATE, DELETE, CREATE, DROP, ALTER):

  • Via CLI flag: Pass --allow-write, --write, or -w

  • Via Environment Variable: Set ALLOW_WRITE=1 (or ALLOW_WRITE=true)

Environment Variables Reference

Variable

Description

Default

DATABASE_URL / POSTGRES_URL / POSTGRES_CONNECTION_STRING

Full PostgreSQL connection URI (postgres://user:pass@host:port/db)

None

ALLOW_WRITE

Enables write queries (1, true, yes, on)

false (Read-only)

PGHOST / POSTGRES_HOST

Database host name

localhost

PGPORT

Database port number

5432

PGDATABASE / POSTGRES_DB

Database name

postgres

PGUSER / POSTGRES_USER

Database user name

postgres

PGPASSWORD / POSTGRES_PASSWORD

Database password

None

PGSSLMODE / PGSSL

SSL configuration mode (require, verify-full, etc.)

Disabled

MAX_ROW_LIMIT / ROW_LIMIT

Maximum rows returned per query

1000

QUERY_TIMEOUT_MS

Per-query timeout in milliseconds

30000 (30s)

MAX_CONNECTIONS / POOL_MAX

Maximum active database connections in pool

10


MCP Tools Reference

1. list_tables

Discover all user schemas and their tables/views and columns without writing SQL.

  • Arguments:

    • schema (optional string): Filter tables by schema name (e.g. "public").

  • Output: Array of { schema, name, type, columns: [{ name, dataType, nullable, isPrimaryKey, isUnique }] }.

2. describe_table

Retrieve detailed column specifications and primary key definitions for a table.

  • Arguments:

    • schema (required string): Schema name (e.g. "public").

    • table (required string): Table name (e.g. "users").

  • Output: { schema, table, columns: [...], primaryKey?: string }.

3. list_databases

Discover databases visible and connectable to the connected user.

  • Arguments: None.

  • Output: Array of { name, owner, encoding, isTemplate, connectable }.

4. list_roles

Discover roles/users, their administrative attributes, and group memberships.

  • Arguments: None.

  • Output: Array of { name, superuser, canLogin, canCreateDb, canCreateRole, canBypassRls, memberOf, members }.

5. list_permissions

Discover granted privileges across schemas, tables, and columns.

  • Arguments:

    • objectType (optional string): "schema", "table", or "column".

    • schema (optional string): Schema name filter.

    • table (optional string): Table name filter.

  • Output: Array of { grantor, grantee, objectType, objectName, privilege, grantable }.

6. run_query

Execute a read-only parameterized SELECT query.

  • Arguments:

    • sql (required string): Parameterized SQL statement (e.g. "SELECT * FROM orders WHERE status = $1").

    • params (optional array): Parameter substitution values.

    • limit (optional integer): Page limit (capped at MAX_ROW_LIMIT).

    • offset (optional integer): Page offset for pagination.

    • role (optional string): Role/user to assume (SET ROLE) for this specific query only.

  • Output: { columns, rows, rowCount, truncated }.

7. run_write_query

Execute modifying SQL statements (INSERT, UPDATE, DELETE, DDL). Only active when ALLOW_WRITE=1 or --allow-write is provided.

  • Arguments:

    • sql (required string): SQL write statement.

    • params (optional array): Parameter values.

    • role (optional string): Role/user to assume (SET ROLE) for this specific write query only.

  • Output: { rowCount }.

8. set_role

Set the active PostgreSQL role/user for the session (SET ROLE) or restore the default session user (RESET ROLE).

  • Arguments:

    • role (required string): Role/username to set (e.g. "analyst", "app_readonly", or "NONE" / "RESET" to return to the original session user).

  • Output: { activeRole, sessionUser, isReset, message }.


MCP Client Setup Examples

Gemini CLI Configuration (mcp_config.json or settings.json)

Read-only mode (Default):

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@allensandiego/postgres-mcp-server@latest",
        "postgres://username:password@localhost:5432/mydb"
      ]
    }
  }
}

Write-enabled mode:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@allensandiego/postgres-mcp-server@latest",
        "postgres://username:password@localhost:5432/mydb",
        "--allow-write"
      ]
    }
  }
}

Or via environment variables:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "@allensandiego/postgres-mcp-server@latest"],
      "env": {
        "DATABASE_URL": "postgres://username:password@localhost:5432/mydb",
        "ALLOW_WRITE": "1"
      }
    }
  }
}

Claude Desktop Configuration (claude_desktop_config.json)

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@allensandiego/postgres-mcp-server@latest",
        "postgres://username:password@localhost:5432/mydb"
      ],
      "env": {
        "ALLOW_WRITE": "0"
      }
    }
  }
}

Antigravity / Cursor Configuration

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@allensandiego/postgres-mcp-server@latest",
        "postgres://username:password@localhost:5432/mydb"
      ],
      "env": {
        "ALLOW_WRITE": "1"
      }
    }
  }
}

Testing & Quality Gates

Run the automated test suite (unit + contract + integration tests):

npm test

Type checking:

npm run typecheck

Linting:

npm run lint

License

This project is licensed under the PolyForm Noncommercial License 1.0.0 - free for personal, educational, research, and non-commercial open-source use. Commercial use requires a commercial license.

Available Tools

8 tools
describe_tableA
Read-only

Detail the columns, types, and primary keys of a specific table (FR-002)

NameRequiredDescriptionDefault
tableYesTable name
schemaYesSchema name (e.g. 'public')

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, so the safe-read profile is covered. The description adds value by naming the return content (columns, types, primary keys), but does not discuss permissions, error behavior, or limits.

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?

A single front-loaded sentence with no filler. The trailing '(FR-002)' reference is not useful to an agent and slightly detracts from otherwise tight phrasing.

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 is simple, parameters are fully documented, and annotations cover safety. Since there is no output schema, the description usefully states what is returned (columns, types, primary keys); the main remaining gap is lack of explicit usage guidance versus sibling tools.

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 100%, so the schema already documents both parameters. The description adds no syntax or constraints beyond what the schema provides, so baseline 3 is appropriate.

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?

States a specific verb ("Detail") and resource ("a specific table"), listing the returned elements: columns, types, and primary keys. This distinguishes it contextually from list_tables, but it does not explicitly name the sibling tool it differs from.

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

Usage Guidelines3/5

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

The description implies usage for inspecting a single table's structure, but gives no explicit when-to-use guidance, prerequisites, or comparison to alternatives like list_tables or run_query.

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

list_databasesA
Read-only

Discover databases visible/connectable to the connected user (FR-002a)

NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already establish readOnlyHint=true, so the safety profile is covered by structured data. The description does add one genuinely behavioral fact beyond that: results are limited to what the connected user can see or connect to, so the agent knows an empty list may reflect privileges rather than absence.

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?

A single short clause, front-loaded with the verb and resource. The '(FR-002a)' requirement traceability tag is internal noise that costs an agent a moment of parsing but is minor.

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

Completeness3/5

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

There is no output schema and no parameters, so the description is the only place an agent could learn the shape of the result — whether it gets database names, identifiers, or connection details to feed into later calls like list_tables or run_query. That gap leaves the tool slightly under-specified for a discovery entry point.

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 takes zero parameters, which is the baseline-4 case. Nothing in the description contradicts or complicates that, and there are no parameter semantics to explain.

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?

Clear verb+resource pair ('Discover databases') with a scope qualifier ('visible/connectable to the connected user') that tells the agent results are permission-scoped. It doesn't explicitly contrast with sibling list_tables, but the resource noun is distinct enough that an agent won't confuse the two.

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?

No explicit when-to-use or when-not-to-use guidance, and no mention of the sibling discovery tools (list_tables, describe_table) that would naturally follow this call. Usage is only implied by the zero-parameter, permission-scoped nature of the tool.

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

list_permissionsB
Read-only

Discover privileges granted to roles on schemas, tables, and columns (FR-002c)

NameRequiredDescriptionDefault
tableNoOptional table filter
schemaNoOptional schema filter (e.g. 'public')
objectTypeNoOptional object type filter: 'schema', 'table', or 'column'

TDQS

B3.1/5.0
Behavior2/5

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

readOnlyHint=true already covers the safety profile, so the description's only added value is the object scope (schemas/tables/columns). It says nothing about what is returned per grant, whether results are filtered by the caller's own privileges, or what an unfiltered call yields. '(FR-002c)' is an internal requirement tag with no meaning to an agent.

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

Conciseness5/5

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

A single front-loaded sentence with no redundant wording; the only wasted token is the trailing '(FR-002c)' reference.

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

Completeness3/5

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

For a read-only, filterable list tool with no output schema, the description covers purpose but not the return shape (role, object, privilege type) or the meaning of an unfiltered call. Adequate to select the tool, incomplete for predicting its output.

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 all three filters are documented there, including the objectType enum, so the baseline of 3 applies. The description names the three object scopes but adds no filter semantics beyond what the schema states.

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?

States a specific verb ('Discover') and resource ('privileges granted to roles on schemas, tables, and columns'), which is enough to distinguish it from list_roles and describe_table. It stops short of explicitly naming the sibling it complements, so it is clear but not maximally differentiating.

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

Usage Guidelines2/5

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

No guidance on when to call this versus list_roles or describe_table, and no prerequisites (e.g., that only grants visible to the current role may be returned). The only usage signal is implicit in the word 'Discover' and the optional filters in the schema.

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

list_rolesB
Read-only

Discover roles/users and their attributes and memberships (FR-002b)

NameRequiredDescriptionDefault

No parameters

TDQS

B3.3/5.0
Behavior3/5

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

The readOnlyHint annotation already establishes that this is a safe read operation. The description adds useful scope by saying it returns roles/users with attributes and memberships, but it does not disclose pagination, ordering, or whether users are always included.

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

Conciseness4/5

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

The description is a single front-loaded sentence with little waste. The trailing '(FR-002b)' internal reference is the only unnecessary element.

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

Completeness3/5

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

For a zero-parameter list tool with no output schema, the description adequately identifies what is returned. However, it does not clarify result shape, ordering, or how users and roles relate, which would help an agent invoke and interpret it confidently.

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 takes zero parameters, so there is no parameter semantics to explain; baseline 4 is appropriate. Schema coverage is also 100%, though empty.

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 states a clear resource (roles/users) and what information is returned (attributes and memberships), which lets an agent distinguish it from mutations like set_role. The verb 'Discover' is less precise than 'List', and the internal requirement reference '(FR-002b)' adds no meaning.

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

Usage Guidelines2/5

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

There is no explicit guidance on when to use this tool versus siblings such as list_permissions or set_role. The intent to browse roles/users is only implied by 'Discover'.

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

list_tablesA
Read-only

Discover schemas and their tables/columns without writing a query (FR-002)

NameRequiredDescriptionDefault
schemaNoOptional schema name to filter tables (defaults to all non-system schemas)

TDQS

A3.5/5.0
Behavior3/5

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

readOnlyHint=true already tells the agent this is a safe read, so the bar is lower; the description adds that no query needs to be composed, which is useful framing. It says nothing about result size, pagination, or how system schemas are treated (that detail lives only in the schema), so additional behavioral disclosure is thin.

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?

One front-loaded sentence with the key constraint ('without writing a query') placed early and no redundant restatement of the name. The trailing requirement tag '(FR-002)' is traceability noise for an agent and is the only inefficiency.

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-required-parameter, single-optional-parameter list tool with a readOnly annotation and full schema coverage, the description covers the essential purpose. The main remaining gap is the shape of the returned hierarchy (schemas -> tables -> columns), which must be inferred from the prose.

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 single parameter's default behavior ('defaults to all non-system schemas') is fully documented in the schema itself. The description adds no further meaning about the schema filter, so 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?

States a specific verb ('discover') and resource ('schemas and their tables/columns'), which clearly signals a metadata-listing tool distinct from run_query. It does not, however, distinguish itself from close siblings like list_databases or describe_table, so an agent must infer the boundary.

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?

'Without writing a query' implies the usage context versus run_query, giving an implicit alternative. There is no explicit guidance on when to pick this over describe_table (single-table detail) or list_databases (top-level enumeration), and no stated preconditions such as required role/permissions that siblings like set_role suggest matter here.

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

run_queryB
Read-only

Execute a read-only SELECT query and return structured rows (FR-003)

NameRequiredDescriptionDefault
sqlYesRead-only SQL query to execute (e.g. SELECT)
roleNoOptional PostgreSQL role to assume (SET ROLE) for this query only
limitNoMaximum number of rows to return (capped by server maxRowLimit)
offsetNoNumber of rows to skip before returning results
paramsNoOptional parameterized query values ($1, $2, etc.)

TDQS

B3.3/5.0
Behavior3/5

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

The annotations already declare readOnlyHint=true, and the description is consistent with that by calling the query read-only. It adds the return shape ('structured rows') but says nothing about server-side row caps, role/permission failures, or error behavior, which matter for a query executor.

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

Conciseness3/5

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

It is a single front-loaded sentence with no padding, but it is arguably too terse for a five-parameter SQL executor. The '(FR-003)' requirement tag is internal noise that does not help an agent select or invoke the tool.

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

Completeness3/5

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

With no output schema and five parameters, the description confirms the return is structured rows, which is helpful. It still leaves gaps on row-limit behavior and role/permission semantics that are only partially covered elsewhere, making it minimally adequate rather than complete.

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 all five parameters (sql, role, limit, offset, params) are already documented in the schema. The description adds no parameter-level meaning beyond what the schema provides, so the baseline 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 states a specific verb ('Execute') and resource ('read-only SELECT query') with a clear outcome ('return structured rows'). The 'read-only SELECT' phrasing implicitly separates it from the sibling run_write_query, though it does not name that sibling outright.

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 read-only qualifier signals this is for reads, which is implied guidance against write usage. However, it never explicitly says when to use this versus run_write_query, nor does it mention prerequisites such as assuming a role or how pagination interacts with limit/offset.

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

run_write_queryB
Destructive

Execute INSERT/UPDATE/DELETE/DDL statements when write mode is enabled (FR-006)

NameRequiredDescriptionDefault
sqlYesSQL write/DDL statement to execute (e.g. INSERT, UPDATE, DELETE, CREATE TABLE)
roleNoOptional PostgreSQL role to assume (SET ROLE) for this write query only
paramsNoOptional parameterized query values ($1, $2, etc.)

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, so the dangerous nature is known; the description adds the meaningful gate that write mode must be enabled. It does not disclose transaction behavior, reversibility, whether DDL is irreversible, or how failures surface — relevant for a destructive tool with only one annotation.

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?

A single front-loaded sentence that earns its place, with the write-mode condition placed where it is immediately visible. The internal '(FR-006)' spec reference is dead weight for an agent.

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

Completeness3/5

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

For a destructive write tool with no output schema, the description covers the enablement gate but omits what is returned (row counts? result rows for DDL?), whether execution is transactional, and how role-scoped writes behave. Adequate but with evident gaps an agent would want closed.

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 sql, role, and params are already documented in the schema, including that role applies to this write query only. The description adds no parameter-level meaning beyond that; baseline 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?

States a specific verb (Execute) and a precise resource class (INSERT/UPDATE/DELETE/DDL statements), which cleanly separates it from the read-oriented run_query sibling. The '(FR-006)' tag adds nothing but the core statement is unambiguous.

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?

It gives one real precondition — write mode must be enabled — which is useful gating context. However it never explicitly says 'for SELECT use run_query' nor explains what happens if write mode is off (error? silent rejection?), leaving the agent to infer the alternative.

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

set_roleA

Set active PostgreSQL role/user for the session (SET ROLE) or reset to default (RESET ROLE)

NameRequiredDescriptionDefault
roleYesRole or username to set (e.g. 'analyst', 'app_user', or 'NONE' / 'RESET' to restore default)

TDQS

A4/5.0
Behavior3/5

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

The readOnlyHint=false annotation already signals a state-changing operation, and the description usefully adds that the change is session-scoped and reversible via RESET ROLE. It omits the operationally important consequences: that the new role governs subsequent run_query/run_write_query calls in the same session, and that membership in the role is required. Those gaps keep it at a 3 for a state-mutating 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?

One sentence, front-loaded with the primary action and immediately covering the inverse operation. Nothing is wasted and nothing material is buried.

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?

With a single fully documented parameter, no nested objects, and no output schema expected for a session-setting command, the definition is nearly self-sufficient. The main omission is the downstream effect on later query calls and the membership prerequisite, which would help an agent sequence its calls correctly.

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 100% and the schema's own property description already documents 'NONE'/'RESET' for restoring the default, so the description's mention of RESET ROLE largely restates structured information. It adds no format, case-sensitivity, or validation guidance beyond the schema, making the baseline 3 correct.

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 pairs a specific verb and resource ('Set active PostgreSQL role/user') with an explicit scope ('for the session') and names the underlying SQL semantics (SET ROLE / RESET ROLE). That is enough to distinguish it from the sibling list_roles, which enumerates roles rather than activating one.

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 makes the two usage modes explicit — setting a role versus restoring the default — so an agent knows both branches without consulting the schema. It stops short of stating prerequisites (e.g., the caller must already be a member of the target role) or when this tool should be preferred over simply qualifying objects in run_query.

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. 8 tool updatesv0.1.4
    • First observeddescribe_table
    • First observedlist_databases
    • First observedlist_permissions
    • First observedlist_roles
    • First observedlist_tables
    • First observedrun_query
    • First observedrun_write_query
    • First observedset_role

TDQS

A3.7/5.0

Scored across 8 tools

Disambiguation4/5

Most tools have clearly distinct resource+action targets, especially read vs. write query execution and role setting. The only mild overlap is between list_tables (which includes column info) and describe_table (which details columns/keys), but descriptions clarify the distinction.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: list_databases, list_tables, describe_table, list_roles, list_permissions, run_query, run_write_query, set_role. No mixed conventions or vague standalone verbs.

Tool Count5/5

Eight tools is well-scoped for a PostgreSQL MCP server focused on discovery and query execution. Each tool earns its place without excessive granularity or missing obvious helpers.

Completeness4/5

The surface covers core database discovery, role/permission inspection, read queries, write/DDL statements, and role switching. Minor gaps exist for deeper schema introspection (indexes, views, constraints beyond primary keys) and transaction control, but agents can work around them via catalog queries.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that enables AI assistants to interact with PostgreSQL databases by executing SQL queries and inspecting database schemas. It provides tools for standardized database exploration and management through the Model Context Protocol.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    An open-source MCP server for PostgreSQL schema introspection and guarded read-only queries. It enables MCP clients to discover schemas, tables, columns, indexes, relationships, and safe queryable data from a configured PostgreSQL database.
    11 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for PostgreSQL that enables Cursor and other MCP clients to execute SQL queries, list tables, and explore database schemas via HTTP.
    1,139 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A read-only MCP server for PostgreSQL that enables safe database introspection and querying via natural language.
    706 npm
    MIT