/api/json/query
MCP tool json_query Evaluates expression against input with @jmespath-community/jmespath (JMESPath Community Edition): the original JMESPath language plus let expressions, $ for the root, arithmetic (+ - * / % //), the ternary ? : operator, and extra functions such as items, from_items, group_by, zip, find_first, pad_left, split, replace, trim. A path that does not exist gives null (not an error). Syntax errors give the column of the offending token; unknown functions are reported before evaluation; type errors (for example length of a number) are reported with the function position.
Browser version (runs locally): JMESPath Query.
Try it
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
input required | string (≤ 500000 chars) | — | The JSON document, as JSON text (string field or raw text/plain POST body). |
expression required | string (≤ 2048 chars) | — | The JMESPath expression, e.g. sort_by(items, &price)[-1].name. JSON literals are written between backtick characters; raw strings go in single quotes. |
indent | 2 | 4 | tab | none | 2 | JSON output indentation: 2 or 4 spaces, tab, or none for minified output (no whitespace at all). |
Also accepted on every endpoint: format (json | text).
Parameters may come from the query string, a JSON object body, an urlencoded or multipart form,
or (for input) a text/plain body.
Global parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
format | json | text | json | json returns the documented object. text returns only the primary value as text/plain (see "Text output"). |
Response 200 application/json
| Field | Type | Description |
|---|---|---|
result | any | The result as a JSON value (null when nothing matched). |
type | "object" | "array" | "string" | "number" | "boolean" | "null" | JSON type of the result. |
json | string | The result as JSON text, formatted per indent. |
warnings | array of object | Valid-but-risky findings: integers beyond 2^53 − 1, numbers that overflow a double, unpaired surrogate escapes, duplicate keys. At most 100 are listed. |
warnings[].message | string | Plain-language finding. |
warnings[].pointer | string | JSON Pointer of the value concerned. |
warnings[].line | integer | 1-based line number. |
warnings[].column | integer | 1-based column, counted in Unicode code points. |
warnings[].offset | integer | 0-based offset in code points. |
Text output (format=text, text/plain): The result as JSON text.
Errors
Errors are JSON: {"error": "<message>", "code": "<code>", "param": "<name>"?}.
| Status | Code | When |
|---|---|---|
422 | unprocessable_input | input is not valid JSON (line, column and offset given); expression has a syntax error (column given) or calls an unknown function; or evaluation fails (a function received the wrong type, division by zero, a slice step of 0). |
400 | invalid_parameter | input exceeds 500,000 characters or expression exceeds 2,048. |
400 | missing_parameter | A required parameter is absent. |
400 | unknown_parameter | A parameter name is not in the table above (typos are rejected, not ignored). |
413 | payload_too_large | The request body exceeds 1 MiB. |
405 | method_not_allowed | A method other than GET, POST or OPTIONS. |
Behaviour
- Idempotent: the same arguments always return the same result.
-
Requires a client ID and secret (authentication). Each call is
recorded as one metadata row against your client ID; inputs and outputs are never stored or
logged. Responses carry
cache-control: no-store. - CORS: any origin may call this endpoint from a browser, using your credentials.
Examples
Responses below were produced by running each request through this code at build time. Long strings are shortened.
Filter and project
curl -X POST 'https://util.caruana.me/api/json/query' \
-H 'content-type: application/json' \
-d '{"input":"{\"items\":[{\"name\":\"a\",\"price\":5,\"tags\":[\"x\"]},{\"name\":\"b\",\"price\":12,\"tags\":[\"x\",\"y\"]},{\"name\":\"c\",\"price\":30,\"tags\":[]}]}","expression":"items[?price > `10`].name"}'
Response 200
{
"result": [
"b",
"c"
],
"type": "array",
"json": "[\n \"b\",\n \"c\"\n]",
"warnings": []
}
Same call as an MCP tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "json_query",
"arguments": {
"input": "{\"items\":[{\"name\":\"a\",\"price\":5,\"tags\":[\"x\"]},{\"name\":\"b\",\"price\":12,\"tags\":[\"x\",\"y\"]},{\"name\":\"c\",\"price\":30,\"tags\":[]}]}",
"expression": "items[?price > `10`].name"
}
}
}Sort, slice and reshape
curl -X POST 'https://util.caruana.me/api/json/query' \
-H 'content-type: application/json' \
-d '{"input":"{\"items\":[{\"name\":\"a\",\"price\":5},{\"name\":\"b\",\"price\":12},{\"name\":\"c\",\"price\":30}]}","expression":"sort_by(items, &price)[-2:].{name: name, cost: price}"}'
Response 200
{
"result": [
{
"name": "b",
"cost": 12
},
{
"name": "c",
"cost": 30
}
],
"type": "array",
"json": "[\n {\n \"name\": \"b\",\n \"cost\": 12\n },\n {\n \"name\": \"c\",\n \"cost\": 30\n }\n]",
"warnings": []
}
Same call as an MCP tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "json_query",
"arguments": {
"input": "{\"items\":[{\"name\":\"a\",\"price\":5},{\"name\":\"b\",\"price\":12},{\"name\":\"c\",\"price\":30}]}",
"expression": "sort_by(items, &price)[-2:].{name: name, cost: price}"
}
}
}Count and aggregate
curl -X POST 'https://util.caruana.me/api/json/query' \
-H 'content-type: application/json' \
-d '{"input":"{\"items\":[{\"price\":5},{\"price\":12},{\"price\":30}]}","expression":"{count: length(items), total: sum(items[].price), max: max(items[].price)}","indent":"none"}'
Response 200
{
"result": {
"count": 3,
"total": 47,
"max": 30
},
"type": "object",
"json": "{\"count\":3,\"total\":47,\"max\":30}",
"warnings": []
}
Same call as an MCP tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "json_query",
"arguments": {
"input": "{\"items\":[{\"price\":5},{\"price\":12},{\"price\":30}]}",
"expression": "{count: length(items), total: sum(items[].price), max: max(items[].price)}",
"indent": "none"
}
}
}