AI agents¶
An AI agent that has to read or move data across a polyglot estate is the
reader iq is already shaped for. iq offers one binary and one language over
ten backends and their dump files. It is JSON in and JSON out (--jsonl,
--compact, -M, --error.format json), so nothing has to be scraped out of a
native shell's formatting.
--explain is a dry run that never connects, so a plan can be inspected before
a single byte moves. --dry-run reports the effect of a write without doing
it.
The destructive commands are capability-gated. As a result, one against a backend that does not implement the port fails with a clear message instead of emulating it. Every error is redacted, so a password in a source URI never reaches a transcript.
Queries are read-only, and a filter that must materialize a whole keyspace is
refused unless --unbounded is passed.
Skill¶
iq ships an Agent Skill, a single Markdown file,
skills/iq/SKILL.md,
that any agent reading the Agent Skills format can load.
It teaches the workflow rather than the flag list:
- Finding the source before guessing at one
--explainbefore every scan--dry-runbefore every write- The machine-readable output flags and the JSON error shape
- Which filters need
--unboundedand why - The rules around writes, so
--replaceandiq data clear,iq data dropandiq data deleterun only on an explicit instruction.
The per-backend detail stays in iq --help, man iq and this site, so the
skill stays small enough to load beside the task.
Install it with the cross-agent installer. The installer fetches once into
~/.agents/skills and links it into every agent's skills directory it detects:
With the GitHub CLI (2.90 or newer):
Without either installer, copy the raw file into wherever the agent in use looks for skills:
mkdir -p ~/.claude/skills/iq
curl -fsSL https://raw.githubusercontent.com/zsltg/iq/main/skills/iq/SKILL.md \
-o ~/.claude/skills/iq/SKILL.md
MCP server¶
iq mcp serves the same query core as a
Model Context Protocol server, speaking
JSON-RPC over stdin and stdout.
It is the CLI's operations as tools, over the same saved sources and the same engine. As a result, an agent that cannot run shell commands still gets the whole command set. It targets the 2026-07-28 specification revision and negotiates back to 2025-11-25 for an older client.
Client configuration¶
The server is the binary itself, so a client only needs the command. The
inherited --timeout defaults to 5 seconds, which is short for a scan, so pass
a longer one. Every example below registers the same server, iq mcp --timeout
30s, under the name iq.
Codex CLI (the -- separates the server command
from Codex's own options. The same entry can be written by hand as
[mcp_servers.iq] in ~/.codex/config.toml):
Gemini CLI (the -- matters here too. A --timeout
before it is Gemini's own connection timeout in milliseconds, not iq's):
Cursor (.cursor/mcp.json in the project, or
~/.cursor/mcp.json for every project), Cline
(~/.cline/mcp.json for the CLI, the MCP Servers panel's Configure tab in the
IDE extensions), Antigravity
(~/.gemini/config/mcp_config.json, or .agents/mcp_config.json in the
workspace) and the Gemini CLI settings file (~/.gemini/settings.json) all
take the same mcpServers block:
Copilot in VS Code (.vscode/mcp.json
in the workspace, or the user profile file behind the
MCP: Open User Configuration command) names the map servers and wants the
transport spelled out:
OpenCode (opencode.json) names it mcp, calls a stdio
server local and takes the command as one array:
{
"mcp": {
"iq": {
"type": "local",
"command": ["iq", "mcp", "--timeout", "30s"],
"enabled": true
}
}
}
pi.dev ships no MCP client by design. It expects a CLI plus
a skill, which is exactly what iq and the Skill above are. Install
the skill, and pi drives the binary directly.
Any other client that takes a stdio server block needs the same two facts: the
command iq and the arguments mcp --timeout 30s.
The server inherits the saved sources and the keyring of whoever starts it. Thus, point an agent at a config with only the sources it is allowed to use, not your own:
Register that config's sources with the same iq add --config
~/.config/iq/agent.toml ... you use anywhere else.
Safety model¶
- Read-only by default. The write, exec and lifecycle tools exist only
behind
--allow. A tool that is not allowed is never registered. It is absent fromtools/listand unknown to the server, so a client cannot call it by name.--allow writesaddsiq_insert, and--allow execaddsiq_exec.--allow destructiveaddsiq_data_clear,iq_data_dropandiq_data_delete(and permitsiq_insert'sreplace). The flag is repeatable. --allow execis broad.iq_execforwards native commands verbatim, with no preview and no confirmation. With--allow exec, the agent can do anything that the database account can do, also write and delete. Give the agent a read-only database user, unless it must write.- Every result is bounded.
--max-items(200) and--max-bytes(256 KiB, roughly 64k tokens) are hard caps. A per-callmax_itemsormax_bytescan only lower them, never raise them. A capped result comes back withtruncated: truerather than an error, so the agent knows there was more. - Every call is bounded. The inherited
--timeoutbounds each call, and a per-calltimeoutcan only shorten it. - Confirmations. A real call to
iq_data_clear,iq_data_drop,iq_data_deleteoriq_insert'sreplacewithoutconfirm: truedoes not proceed.iq_execasks for no confirmation. Where the client can ask its user, the server returns an input-required result carrying the question. The client then retries the call with the answer. Where it cannot, the call comes back refused, naming what to pass. The CLI's--forcehas no counterpart here. A confirmed call is the confirmation. iq_explainfirst. It never connects, and it names the route and the pushed-down conjuncts, so a plan can be read before a scan runs.- Errors are redacted. Every failure is a tool result carrying the CLI's
{"error":{"message","causes"}}document with every connection URI redacted. As a result, no raw driver error and no stored password reaches a transcript.
Tools¶
readOnly marks a tool that never modifies anything. destructive marks one
that can. Every tool declares openWorldHint: false. The sources are a closed,
configured set. The annotations are display hints, not the gate. --allow is
the gate.
| Tool | Allowed by | Annotations | What it does |
|---|---|---|---|
iq_sources |
always | readOnly, idempotent | The handles this server can access, with each URI's password redacted |
iq_ping |
always | readOnly, idempotent | Round-trip one cheap backend command and report the time |
iq_explain |
always | readOnly, idempotent | The access plan for a filter, without connecting |
iq_query |
always | readOnly, idempotent | Run a jq filter. Returns {items, count, truncated} |
iq_inspect |
always | readOnly, idempotent | A backend's native introspection, optionally narrowed by only |
iq_schema |
always | readOnly, idempotent | A draft 2020-12 JSON Schema inferred from a sample |
iq_diff |
always | readOnly, idempotent | Compare two sources by data, stats, or inferred schema |
iq_insert |
--allow writes |
destructive, idempotent | Copy items into another source. no_overwrite defaults to true |
iq_exec |
--allow exec |
destructive | Forward a command to the backend verbatim |
iq_data_clear |
--allow destructive |
destructive, idempotent | Empty a container, keeping it |
iq_data_drop |
--allow destructive |
destructive, idempotent | Remove a container entirely |
iq_data_delete |
--allow destructive |
destructive, idempotent | Remove named keys, keeping the container |
Every tool returns structuredContent against a declared outputSchema, plus
the same JSON in a text block for a client that reads only unstructured content.
tools/list is sorted by name and cacheable for an hour with a private scope,
because only a restart can change it.
Limits¶
- stdio only. There is no HTTP transport, so the server is a child process of its client and reachable by nothing else.
- The tool set is fixed at process start. Changing
--allowmeans restarting the server. - The server advertises the
toolscapability alone. Prompts, resources, sampling, roots and protocol-level logging are not implemented. The last three are deprecated as of the 2026-07-28 revision. Diagnostics go to stderr, or to the--logfile, never to stdout, which carries the protocol and nothing else. - A long dump is not a good tool result. Cap it, or run the CLI and read the file.
The whole manual is also served as one file, llms-full.txt, so an agent can read every page of this site in a single fetch.