jsonloupe
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| load_docA | Open a JSON document and return its size and top-level shape. Accepts a file path or inline text, and transparently decodes Zstd, Base64-Zstd and PostgreSQL bytea (\x…) payloads. Malformed JSON is auto-repaired and flagged. Returns a docId (d1, d2, …) that every other tool takes. The document itself is never returned — read it with get_schema, run_query, profile or sample instead. Prefer path for an existing or large document. For a single question, skip this step: those tools also take filePath. |
| inspectA | First step toward a spreadsheet: find the repeatable arrays and object maps in a loaded document that can become linked tables. Returns table anchors, row counts, fields, types, and deterministic format suggestions; document values are not returned. Next, draft_spec writes a mapping and convert writes the file. For field names and types use get_schema, for coverage and statistics profile, and for real values sample. |
| draft_specA | Draft a reviewable converter spec for a loaded document, usually after inspect shows its tables. This does not convert anything: pass the spec to convert, inline or as the file you saved. Save it to outPath for human editing, or omit outPath to return the JSON under the response cap; an existing outPath is refused unless overwrite=true. format picks one .xlsx workbook or a .zip of CSVs; baseDate gives time-only columns a date. |
| convertA | Write a loaded document out as linked tables — one .xlsx workbook, or a .zip of CSVs — by running a frozen converter spec deterministically. The spec comes from draft_spec, reviewed or edited: pass it inline as spec or as a file in specPath, exactly one of the two. format overrides the format the spec names. Returns row/skipped/warning counts, never the output rows. An existing outPath is refused unless overwrite=true. For one query's result as a single CSV or JSONL file, use export_result instead. |
| get_schemaA | Field names and types of the document — never values. With no path, describes the whole document; with a path, describes just what it selects, merged across matches (so $.tasks[*] describes an element, not the first element). Array shapes are inferred from up to 30 elements; use profile for exact coverage/counts. Start here: it is how you learn which paths run_query can use. For one question, pass filePath directly; it opens the file and returns a reusable docId in the same call. A path that matches nothing returns an error naming that path. |
| run_queryA | Use this instead of ad-hoc Python for JSON counts, filtered exact sums/averages/min/max, composite groups, distinct values, top/bottom ranking, and field projection. It scans server-side and returns only the bounded answer. Pass filePath for a one-call answer, or docId to reuse an open document. For field names and types use get_schema; for coverage and statistics of many fields at once, profile; to judge counts against expectations, run_checks. Grammar (a JSONPath subset with aggregation pipes): Paths: $.key $['odd key'] $[3] $[-1] $[1:5] $.arr[] $..key (recursive)
A [...] step attaches directly to what precedes it: $['odd key'], $.a['b c'] — never $.['odd key'].
Any key that is not a plain identifier (space, '-', '.') must be bracketed: $['line-items'], @['unit price'].
$.arr is the array itself; $.arr[] is its elements — $.orders[] | count counts the orders, $.orders | count is 1.
Predicates filter the CHILDREN of the current node: $.tasks[?(...)]
A [?(...)] step already yields the matched elements — never follow it with [].
Operators: == != > >= < <= (numbers and strings)
Boolean: && || ! Grouping: ( ) — there is no !~; negate with !( … )
Strings: @.name contains 'x' | startsWith | endsWith | @.name =~ /safe-regex/i
Membership: @.status in ['A','B'] Arrays: @.tags contains 'x'
Set: @.field — true unless the key is missing, null or false ('' and 0 count as set)
Explicit: @.field present (key exists) | missing (no key) | isNull (value is null)
Fields compare to fields: @.capacity.used > @.capacity.max
A predicate holds one level only: no predicate inside a predicate, no $ path inside it
Pipes: append AT MOST ONE, at the very end. Pipes never chain — Examples: "how many tasks have no route" → $.tasks[?(!@.routeId)] | count "how many orders are there" → $.orders[] | count "failed tasks by reason" → $.tasks[?(@.status =~ /^failed$/i)] | group(@.failureReason) "tasks that are not cancelled" → $.tasks[?(!(@.status =~ /^cancelled$/i))] "top delayed tasks" → $.tasks[] | top(@.delayMinutes, @.id, @.status) "highest value orders showing just their id and amount" → $.orders[] | top(@.amount, @.id) "all statuses that appear" → $..status | distinct "ids and etas of pending tasks" → $.tasks[?(@.status =~ /^pending$/i)] | pluck(@.id, @.eta) "total line value of failed orders" → $.orders[?(@.status =~ /^failed$/i)].items[].lineTotal | sum "sum of the line-total column" → $['line-items'][*] | sum(@['line-total']) "the run id" → $['meta data']['run id'] "tasks outside india" → $.tasks[?(@.loc.lat < 8 || @.loc.lat > 37)] Matches come back as path + preview; use |
| profileA | Profile one or more fields across every selected record in one server-side scan; this replaces ad-hoc Python loops for discovering or summarizing unfamiliar JSON fields. Pass filePath for a one-call answer, or docId to reuse an open document. Returns present/missing/null counts, type counts, distinct count, exact numeric sum/min/max/average, lengths, and top values. Use fields like "status" or "capacity.used" relative to each selected record; omit fields to auto-discover up to 20 fields on selected records or profile selected scalar values. For a filtered count or a group breakdown use run_query; for whole records use sample. |
| sampleA | Read n real values at a path, exactly as they were parsed (int64 and decimal digits intact). A path that selects one container samples its children; a path that selects many nodes samples those nodes. Pass filePath for a one-call sample, or docId to reuse an open document. Use it to see what records really hold; to count or aggregate use run_query, for statistics profile, and for names and types get_schema. |
| diff_docsA | Compare two documents opened with load_doc and return change counts plus the first 25 changes. There is no filePath shortcut: load both first. docIdA is the older side: additions and removals read A → B. Give keySpec to align arrays by identity (e.g. "id,orderId") so reordered elements are not reported as wholesale changes. |
| export_csvA | The CSV-only shortcut for export_result: run a query and write its complete table to a CSV file (RFC 4180, exact digits, formula-injection safe). Returns only the path, row count and byte size — the rows themselves never enter the conversation. The query must produce a table: use |
| export_resultA | Write every query match to a local file without sending the data through the conversation. JSONL accepts bare filtered matches and preserves nested values; CSV requires |
| run_checksA | Run deterministic checks — a query plus the count it expects — against a document; one verdict per check: pass, fail, or inconclusive (a | group or | distinct hit its 100,000-value cap, so the count is only a lower bound; never reported as a pass). Pass playbookPath for a jsonloupe playbook file, or checks inline. Playbook functions are JavaScript and are never run here. Expectations: {"type":"no-matches"}, {"type":"at-least-one"}, {"type":"exact-count","count":N}, {"type":"at-most","count":N}, {"type":"at-least","count":N}, {"type":"between","min":M,"max":N}. A check counts matches (groups/distinct values for | group / | distinct); value pipes like | sum are refused. A document that is not valid JSON is refused unless allowRepair is true. Failed and inconclusive checks list their first matched paths. Pass filePath for a one-call answer, or docId to reuse an open document. Use it to gate a document on counts you expect; for an open-ended count or breakdown use run_query. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 12 tools
Most tools target distinct operations (load, query, checks, profile, sample, export, convert), and descriptions explicitly cross-reference alternatives. However, get_schema/inspect/profile/sample/run_query have some overlapping schema/value/statistics territory, and export_csv is a near-duplicate shortcut of export_result, so an agent must read carefully to choose.
All names use snake_case and are readable, with most following verb_noun (load_doc, run_query, get_schema, export_result). Occasional single-verb/noun names (inspect, convert, profile, sample) are minor deviations but still understandable.
12 tools is appropriate for a JSON analysis/query/conversion/export surface; each capability (load, schema, query, checks, profile, sample, export, diff, conversion) has a clear role. No excessive duplication or trivial single-tool thinness.
The surface covers loading, schema discovery, querying, validation checks, profiling, sampling, diffing, exporting, and table conversion. For an analysis-focused JSON tool, this provides complete lifecycle coverage without obvious dead ends.