# MCP SQL requests and results

## Batches and temporary tables

sql is a non-empty array of SQL strings executed in order. SELECT/VALUES and
the engine's supported read-only statements are available. The existing engine
reports invalid or unsupported SQL; source inputs cannot be updated.
CREATE VIEW, CREATE TEMP VIEW and CREATE TEMP TABLE ... AS SELECT ... define
lazy relations in the dataset session. To name
intermediate results, supply:

```json
{
  "dataset_id": "dataset-1",
  "named_temp_queries": [
    {"name": "sizes", "sql": "select file_id, byte_len from dex_files"}
  ],
  "sql": ["select sum(byte_len) as bytes from sizes"]
}
```

Definitions survive later calls for the same dataset until DROP VIEW / DROP TABLE,
redefinition, or close_dataset. CREATE replaces the previous definition after
validation; IF NOT EXISTS keeps it. Named temporary queries have the same lifetime.
TEMP TABLE is lazy like TEMP VIEW: defining it does not execute or materialize its rows.
Definitions are isolated between datasets.
No tools create or open persistent disk caches; use the CLI for those operations.

## Results

query returns dataset_id, statements, and diagnostics. Every statement
contains its zero-based statement_index, sql, kind, columns, rows,
offset, next_offset, total_rows, and truncated. Rows are arrays aligned with the column order,
including duplicate column names. total_rows is the engine's result count
before applying the returned-row limit; an SQL LIMIT has already taken effect.

Each cell is { "type": "...", "value": ... }:

| type | value |
| --- | --- |
| null | JSON null |
| int64 / uint64 | Exact decimal string, including values beyond JavaScript's safe integer range |
| float64 | JSON number, or "NaN", "Infinity", "-Infinity" |
| utf8 | UTF-8 decoded text; see [text values](../sql/index.md#text-values) |
| binary | Lowercase hexadecimal bytes |

The default limit is 200 returned rows per statement (maximum 1000). `offset`
defaults to 0; `offset + limit` must not exceed 100000. Each statement has its own
`next_offset` because byte limits may shorten its page. Continue statements separately
if their offsets differ. Use a deterministic `ORDER BY` with a unique tie-breaker:
paging re-executes the SQL using the current session definitions. A changed SQL
request is a new result, not a continuation. Long request SQL metadata is abbreviated
with `sql_truncated: true`; cell values are never silently shortened.

`max_bytes` can lower the server result budget (minimum 4096 bytes). If one complete row cannot fit,
the tool returns `output_too_large`; select fewer columns or use `substr()` to read
large string values in pieces. These are response limits. Prefer selective WHERE
clauses and SQL LIMIT to reduce execution work; use keyset predicates for deep pages.
Set timing: true to include query timing and per-statement execute_ms,
all in milliseconds. Preparing a dataset reports prepare_ms separately.

Tool results contain both structured JSON and the same JSON as text for client
compatibility. Empty result sets are successful. Input, dataset and SQL failures
set isError: true and return an error object. Engine errors include kind,
stage, message, and a zero-based statement_index when known.

---

Copyright (c) 2026 LSPosed Developers. Documentation licensed under [MIT](../license.md).
