mcp-trino v1.3.0 — Format Validation, Tool Description Prose, and Opt-in JSON Unwrap
v1.3.0 improves agent ergonomics for trino_query and trino_execute with three changes: invalid format values now return a clear error instead of silently falling through, the tool description prose now documents format and unwrap_json so agents discover them without reading parameter schemas, and a new opt-in unwrap_json parameter eliminates double-encoded JSON responses from table functions like raw_query().
New Features
Format parameter validation
The format parameter on trino_query and trino_execute now validates against accepted values (json, csv, markdown). Previously, an invalid value like format=tsv or format=JSON (wrong case) silently fell through to JSON output with no signal to the caller. Now it returns a clear error:
invalid format "tsv": must be one of json, csv, markdown
Tool description prose
Both trino_query and trino_execute tool descriptions now mention format and unwrap_json in the main prose block. MCP agents that scan tool descriptions (rather than per-parameter schemas) will now discover these parameters. Example addition:
Results are returned as JSON by default. Pass format=csv for CSV output (more token-efficient for large result sets) or format=markdown for a pipe-table. Set unwrap_json=true to automatically parse single-row, single-string-column results containing a JSON object or array — the column type changes to JSON and the value becomes the parsed object.
Opt-in JSON unwrap (unwrap_json)
New boolean parameter on trino_query and trino_execute (default false). When enabled and the result is exactly one row with one string-type column (VARCHAR, CHAR, or JSON) containing a valid JSON object or array:
- The string value in
rows[0]is replaced with the parsed JSON object columns[0].typeis changed to"JSON"as an unambiguous signal- The envelope shape (
columns,rows,row_count,stats) is unchanged
Without unwrap_json (current behavior):
{
"columns": [{ "name": "result", "type": "VARCHAR" }],
"rows": [{ "result": "{\"took\":2,\"aggregations\":{\"by_region\":{\"buckets\":[...]}}}" }],
"row_count": 1,
"stats": { "row_count": 1, "duration_ms": 45 }
}With unwrap_json=true:
{
"columns": [{ "name": "result", "type": "JSON" }],
"rows": [{ "result": { "took": 2, "aggregations": { "by_region": { "buckets": [...] } } } }],
"row_count": 1,
"stats": { "row_count": 1, "duration_ms": 45 }
}Same envelope, no double-encoding, no extra fields. Consumers can branch on columns[0].type == "JSON" to detect the unwrap.
Graceful fall-through: If the result doesn't match (multiple columns, multiple rows, non-string type, invalid JSON, or a JSON scalar like 42 or "hello"), the response is byte-identical to unwrap_json=false.
Accepted column types: VARCHAR, VARCHAR(N), CHAR, CHAR(N), JSON — any string-like Trino type.
Explain type validation
trino_explain's type parameter now validates against accepted values (logical, distributed, io, validate) with the same pattern as format.
Breaking Changes
trino_explain type parameter validation
Previously, invalid type values (e.g. LOGICAL uppercase, unknown) silently defaulted to logical. Now they return an error:
invalid explain type "LOGICAL": must be one of logical, distributed, io, validate
Any existing caller passing uppercase or unrecognized type values will need to update.
JSON format output includes row_count top-level field
The JSON output now serializes QueryOutput instead of the internal client.QueryResult. This adds a row_count field at the top level of the JSON envelope. No existing fields were removed or renamed. Consumers that strictly validate the response schema against a fixed set of known fields may need to update their schema to allow the new field.
Code Organization
- New
pkg/tools/format.go: Consolidates all formatting logic — validation, output rendering (formatOutput,formatCSV,formatMarkdown), value stringification, CSV escaping, column type detection, and JSON unwrap. Previously this was spread acrossquery.gowith inline switch statements. formatCSV/formatMarkdownnow operate on*QueryOutputinstead of*client.QueryResult, enabling the unwrap mutation to flow through all output formats.stringifyValuehelper ensuresmap[string]anyand[]anyvalues (from unwrapped JSON) render as compact JSON strings in CSV and markdown output, instead of Go'smap[key:value]format.
Dependency Updates
github.com/modelcontextprotocol/go-sdkbumped (#56)- GitHub Actions group bumped with 3 updates (#55)
Full Changelog: v1.2.0...v1.3.0