{
  "id": "surf.onchain.sql.preflight",
  "object": "tool",
  "name": "Preflight Blockchain SQL Query",
  "summary": "Validate and cost-estimate a ClickHouse SQL query (EXPLAIN ESTIMATE) without executing it.",
  "description": "Validate and cost-estimate a ClickHouse SQL query without executing it (EXPLAIN ESTIMATE). Returns accepted true/false, the server-bounded executed_sql, estimated parts/rows/marks/bytes per table, the scan budget, and machine-readable guardrail warnings (missing partition filter, unprunable predicates) with recommended actions. NOTE: costs the SAME as executing the query — use it as insurance before an expensive or uncertain /onchain/sql or /onchain/sql/jobs run, not as a routine pre-check.\n\nRaw surf#onchain/sql/preflight endpoint: input is { body, queryParams, pathParams } as the provider documents them (https://docs.asksurf.ai).",
  "category": "lookup",
  "hosted_by": "Surf",
  "runtime": "partner",
  "side_effects": false,
  "status": "live",
  "credits": 0,
  "price": null,
  "providers": [
    {
      "id": "surf",
      "name": "Surf",
      "price": null,
      "own_key_only": true
    }
  ],
  "mcp_name": "surf_onchain_sql_preflight",
  "input_schema": {
    "type": "object",
    "properties": {
      "body": {
        "type": "object",
        "properties": {
          "sql": {
            "type": "string",
            "minLength": 1,
            "description": "Read-only ClickHouse SELECT/WITH query to validate and estimate WITHOUT executing. Same shape and rules as /onchain/sql. Rules (server-enforced or query-killing): SELECT/WITH only (read-only); table references must be database-qualified as agent.<table>; ALWAYS filter on block_date or block_number (partition key — without it the query times out); compare address columns directly against lowercase literals (wrapping the column in lower() is rejected); never filter on symbol columns (unindexed full scan, and symbol matches surface scam clones — resolve a ticker to a contract address with /search/token first); on transfer tables use separate UNION ALL branches instead of OR across from/to; use single quotes for strings, e.g. toDate('2026-04-07')."
          },
          "max_rows": {
            "default": 1000,
            "type": "integer",
            "minimum": 1,
            "maximum": 10000,
            "description": "Maximum rows to return. Example: 100. Defaults to 1000 (server-side), capped at 10000."
          }
        },
        "required": [
          "sql"
        ],
        "additionalProperties": false
      }
    },
    "required": [
      "body"
    ],
    "additionalProperties": false
  },
  "kind": "endpoint"
}