Skip to main content
Glama
YawLabs

@yawlabs/postgres-mcp

by YawLabs

Run SQL query

pg_query
Destructive

Run SQL queries against your PostgreSQL database with parameterized inputs to prevent injection, returning results capped to avoid oversized payloads.

Instructions

Run a SQL query against the configured PostgreSQL database. Postgres itself is the primary safety gate: the role in DATABASE_URL enforces what queries can succeed. The recommended posture is a least-privileged role (e.g. one granted pg_read_all_data), which makes writes server-rejected regardless of any env var. ALLOW_WRITES=1 is a secondary belt-and-braces gate - it lifts the in-server BEGIN READ ONLY wrapper, but it cannot grant privileges the role lacks. Useful for managed databases where creating a second role is awkward. For read-only access where you want the guarantee in the tool name, prefer pg_readonly. Use params for parameterized queries to avoid SQL injection. Params can be strings, numbers, booleans, null, arrays (for postgres arrays / ANY), or objects (for json/jsonb columns). Dates and UUIDs can be passed as ISO strings. Large result sets are truncated to POSTGRES_MAX_ROWS (default 1000) with a truncated: true flag.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sqlYesThe SQL statement to execute. Hard cap of 1 MB.
paramsNoPositional parameters referenced as $1, $2, ... in the SQL.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
rowsYesResult rows, capped at POSTGRES_MAX_ROWS. Values are whatever JSON type pg parsed the column into.
fieldsYesResult column descriptors, in select-list order.
commandNoPostgres command tag (`INSERT`, `CREATE TABLE`, ...). Absent on the cursor path -- read absence as 'row-returning statement, command unknown'.
rowCountYesRows AFFECTED for DML -- not necessarily rows.length -- and rows returned on the cursor path. Null when pg reported no count.
truncatedNoPresent and true only when the result hit POSTGRES_MAX_ROWS and rows were dropped.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed2 schema fields changedv0.12.1
    • removedOutput schema / properties / rowCount / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / rowCount / type
      Added value: +[
      +  "number",
      +  "null"
      +]
  2. Changed5 schema fields changedv0.12.0
    • addedInput schema / $defs
      Added value: +{
      +  "__schema0": {
      +    "anyOf": [
      +      {
      +        "type": "string"
      +      },
      +      {
      +        "type": "number"
      +      },
      +      {
      +        "type": "boolean"
      +      },
      +      {
      +        "type": "null"
      +      },
      +      {
      +        "items": {
      +          "$ref": "#/$defs/__schema0"
      +        },
      +        "type": "array"
      +      },
      +      {
      +        "additionalProperties": {
      +          "$ref": "#/$defs/__schema0"
      +        },
      +        "propertyNames": {
      +          "type": "string"
      +        },
      +        "type": "object"
      +      }
      +    ]
      +  }
      +}
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • removedInput schema / definitions
      Removed value: -{
      -  "__schema0": {
      -    "anyOf": [
      -      {
      -        "type": "string"
      -      },
      -      {
      -        "type": "number"
      -      },
      -      {
      -        "type": "boolean"
      -      },
      -      {
      -        "type": "null"
      -      },
      -      {
      -        "items": {
      -          "$ref": "#/definitions/__schema0"
      -        },
      -        "type": "array"
      -      },
      -      {
      -        "additionalProperties": {
      -          "$ref": "#/definitions/__schema0"
      -        },
      -        "propertyNames": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      }
      -    ]
      -  }
      -}
    • changedInput schema / properties / params / items / $ref
      Previous value: -"#/definitions/__schema0"New value: +"#/$defs/__schema0"
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "https://json-schema.org/draft/2020-12/schema",
      +  "additionalProperties": false,
      +  "properties": {
      +    "command": {
      +      "description": "Postgres command tag (`INSERT`, `CREATE TABLE`, ...). Absent on the cursor path -- read absence as 'row-returning statement, command unknown'.",
      +      "type": "string"
      +    },
      +    "fields": {
      +      "description": "Result column descriptors, in select-list order.",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "dataTypeID": {
      +            "type": "number"
      +          },
      +          "dataTypeName": {
      +            "type": "string"
      +          },
      +          "name": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "name",
      +          "dataTypeID"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "rowCount": {
      +      "anyOf": [
      +        {
      +          "type": "number"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "Rows AFFECTED for DML -- not necessarily rows.length -- and rows returned on the cursor path. Null when pg reported no count."
      +    },
      +    "rows": {
      +      "description": "Result rows, capped at POSTGRES_MAX_ROWS. Values are whatever JSON type pg parsed the column into.",
      +      "items": {
      +        "additionalProperties": {},
      +        "propertyNames": {
      +          "type": "string"
      +        },
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "truncated": {
      +      "description": "Present and true only when the result hit POSTGRES_MAX_ROWS and rows were dropped.",
      +      "type": "boolean"
      +    }
      +  },
      +  "required": [
      +    "rows",
      +    "rowCount",
      +    "fields"
      +  ],
      +  "type": "object"
      +}
  3. First observedv0.7.0

TDQS

A5/5.0
Behavior5/5

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

Annotations already indicate destructive potential and non-read-only behavior; the description goes further by explaining the role-based safety gate, the BEGIN READ ONLY wrapper, ALLOW_WRITES as a secondary gate, and result truncation to POSTGRES_MAX_ROWS with a truncated flag. This gives the agent a clear model of side effects and limits.

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

Conciseness5/5

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

The description is dense but well-organized: it leads with the core operation, then safety posture, sibling routing, parameter usage, and truncation. Every sentence carries actionable information for an arbitrary-SQL tool with destructive capability; nothing feels like 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 powerful SQL execution tool, the description covers the essential operational context: write-safety mechanisms, when to prefer the read-only sibling, parameter typing semantics, and result limits. The output schema exists to describe return values, so no critical context appears missing.

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

Parameters5/5

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

Schema coverage is 100%, so baseline is 3, but the description adds substantial value beyond the schema: params may be strings, numbers, booleans, null, arrays (for Postgres arrays / ANY), or objects (for json/jsonb), and dates/UUIDs can be ISO strings. It also clarifies the SQL parameterization intent for injection safety.

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 ('Run a SQL query against the configured PostgreSQL database') and explicitly differentiates itself from pg_readonly, so an agent can tell them apart. The intended scope — arbitrary SQL against Postgres — is unmistakable.

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

Usage Guidelines5/5

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

Gives explicit routing guidance: prefer pg_readonly when guaranteed read-only access is desired, and use pg_query for general SQL or managed databases where a second role is awkward. It also tells the agent to use params for parameterized queries to avoid SQL injection.

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

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

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