Skip to main content
Glama
YawLabs

@yawlabs/postgres-mcp

by YawLabs

Describe table

pg_describe_table
Read-onlyIdempotent

Inspect a PostgreSQL relation's structure—kind, columns, keys, constraints, indexes, partitions, and writability—to understand the schema before querying or modifying data.

Instructions

Describe a relation: kind (table / view / materialized_view / partitioned_table / foreign_table), columns (name, type, nullable, default, generated, identity), primary key, foreign keys (outgoing), referenced_by (other tables whose FKs point at this one), constraints (CHECK / UNIQUE non-PK / EXCLUDE), indexes, and partition info (partition_of parent, partitions children). Works on views and materialized views too -- PK/FK/constraint/index lists will simply be empty for a plain view. Use kind to disambiguate before assuming you can write to the relation. Generated columns (generated: 'stored' / 'virtual') and identity: 'always' columns are NOT writable -- omit them from INSERT/UPDATE column lists; a generated column's expression is reported as generation_expression, never as default_value. On PostgreSQL 18+ constraints also report validated / enforced / has_period, and columns report not_null_validated -- a NOT VALID not-null constraint means nullable: false can still hide NULLs.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tableYesTable name.
schemaNoSchema name (defaults to 'public').public

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
kindYestable | partitioned_table | view | materialized_view | foreign_table, or the raw relkind. Defaults to 'table' with a `_warnings` entry when the kind fetch failed.
tableYes
schemaYes
columnsYes
indexesYes
_warningsNo
partitionsNoPresent only when this relation is a partitioned parent WITH children.
constraintsYesCHECK / non-PK UNIQUE / EXCLUDE only; PK and FK have their own lists.
primary_keyYesKey columns in declared order; INCLUDE columns are excluded.
foreign_keysYes
partition_ofNoPresent only when this relation is itself a partition.
referenced_byYesOther tables whose foreign keys point AT this one.

Schema Changelog

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

  1. Changed4 schema fields changedv0.12.1
    • removedOutput schema / properties / columns / items / properties / default_value / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / columns / items / properties / default_value / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / columns / items / properties / generation_expression / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / columns / items / properties / generation_expression / type
      Added value: +[
      +  "string",
      +  "null"
      +]
  2. Changed2 schema fields changedv0.12.0
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "https://json-schema.org/draft/2020-12/schema",
      +  "additionalProperties": false,
      +  "properties": {
      +    "_warnings": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "columns": {
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "default_value": {
      +            "anyOf": [
      +              {
      +                "type": "string"
      +              },
      +              {
      +                "type": "null"
      +              }
      +            ],
      +            "description": "Null for a generated column -- see generation_expression."
      +          },
      +          "generated": {
      +            "anyOf": [
      +              {
      +                "enum": [
      +                  "stored",
      +                  "virtual"
      +                ],
      +                "type": "string"
      +              },
      +              {
      +                "type": "null"
      +              }
      +            ],
      +            "description": "Non-null means the column is NOT writable; omit it from INSERT/UPDATE column lists."
      +          },
      +          "generation_expression": {
      +            "anyOf": [
      +              {
      +                "type": "string"
      +              },
      +              {
      +                "type": "null"
      +              }
      +            ],
      +            "description": "Null unless `generated` is set."
      +          },
      +          "identity": {
      +            "anyOf": [
      +              {
      +                "enum": [
      +                  "always",
      +                  "by_default"
      +                ],
      +                "type": "string"
      +              },
      +              {
      +                "type": "null"
      +              }
      +            ],
      +            "description": "'always' means the column is NOT writable without OVERRIDING SYSTEM VALUE."
      +          },
      +          "name": {
      +            "type": "string"
      +          },
      +          "not_null_validated": {
      +            "description": "PostgreSQL 18+ only, absent below that. False means a NOT VALID not-null constraint, so `nullable: false` can still hide NULLs.",
      +            "type": "boolean"
      +          },
      +          "nullable": {
      +            "description": "NOT attnotnull. On PG18+ read alongside `not_null_validated`.",
      +            "type": "boolean"
      +          },
      +          "ordinal_position": {
      +            "description": "attnum, so dropped columns leave gaps.",
      +            "type": "number"
      +          },
      +          "type": {
      +            "description": "Formatted type, e.g. `character varying(64)`.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "name",
      +          "type",
      +          "nullable",
      +          "default_value",
      +          "generation_expression",
      +          "generated",
      +          "identity",
      +          "ordinal_position"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "constraints": {
      +      "description": "CHECK / non-PK UNIQUE / EXCLUDE only; PK and FK have their own lists.",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "definition": {
      +            "type": "string"
      +          },
      +          "enforced": {
      +            "description": "PostgreSQL 18+ only, absent below that. False means the constraint is recorded but enforces nothing -- do not lean on it as a guarantee.",
      +            "type": "boolean"
      +          },
      +          "has_period": {
      +            "description": "PostgreSQL 18+ only, absent below that. True for a temporal (PERIOD / WITHOUT OVERLAPS) key.",
      +            "type": "boolean"
      +          },
      +          "name": {
      +            "type": "string"
      +          },
      +          "type": {
      +            "description": "check | unique | exclude, or the raw contype.",
      +            "type": "string"
      +          },
      +          "validated": {
      +            "description": "False for a NOT VALID constraint: existing rows were never checked against it.",
      +            "type": "boolean"
      +          }
      +        },
      +        "required": [
      +          "name",
      +          "type",
      +          "definition",
      +          "validated"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "foreign_keys": {
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "columns": {
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "constraint_name": {
      +            "type": "string"
      +          },
      +          "enforced": {
      +            "description": "PostgreSQL 18+ only, absent below that. False means the constraint is recorded but enforces nothing -- do not lean on it as a guarantee.",
      +            "type": "boolean"
      +          },
      +          "foreign_columns": {
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "foreign_schema": {
      +            "type": "string"
      +          },
      +          "foreign_table": {
      +            "type": "string"
      +          },
      +          "has_period": {
      +            "description": "PostgreSQL 18+ only, absent below that. True for a temporal (PERIOD / WITHOUT OVERLAPS) key.",
      +            "type": "boolean"
      +          },
      +          "validated": {
      +            "description": "False for a NOT VALID constraint: existing rows were never checked against it.",
      +            "type": "boolean"
      +          }
      +        },
      +        "required": [
      +          "constraint_name",
      +          "columns",
      +          "foreign_table",
      +          "foreign_schema",
      +          "foreign_columns",
      +          "validated"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "indexes": {
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "definition": {
      +            "type": "string"
      +          },
      +          "is_primary": {
      +            "type": "boolean"
      +          },
      +          "is_unique": {
      +            "type": "boolean"
      +          },
      +          "name": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "name",
      +          "definition",
      +          "is_unique",
      +          "is_primary"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "kind": {
      +      "description": "table | partitioned_table | view | materialized_view | foreign_table, or the raw relkind. Defaults to 'table' with a `_warnings` entry when the kind fetch failed.",
      +      "type": "string"
      +    },
      +    "partition_of": {
      +      "additionalProperties": false,
      +      "description": "Present only when this relation is itself a partition.",
      +      "properties": {
      +        "schema": {
      +          "type": "string"
      +        },
      +        "table": {
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "schema",
      +        "table"
      +      ],
      +      "type": "object"
      +    },
      +    "partitions": {
      +      "description": "Present only when this relation is a partitioned parent WITH children.",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "bound": {
      +            "type": "string"
      +          },
      +          "schema": {
      +            "type": "string"
      +          },
      +          "table": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "schema",
      +          "table",
      +          "bound"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "primary_key": {
      +      "description": "Key columns in declared order; INCLUDE columns are excluded.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "referenced_by": {
      +      "description": "Other tables whose foreign keys point AT this one.",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "columns": {
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "constraint_name": {
      +            "type": "string"
      +          },
      +          "enforced": {
      +            "description": "PostgreSQL 18+ only, absent below that. False means the constraint is recorded but enforces nothing -- do not lean on it as a guarantee.",
      +            "type": "boolean"
      +          },
      +          "has_period": {
      +            "description": "PostgreSQL 18+ only, absent below that. True for a temporal (PERIOD / WITHOUT OVERLAPS) key.",
      +            "type": "boolean"
      +          },
      +          "referenced_columns": {
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "schema": {
      +            "type": "string"
      +          },
      +          "table": {
      +            "type": "string"
      +          },
      +          "validated": {
      +            "description": "False for a NOT VALID constraint: existing rows were never checked against it.",
      +            "type": "boolean"
      +          }
      +        },
      +        "required": [
      +          "constraint_name",
      +          "schema",
      +          "table",
      +          "columns",
      +          "referenced_columns",
      +          "validated"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "schema": {
      +      "type": "string"
      +    },
      +    "table": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "schema",
      +    "table",
      +    "kind",
      +    "columns",
      +    "primary_key",
      +    "foreign_keys",
      +    "referenced_by",
      +    "constraints",
      +    "indexes"
      +  ],
      +  "type": "object"
      +}
  3. First observedv0.7.0

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, but the description adds substantial behavioral detail beyond that: generated and identity columns are NOT writable, generation expressions are reported separately, and PostgreSQL 18+ introduces additional fields like `validated` and `not_null_validated`. It also warns about the subtle case where `nullable: false` can still hide NULLs under a NOT VALID constraint, which is exactly the kind of behavioral nuance an agent needs.

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?

Although the description is long, every sentence carries essential information: the full output inventory, edge cases for views and materialized views, write-safety caveats for generated and identity columns, and version-specific behavior. It is front-loaded with the core output structure and then layers on important nuances without any filler or repetition.

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?

The tool is complex, but the description covers all critical aspects needed for correct use: what the output contains, special relation kinds, write restrictions, version-specific fields, and the NULL caveat. Since an output schema exists, the exact return structure does not need to be spelled out in prose, and nothing important is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so the input schema already fully documents both parameters (`table` and `schema`). The description adds no new parameter-specific meaning beyond what the schema provides, so the baseline score 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 ('Describe') with a clear resource ('a relation') and enumerates the exact information returned: kind, columns, primary key, foreign keys, constraints, indexes, and partition info. It also explicitly distinguishes itself from sibling listing tools by covering views and materialized views, making it immediately clear what this tool does and what it is not.

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 practical guidance: use `kind` to disambiguate before assuming you can write, and it states that the tool works on views and materialized views. It does not explicitly name sibling alternatives or state when not to use this tool, but the context is clear enough for an agent to know when this detailed inspection tool is appropriate.

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