Skip to main content
Glama

explain_query

Analyze SQL query execution plans to understand database performance, simulate hypothetical indexes, and optimize PostgreSQL queries with detailed cost estimates.

Instructions

Explains the execution plan for a SQL query, showing how the database will execute it and provides detailed cost estimates.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sqlYesSQL query to explain
analyzeNoWhen True, actually runs the query to show real execution statistics instead of estimates. Takes longer but provides more accurate information.
hypothetical_indexesNoA list of hypothetical indexes to simulate. Each index must be a dictionary with these keys: - 'table': The table name to add the index to (e.g., 'users') - 'columns': List of column names to include in the index (e.g., ['email'] or ['last_name', 'first_name']) - 'using': Optional index method (default: 'btree', other options include 'hash', 'gist', etc.) Examples: [ {"table": "users", "columns": ["email"], "using": "btree"}, {"table": "orders", "columns": ["user_id", "created_at"]} ] If there is no hypothetical index, you can pass an empty list.

Implementation Reference

  • The `explain_query` function acts as the MCP tool handler. It parses inputs (SQL, analyze flag, hypothetical indexes), validates them, and delegates the core explain logic to the `ExplainPlanTool` class.
    async def explain_query(
        sql: str = Field(description="SQL query to explain"),
        analyze: bool = Field(
            description="When True, actually runs the query to show real execution statistics instead of estimates. "
            "Takes longer but provides more accurate information.",
            default=False,
        ),
        hypothetical_indexes: list[dict[str, Any]] = Field(
            description="""A list of hypothetical indexes to simulate. Each index must be a dictionary with these keys:
        - 'table': The table name to add the index to (e.g., 'users')
        - 'columns': List of column names to include in the index (e.g., ['email'] or ['last_name', 'first_name'])
        - 'using': Optional index method (default: 'btree', other options include 'hash', 'gist', etc.)
    
    Examples: [
        {"table": "users", "columns": ["email"], "using": "btree"},
        {"table": "orders", "columns": ["user_id", "created_at"]}
    ]
    If there is no hypothetical index, you can pass an empty list.""",
            default=[],
        ),
    ) -> ResponseType:
        """
        Explains the execution plan for a SQL query.
    
        Args:
            sql: The SQL query to explain
            analyze: When True, actually runs the query for real statistics
            hypothetical_indexes: Optional list of indexes to simulate
        """
        try:
            sql_driver = await get_sql_driver()
            explain_tool = ExplainPlanTool(sql_driver=sql_driver)
            result: ExplainPlanArtifact | ErrorResult | None = None
    
            # If hypothetical indexes are specified, check for HypoPG extension
            if hypothetical_indexes and len(hypothetical_indexes) > 0:
                if analyze:
                    return format_error_response("Cannot use analyze and hypothetical indexes together")
                try:
                    # Use the common utility function to check if hypopg is installed
                    (
                        is_hypopg_installed,
                        hypopg_message,
                    ) = await check_hypopg_installation_status(sql_driver)
    
                    # If hypopg is not installed, return the message
                    if not is_hypopg_installed:
                        return format_text_response(hypopg_message)
    
                    # HypoPG is installed, proceed with explaining with hypothetical indexes
                    result = await explain_tool.explain_with_hypothetical_indexes(sql, hypothetical_indexes)
                except Exception:
                    raise  # Re-raise the original exception
            elif analyze:
                try:
                    # Use EXPLAIN ANALYZE
                    result = await explain_tool.explain_analyze(sql)
                except Exception:
                    raise  # Re-raise the original exception
            else:
                try:
                    # Use basic EXPLAIN
                    result = await explain_tool.explain(sql)
                except Exception:
                    raise  # Re-raise the original exception
    
            if result and isinstance(result, ExplainPlanArtifact):
Behavior2/5

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

With no annotations, the description bears full responsibility for behavioral disclosure. It fails to warn that the tool can actually execute queries when analyze=True (potentially destructive for INSERT/UPDATE/DELETE statements) or describe the performance implications of running queries. It also omits the hypothetical index simulation capability entirely.

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 efficiently states the tool's purpose without redundancy. However, given the complexity of the hypothetical_indexes parameter and the analyze safety implications, the brevity may be excessive under-specification rather than optimal conciseness.

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

Completeness2/5

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

Inadequate for a three-parameter tool with complex nested objects (hypothetical index definitions) and no output schema. The description omits the tool's index simulation capabilities, fails to describe return value structure, and lacks safety warnings necessary for a tool capable of executing SQL when analyze=True.

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%, establishing a baseline of 3. The description mentions 'cost estimates' which contextually relates to the analyze parameter's purpose, but adds no syntax guidance, format details, or semantic clarifications beyond what the detailed schema already provides.

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?

Clearly states the core function (explains execution plans) and outputs (cost estimates). Uses specific verbs and identifies the resource (SQL query). However, it does not explicitly differentiate from sibling analysis tools like analyze_query_indexes or analyze_workload_indexes.

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?

Provides no guidance on when to use this tool versus alternatives. Does not mention whether to use this before execute_sql, when debugging slow queries, or how it relates to the index analysis siblings. No prerequisites or conditions are stated.

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

Install Server

Other Tools

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/moecodeshere/mcptrial'

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