Resources

Database to MCP

QueryPlan vs SQL mode for Database to MCP

When to use structured QueryPlan execution and when SQL mode makes sense for advanced database MCP workflows.

11 min readUpdated 2026-07-02
QueryPlanSQL modeDatabase validationMCP executors

Written by RTT Intelligence Engineering

Technical notes from the team building MCP surfaces for OpenAPI APIs and database scopes with server-side credentials, validation, and audit-oriented logs.

Reviewed for practical implementation

Focused on usable architecture, security boundaries, and production tradeoffs rather than generic definitions.

Use QueryPlan mode by default

QueryPlan mode is the recommended executor mode because a structured request is easier to validate conservatively.

A QueryPlan describes the intended query using provider-independent JSON. Instead of asking the model to write database-specific SQL, the model fills structured fields such as source table, selected columns, joins, filters, grouping, ordering, and limit.

The Gateway validates that plan against the published database scope. Only after validation does the Gateway generate PostgreSQL or SQL Server SQL, and the generated SQL is validated again before execution.

This gives the model enough structure to answer real questions while keeping table access, column permissions, joins, limits, and policy flags in the Gateway.

What a QueryPlan looks like

The plan is explicit about table aliases, columns, aggregates, filters, ordering, and row limits.

Provider-independent QueryPlan example

json
{
  "version": "1.0",
  "description": "Last 3 months total sales by city",
  "from": {
    "table": "Customers",
    "alias": "c"
  },
  "joins": [
    {
      "type": "inner",
      "table": "Orders",
      "alias": "o",
      "on": {
        "left": {
          "tableAlias": "o",
          "column": "CustomerId"
        },
        "operator": "=",
        "right": {
          "tableAlias": "c",
          "column": "Id"
        }
      }
    }
  ],
  "select": [
    {
      "column": {
        "tableAlias": "c",
        "column": "City"
      },
      "alias": "City"
    },
    {
      "aggregate": {
        "function": "SUM",
        "tableAlias": "o",
        "column": "TotalAmount"
      },
      "alias": "TotalSales"
    }
  ],
  "where": [
    {
      "column": {
        "tableAlias": "o",
        "column": "OrderDate"
      },
      "operator": ">=",
      "valueType": "relative_date",
      "value": "last_3_months"
    }
  ],
  "groupBy": [
    {
      "tableAlias": "c",
      "column": "City"
    }
  ],
  "orderBy": [
    {
      "alias": "TotalSales",
      "direction": "desc"
    }
  ],
  "limit": 100
}

How QueryPlan validation works

The validator checks the plan against scope metadata before SQL generation.

Validation checkWhat it prevents
Scope modeA QueryPlan request cannot run against a scope configured for SqlScript mode.
Published table checkThe from table and joined tables must exist in the current MCP scope.
Relationship checkJoins must use relationships allowed in the current scope.
Alias and column resolutionColumn references must resolve through known aliases and published columns.
Column permissionsSelected, filtered, sorted, grouped, and aggregated columns must be permitted for that use.
Limit policyThe request must include a limit when required and cannot exceed MaxRows.
Raw expression policyRaw expressions are rejected unless a policy explicitly allows them.

Use SqlScript mode for advanced cases

SqlScript mode is available when a reviewed workflow needs SQL expressiveness, but it is not direct database access.

In SqlScript mode, the model or orchestration layer proposes SQL text and parameters. The Gateway still validates the SQL before execution, and the scope publishes SqlScript executor tools instead of QueryPlan executor tools.

SqlScript mode should be treated as advanced. It is useful when a known workflow needs SQL patterns that QueryPlan does not cover yet, but it should not become a broad free-form SQL console for an agent.

SqlScript execution candidate

json
{
  "sql": "select CustomerId, Status, CreatedAt from sales.Orders where Status = @status order by CreatedAt desc limit 50",
  "parameters": {
    "status": "open"
  }
}

SqlScript mode guardrails

The default SQL validator is conservative by design.

GuardrailDefault expectation
Statement typeSELECT-only. DML and DDL are rejected.
Statement countSingle statement only.
LimitRequired when RequireLimit is enabled.
SELECT *Blocked when BlockSelectStar is enabled.
Scope accessOnly published tables, columns, and relationships in the current scope can be used.
System objectsSystem schemas and tables are blocked.
Complex SQLCTEs, subqueries, unions, and raw expressions stay disabled unless policy flags allow them.
Dangerous functionsDangerous functions are blocked.

Decision matrix

Most teams should start with QueryPlan and only move to SqlScript for a documented reason.

QuestionPrefer QueryPlan when...Consider SqlScript when...
Is this a normal read workflow?The answer can be expressed with tables, joins, filters, grouping, ordering, and limits.The query needs a SQL pattern not supported by the current QueryPlan shape.
How much validation clarity do you need?You want each table, column, aggregate, and filter to be checked as structured data.You can accept SQL parsing and conservative SQL validation for a reviewed use case.
Who will maintain it?A product or operations team will tune scopes and permissions over time.A technical team owns the SQL pattern and understands validator failures.
What is the first rollout?You are starting a new AI database workflow.You are migrating a known internal reporting query and can test it thoroughly.

How this behaves in chat

A good chat workflow uses schema tools for context, then validates before execution.

  • The assistant reads schema metadata tools to understand approved tables, columns, permissions, and relationships.
  • For QueryPlan mode, the assistant proposes a structured plan and can validate it before execution.
  • For SqlScript mode, the assistant proposes SQL and parameters, then the Gateway validates the SQL before execution.
  • If validation fails, the assistant should revise the request instead of bypassing the Gateway.
  • Explain tools are useful for debugging and review, but execution still requires validation and scope compliance.

Operational advice

The executor mode is a product decision, not only a technical preference.

  • Use one executor mode per scope so clients see a clear contract.
  • Use QueryPlan for the first version of a customer-facing or internal operations workflow.
  • Keep SqlScript behind stricter review and logging because the input language is broader.
  • Inspect validation failures during rollout; they often reveal missing column permissions or an overly broad user question.
  • Do not ask the model to enforce database policy. Put policy in Gateway validation.

Common questions

Can QueryPlan and SQL mode be published together?

No. A database scope publishes either QueryPlan executor tools or SqlScript executor tools, never both at the same time.

Why is QueryPlan recommended?

A structured plan gives the Gateway clearer fields to validate against published tables, columns, relationships, aggregates, limits, and policy flags before SQL is generated.

Does SQL mode skip validation?

No. SqlScript mode is still validated by the Gateway before execution. It is SELECT-only by default and remains bound to the current scope.

Why not just let the LLM write SQL?

An LLM can propose SQL, but it should not be trusted as the database security boundary. The Gateway must still enforce scope, table, column, relationship, limit, and SQL safety rules.

What happens if validation fails?

The request is rejected before execution. A chat workflow can use the validation error to revise the QueryPlan or SQL candidate inside the published scope.