Skip to main content
Glama
YawLabs

@yawlabs/postgres-mcp

by YawLabs

Recommend indexes for a workload

pg_index_advisor
Read-onlyIdempotent

Recommend PostgreSQL indexes that measurably cut query cost; each candidate is EXPLAINed and validated with HypoPG before being suggested.

Instructions

Recommend indexes for a workload, and prove each one pays for itself before recommending it. Give it statements (the SQL you care about) or let it take the top N from pg_stat_statements; it plans each statement, generates candidate indexes, costs them with HypoPG hypothetical indexes, and returns only the ones that measurably cut estimated cost. How candidates are generated, and the honest limit: this tool has NO SQL parser and does not read your SQL text. It EXPLAINs each statement and harvests the columns the PLANNER reports as filters, join keys, and sort keys, then intersects those tokens with the real column list from pg_attribute -- so a candidate can never name a column that does not exist. The extraction is deliberately loose (a token matching a real column name on a different table can slip through); HypoPG is the arbiter, and anything that does not lower cost is discarded. Column ORDER within each candidate is equality columns first (most selective first, from pg_stats), then at most one range column, then sort columns. The search is greedy and BOUNDED. Each accepted index stays in place while the rest are re-costed on top of it, so later picks account for what earlier ones already fixed. max_candidates caps how many candidates are considered and max_explains caps total EXPLAIN round trips; when a cap stops the search early, budget_exhausted is true and the result is a truncated search, not a converged one. PostgreSQL 18 note, and it reverses a rule you have probably internalized: PG18 added B-tree SKIP SCAN, so a multi-column index whose LEADING column the query never constrains CAN now be used. The classic 'leading column never filtered means the index is useless' heuristic is wrong on PG18+. This tool gates that prune on the server version -- on PG18+ such candidates are kept and costed (skip_scan_available: true, and an accepted one carries requires_skip_scan), below PG18 they are pruned as unusable and counted in candidates_pruned_leading_column. Requires the HypoPG extension (CREATE EXTENSION hypopg;). Hypothetical indexes are session-scoped and are reset before the call returns, on the success and the failure path alike, so they never touch disk and never leak into a later query plan. Statements are only ever EXPLAINed, never executed, inside a BEGIN READ ONLY transaction. Costs are PLANNER ESTIMATES, not measurements: they are the right way to compare two plans for the same statement and the wrong way to predict wall-clock time. They are weighted by calls when the workload came from pg_stat_statements, so a query run a million times outranks an identical one run twice. Validate a recommendation with pg_explain before creating it, and create it with CONCURRENTLY in production (create_statement_concurrently).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoHow many statements to pull from pg_stat_statements. Ignored when `statements` is given.
schemaNoOnly recommend indexes on tables in this schema. Candidates elsewhere are dropped.
statementsNoThe workload to optimize. When omitted, the top `limit` statements from pg_stat_statements are used instead (and weighted by their call counts).
max_explainsNoCap on EXPLAIN round trips spent searching (baseline plans are not counted). The search stops when the next candidate would exceed it and reports `budget_exhausted: true`.
max_candidatesNoCap on candidate indexes considered. Candidates are ranked by table sequential-scan count first.
min_improvementNoFraction of total weighted workload cost an index must remove to be accepted (0.1 = 10%). Relative rather than absolute so it means the same thing on a small and a large database.
max_index_columnsNoWidest candidate index to consider. Every narrower prefix is considered too.
max_recommendationsNoStop after this many accepted indexes, even if more would still help.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
_warningsNo
statementsYesThe workload as analyzed, in the order `helps_statements.statement` indexes into.
explains_usedYesEXPLAIN round trips spent searching, excluding baseline plans.
explain_budgetYes
recommendationsYes
budget_exhaustedYesTrue when `max_explains` stopped the search before it converged.
final_workload_costYesWeighted total after applying every recommendation.
skip_scan_availableYesTrue on PostgreSQL 18+, where B-tree skip scan exists.
candidates_consideredYes
baseline_workload_costYesWeighted total estimated cost before any recommendation.
candidates_pruned_leading_columnYesMulti-column candidates dropped by the pre-PG18 leading-column rule. Always 0 on PG18+.

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 / recommendations / items / properties / estimated_size_bytes / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / recommendations / items / properties / estimated_size_bytes / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / statements / items / properties / baseline_cost / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / statements / items / properties / baseline_cost / type
      Added value: +[
      +  "number",
      +  "null"
      +]
  2. Addedv0.12.0

TDQS

A4.7/5.0
Behavior5/5

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

The description goes far beyond the readOnlyHint/destructiveHint annotations: no SQL parser, EXPLAIN-only execution, BEGIN READ ONLY transaction, HypoPG reset on both success and failure paths, bounded greedy search, PG18 skip-scan version dependence, and planner-estimate semantics. This is exceptionally thorough behavioral disclosure.

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 long but every paragraph earns its place: input modes, candidate generation limitations, bounded search behavior, PG18 caveat, safety guarantees, and cost semantics are all relevant. The bolded paragraph lead-ins and code-formatted parameter names make it easy to scan.

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 tool with 8 optional parameters, an output schema, and subtle server-version behavior, the description is complete. It covers prerequisites, side effects, algorithm limits, version-specific pruning, and what the returned recommendations mean. Since the output schema exists, not enumerating return values in prose is acceptable.

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 input schema already provides 100% parameter coverage, so the baseline is 3. The description adds meaningful context beyond the schema by explaining that `max_candidates` and `max_explains` cap the search and produce `budget_exhausted`, and by clarifying that `statements` weighting by `calls` applies when pulling from pg_stat_statements.

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 leads with a specific verb and object: 'Recommend indexes for a workload', then substantiates it with a clear mechanism: plan statements, generate candidates, cost them with HypoPG, and return only cost-reducing indexes. This sharply distinguishes it from generic siblings like pg_advisor or pg_unused_indexes.

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 clearly tells the agent when to supply explicit `statements` versus using `pg_stat_statements`, and it names `pg_explain` as the follow-up validation tool. It does not explicitly enumerate every sibling alternative or state when *not* to use it, but the usage context is strong enough for correct selection.

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