MCP tool reference
There is no separate REST API for Arxo. The only public interface is the Model Context Protocol — Connect an AI assistant (MCP) covers transport, corpus slices, and call order. This page reads through the same tools one at a time: what each one is for, what it takes, a minimal call, what comes back, and where it typically refuses.
The live tools/list response of the server is the only source of
truth about the set — this page is a reading aid built from it, not a
substitute for it. A tool’s description and parameters can change between
formalization releases; if this page and a live call disagree, the live
call wins.
How the calls on this page read
Section titled “How the calls on this page read”Every tool is called the same way, over JSON-RPC tools/call, POST to
/mcp. The full envelope — headers, the JSON-RPC wrapper — is in
Connect an AI assistant (MCP), “Ask with one call”. To keep this page short, each
tool below shows only the arguments object of params. For example
{"query": "feeding break"}is short for
curl -s https://mcp.arxo.io/mcp \ -H 'content-type: application/json' \ -H 'accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ "name":"law_search","arguments":{"query":"feeding break"}}}'Every reply carries a human line in content[].text and the same answer as
a document in structuredContent — how to read the four fields that matter
most (truthStatus, rulesApplied, provenance, the hashes) is
How to read an answer.
Discovery
Section titled “Discovery”Where a question starts: turn words into addresses, then take exact signatures and the official text behind them.
law_search
Section titled “law_search”Semantic search over formalized law: a question or concept in your own words returns candidates with addresses — predicates with signatures, rules, source fragments. This is the discovery layer, not an answer: it does not establish a fact or a norm, and text similarity is not applicability. Ranking is a deterministic lexical embedder, not a language model.
- Parameters:
query(required, your words) ·kinds(narrow topackage/predicate/rule/norm/constraint/fragment) ·package(search inside one act only) ·limit(default 8, max 25). - Call:
{"query": "feeding break for a nursing mother"} - Response: ranked candidates, each with
next— the following call already filled in (usuallylaw_packagesorlaw_rules). - Typical limits: an empty result is an honest “not formalized”, not a server fault — do not invent a predicate name after it.
- Used in: Find the norm.
law_packages
Section titled “law_packages”The catalogue of formalized law: acts, predicates with signatures, and
coverage bounds. This is where predicate names come from — do not
guess them. Three modes, all paginated: no arguments gives an overview (one
line per act); package gives the full signature list of one act;
query filters signatures, labels, and constants across every act by a
substring. package together with catalog lists a further inventory of
one act: its declared question catalogue, its norms, or its constants.
- Parameters:
package(act key) ·query(substring filter) ·catalog(questions/norms/constants, only withpackage) ·limit,offset(pagination; the unit is named bypageUnitin the reply). - Call:
{"package": "kz-labour-code"} - Response: signatures with parameter types, constants, and — with
catalog: "questions"— a template per supported question, each marked with what it does not answer and why. - Typical limits: do not start here to find an act — a title rarely
matches the words of a question; start from
law_search. - Used in: Find the norm.
law_rules
Section titled “law_rules”Verbalized rules: exactly how a predicate is derived — premises and their
source articles. Call this before sending facts to law_ask: a rule
names the facts it needs, so there is nothing to guess. package lists a
table of contents of an act’s rules; predicate gives the full text of the
rules that derive it.
- Parameters:
predicate(rules deriving it) ·package(all rules of an act, paginated) ·lang(verbalization language, defaultru) ·limit,offset. - Call:
{"predicate": "feeding_break_too_short"} - Response: each rule’s premises, its source article, and its strength (strict or defeasible).
- Used in: Read the rules.
law_sources
Section titled “law_sources”The official text behind a norm: the source law_ask and law_rules cite.
By default, short excerpts (view: "summary"); view: "full" returns
exact ranges of the pinned text, addressed by Unicode character offsets,
with a contentHash of the full source (not of the excerpt).
- Parameters:
package(all fragments of an act) ·fragment(aStableIdfromlaw_search/law_rules) ·view(summary/full) ·textOffset,textLimit,contentHash(continuing afullread) ·limit,offset. - Call:
{"fragment": "urn:...#fragment/Article-100"} - Response: the excerpt or exact text range, the hash that proves it
matches the pinned publication, and — in
summary— the address of the full text. - Used in: Read the rules, Why this can be trusted.
Question
Section titled “Question”The law, asked directly, with the chain that produced the answer.
law_ask
Section titled “law_ask”The core call: ask formalized law a question. Before the first call,
get predicate names from law_search or law_packages — an invented name
is refused. Five kinds: truth (is a fact established — one of four
statuses), collect (list records matching a pattern), calc (compute a
quantity), deadline (a period’s expiry on the official calendar),
positions (which duties arose and their status). “Not established” and a
tool error are the answer; do not replace them with general knowledge
of another country’s law.
- Parameters (required):
predicate. Parameters (usual):kind(defaulttruth) ·package·args·facts([{predicate, args, negated?}]) ·legalTime. Kind-specific:calc(an expression tree) ·days,after,deadlinePolicy(deadline) ·proof(attach a proof graph, feedslaw_explain). - Call: the example from Connect an AI assistant (MCP) —
{"kind":"truth","package":"kz-labour-code","predicate":"feeding_break_too_short","args":["Айгуль","Работодатель"],"facts":[...],"legalTime":"2026-09-01"} - Response: the status,
rulesApplied,provenancewith hashes, and — onNEITHER—whyNot, naming the missing premise. - Typical limits: a name the corpus does not know is refused, not guessed at.
- Used in: Connect an AI assistant (MCP), Ask the law, Reading silence.
law_case_ask
Section titled “law_case_ask”Run a case already assembled as its own package (a “case package”): a
fixed set of facts and pinned dependencies, asked through a declared
case/query, or an evaluate expression. Preparation failures (missing
pins, an unregistered case) come back as a coded error, not a silent empty
answer.
- Parameters (required):
package(path to the case package). Usual:case(name, optional with one case) ·query(a JSON question) orevaluate+queryId(a.lawtest-style expression). - Call:
{"package": "examples/labour-cases/feeding-break", "queryId": "too-short"} - Response: the same evaluation document as
law_ask, computed over the case’s own fixed snapshot. - Typical limits: for a one-off question about the general corpus, use
law_askinstead — this tool is for a pre-registered case package.
law_explain
Section titled “law_explain”Unfold a law_ask answer’s proof into a chain: rule ← premises → conclusion.
The compact form re-runs the computation from question +
resultHash + codeHash and refuses loudly if anything changed; or pass
the evaluation document from law_ask(proof: true) directly.
- Parameters: one of
evaluation(a full evaluation document) /question+resultHash+codeHash/answerResource(a saved compact answer’sfullAnswer.uri). Optional:nodeId(one node and its premises only, capped at 24 KB). - Call:
{"evaluation": {"...": "..."}} - Response: the proof tree, or a refusal if replay does not match the hashes you supplied.
- Used in: Explain and doubt.
Robustness and bounds
Section titled “Robustness and bounds”Whether a conclusion survives counter-argument, and how far the act can be pushed.
law_argue
Section titled “law_argue”How robust is a conclusion: an argumentation map over the whole act (not
just the rules that fired in a plain law_ask), including chains that lost.
Four verdicts: SKEPTICALLY_ACCEPTED (survives every attack),
CREDULOUSLY_ACCEPTED (defensible — there is a position for and against),
REJECTED, NO_ARGUMENT.
- Parameters (required):
predicate. Usual:args,facts,package,legalTime·limits(caps on the search:maxArguments,maxExtensions,maxUndecided). - Call:
{"predicate": "feeding_break_too_short", "facts": [...]} - Response: the verdict and the map of attacking/defending arguments.
- Typical limits: a large act can refuse on its argument cap — narrow
factsor raiselimits.maxArguments.
law_loophole
Section titled “law_loophole”Bounded search (dates and action sequences) for a path to a target outcome
on which no step produces a violated duty. “Not found” is a statement
inside the given depth and budget, not about the act in general; hitting a
cap is reported explicitly (SPACE-TRUNCATED, BUDGET-EXHAUSTED), never
silently.
- Parameters (required):
predicate(the goal). Usual:args,facts,package,legalTime,expect(defaultTRUE_ONLY) ·depth,alphabetCap,datesCap,budget(search bounds). - Call:
{"predicate": "some_goal", "depth": 3} - Response: a found sequence with its dates, or an explicit not-found verdict naming which cap ended the search.
law_amend
Section titled “law_amend”The minimal mechanical edit to an act (drop a rule, drop a priority, narrow a window, add a priority, exclude one enum value) that yields a target outcome without moving a named list of regression questions on the same act. A candidate is accepted by execution, not by claim — the regression is checked byte-for-byte.
- Parameters (required):
predicate(the target question). Usual:args,facts,expect,package,legalTime·keep(regression questions that must not move) ·maxEdits(default 2),budget. - Call:
{"predicate": "some_goal", "expect": "TRUE_ONLY", "keep": [...]} - Response: the minimal edit found, with
manifest.autoRegressionproving the kept questions held. - Typical limits: it enumerates mechanical edits only — it does not author a new rule.
Time and process
Section titled “Time and process”What changed between two dates, and how one case moves through a procedure.
law_editions
Section titled “law_editions”What changed in an act between two legal dates: edition state, dating of
norms, and a semantic diff between the two projections. NOT_DATED means
there was nothing to date by, not “nothing changed”. For the outcome of one
question on one date, use law_ask with legalTime instead.
- Parameters (required):
package,dateA,dateB. - Call:
{"package": "kz-labour-code", "dateA": "2025-01-01", "dateB": "2026-09-01"} - Response: the diff between the two dates’ projections, article by article.
law_process
Section titled “law_process”The stages a formalized process has, and whether its graph has a structural
defect (an unreachable stage, a dead transition, a transition that leads
nowhere). Without package, lists which acts have a process formalized at
all. A stage without an outgoing transition is named but not flagged as a
defect — the formalization does not say whether it is meant to be terminal.
- Parameters:
package(optional — omit for the list of acts with a process). - Call:
{"package": "kz-tender-procedure"} - Response: stages, transitions, and their conditions, plus any detected structural defect.
law_process_run
Section titled “law_process_run”How one concrete case moves through a procedure: a log of
{date, attempt?, facts?} steps, each evaluated under the law of its own
date. The reply says which stages were entered, which attempted
transition did not produce its legal effect and why, which duties are
violated, and what is available next.
- Parameters (required):
package,instance(what is going through the procedure),steps(the log). Usual:legalTime,procedure,probeTime(to inspect the next available steps). - Call:
{"package": "kz-tender-procedure", "instance": "lot-42", "steps": [{"date": "2026-01-10", "facts": [...]}]} - Response: stages entered, failed attempts and why, active violations, and what remains to be done.
Structure and completeness
Section titled “Structure and completeness”Querying the formalization itself, measuring how much of an act is executable, and checking a file.
law_query
Section titled “law_query”A deterministic LawQL query over the compiled intermediate representation
(CLIR): tables like nodes, edges, rules, norms, positions,
labels, imports. This is orchestration over the existing engine, not a
new source of legal semantics.
- Parameters (required):
query(inline LawQL, or aquery …over "pkg"block). Usual:corpus(apackage.nameglob for a structural snapshot) ·rowLimit(default 20, max 5000),rowOffset·case(forquery … overwith a case in place of a case clause). - Call:
{"query": "from n in nodes where n.kind == \"rule\" select n.id as id", "corpus": "kz-labour-code"} - Response: matching rows, with
warnings: ["ROWS_TRUNCATED"]and anextcursor if the page was cut. - Typical limits: row truncation is reported explicitly, never silent.
law_measure
Section titled “law_measure”Both completeness measures at once: article coverage (by convention —
“Article N”, “N-бап” — and markers of executable content) and depth
(EXECUTABLE/ANCHORED/SOURCE_ONLY per article, with byte coverage of
the pinned text). Neither measure alone is enough: “every article is
covered” and “nothing computes” can both be true together. Two input
modes: a draft (source + document) or a corpus package (package,
using the committed CLIR and pinned documents).
- Parameters:
package(corpus act) — orsource+document+declaration(a draft). - Call:
{"package": "kz-labour-code"} - Response: per-document article coverage and per-article depth.
- Used in: Package passports.
law_check
Section titled “law_check”Compile a .law file from the repository: syntax, symbol declarations,
arity, types, and the hashes of official texts it cites.
- Parameters (required):
path(repository-relative). - Call:
{"path": "packs/examples/tutorial/archive/archive.law"} - Response: compiler diagnostics, or a clean pass.
law_screen
Section titled “law_screen”Build a necessary-condition superset for pre-screening rows of an external
data source. This is not a legal answer and not SQL — it is a
typed tree plus a manifest of extensions to TRUE. Every row that passes
still has to be fully evaluated by the engine (law_ask) with its own
proof, on the same data snapshot.
- Parameters (required):
package,goal(aStableIdor short name),binding(alaw.screen.binding/0.1artifact),sourceSchemaContentHash. Usual:legalTime. - Call:
{"package": "kz-labour-code", "goal": "feeding_break_too_short", "binding": {"...": "..."}, "sourceSchemaContentHash": "sha256:..."} - Response: the screening tree and manifest; rows still need
law_ask. - Typical limits: the hash in
bindingmust match the source schema exactly, or the call refuses loudly.
Draft workbench
Section titled “Draft workbench”Author-facing tools for taking a .law draft from pinned bytes to a
checked, measured, differential-tested candidate. Drafts are a sandbox:
they never become law, never enter the corpus, and are invisible to
law_ask.
law_pin
Section titled “law_pin”Phase 0: pin a document’s bytes — sha256 and a ready-made publication
block. No network access — the client brings the document; retrieved_at
is passed as an argument, the server does not invent a time.
- Parameters:
textorhtml(the document) ·uri,local_path,retrieved_at. - Call:
{"text": "...", "uri": "https://...", "retrieved_at": "2026-09-22T00:00:00Z"} - Response: the hash and a publication block ready for
sources.law.
law_draft_check
Section titled “law_draft_check”Layers 1–2: whether a draft parses, and — if it parses — whether every node survives lowering into executable form. A node that drops out is a verdict, not a log line: “a rule that can never fire is indistinguishable from silence”.
- Parameters (required):
source(the draft text). Usual:sources(pinned companion files, for source-citation checks). - Call:
{"source": "package tutorial.archive version \"0.1.0\" { ... }"} - Response: parse result, dropped nodes (if any), citation checks.
law_draft_eval
Section titled “law_draft_eval”Layer 3: execute the draft in a sandbox. A clean law_draft_check does not
mean the rules derive anything — not_known, classical negation in an open
world, and arithmetic kind errors only show up on execution. kind: "positions" reports duty/power statuses instead of a plain predicate.
- Parameters (required):
source. Usual:predicate,args,facts,kind(truth/collect/positions),legalTime,sources. - Call:
{"source": "...", "predicate": "eligible", "facts": [...]} - Response: the computed result and any issue above
infoseverity, including dead rules named individually.
law_draft_verbalize
Section titled “law_draft_verbalize”Layer 5: verbalize the draft — a side-by-side “official text ↔ deterministic sentence” pair for meaning review. The server does not judge whether the formalization is correct; it makes the comparison possible, and names constructs it cannot verbalize rather than skipping them.
- Parameters (required):
source. Usual:sources. - Call:
{"source": "..."} - Response: paired official-text and generated-sentence entries per rule.
law_draft_differential
Section titled “law_draft_differential”The final gate: ask the same question of the draft through both implementations (the Python oracle and the Rust engine) and compare the canonical output bytes. A divergence is a blocker that must be classified (a defect in one implementation or in the specification) — never silently patched over.
- Parameters (required):
source,predicate. Usual:args,facts,legalTime,sources. - Call:
{"source": "...", "predicate": "eligible", "facts": [...]} - Response: a byte-identical result from both engines, or a named divergence.
law_draft_impact
Section titled “law_draft_impact”What a draft changes against a corpus package: a semantic diff (norms
added, dropped, changed) and coverage targets. The draft must declare the
same package as the comparison base — this tool compares editions of
one act, not two different acts. It does not check whether the draft’s
rules fire on a scenario; that is law_draft_eval.
- Parameters (required):
package(comparison base),source(the new edition’s draft). Usual:sources. - Call:
{"package": "kz-labour-code", "source": "..."} - Response: the semantic diff between the draft and the corpus edition.
Passports and reports
Section titled “Passports and reports”What is released, under what name; and a channel to flag a mismatch with the source.
law_passport
Section titled “law_passport”The passport of an exact release: purpose, interface, bounds, checks, and
performance. The reports section carries the history of measurements,
including failures. Paginated by JSON Pointer, with next continuing the
read.
- Parameters (required):
name,version,contentHash. Usual:sections(narrow to one or more ofdescription,interface,semantics,sources,composition,dependencies,checks,evidence,reports) ·limit,offset. - Call:
{"name": "kz-labour-code", "version": "0.3.0", "contentHash": "sha256:..."} - Response: the requested passport sections.
- Used in: Package passports.
law_report
Section titled “law_report”Report a divergence between the formalization and its source: the answer contradicts the pinned text, a norm is not expressed as a rule, a label disagrees with the text, or an address does not resolve. This is a triage hypothesis, not a correction — it does not change the law, does not appear in other tools’ answers, and “not derived” does not become “derived” because a report was filed.
- Parameters (required):
package,category(missing-norm/wrong-outcome/label-mismatch/broken-address/source-text/other),expected,observed. Usual:fragment(aStableId),predicate,callId(theX-Law-Call-Idof the disputed answer). - Call:
{"package": "kz-labour-code", "category": "wrong-outcome", "expected": "...", "observed": "..."} - Response: confirmation that the report was logged for triage.
Published answers
Section titled “Published answers”Freeze a set of prior law_ask/law_process_run calls into a reproducible,
shareable page.
law_prepare_answer
Section titled “law_prepare_answer”By explicit user request, replay 1–12 prior law_ask or law_process_run
calls, strictly verify their replayControl, and prepare an unpublished,
frozen document for 24 hours. The client never hands over a pre-computed
answer — the server only accepts what its own fresh execution produces; any
mismatch in input, rights, resource, MCP code, or result rejects the whole
document.
- Parameters (required):
question· one ofcalculations(withrequest+replayControlper entry) orproducerRuns. Usual:assistant(a summary and per-calculation explanations),documentVersion,language. - Response: a
preparationIdforlaw_publish_answer, or a rejection naming what did not replay.
law_publish_answer
Section titled “law_publish_answer”Publish a prepared document. Calling it again with the same
preparationId is idempotent — it returns the same URL and the same
separate revoke secret.
- Parameters (required):
preparationId. - Response: the public URL and a revoke secret (shown once — store it to be able to revoke later).
law_revoke_answer
Section titled “law_revoke_answer”Revoke a published document using its separate secret. The public id alone grants no management rights; revocation closes the HTML page, the API, and the download.
- Parameters (required):
publicId,revokeSecret. - Response: confirmation that the page, API, and download are closed.
law_answer_capabilities
Section titled “law_answer_capabilities”A machine-readable matrix of which answer producers, replay/projection
checks, profiles, limits, and confirming contract tests are actually
installed on this server. declared_only marks a schema without an
executable witness behind it yet.
- Parameters: none.
- Response: the capability matrix.
law_capture_answer
Section titled “law_capture_answer”Run a registered producer and capture a producerControl/0.2 record for a
later verifiable law_prepare_answer call. The producer must be one of the
names the server’s own registry lists — it is not an arbitrary plugin
point.
- Parameters (required):
producer(a registered name),request. - Response: the captured control record for use in
law_prepare_answer.
What is not here
Section titled “What is not here”There is no separate REST endpoint per tool. Every call above goes
through the same JSON-RPC tools/call method on /mcp — see
Connect an AI assistant (MCP) for the transport, rate limits, and corpus
slices where some of these tools (the draft workbench and the adversarial
analytics group) are absent entirely.
This page does not replace tools/list. Parameter names, required
fields, and even the presence of a tool can change between releases; the
server’s own answer to tools/list is what an agent should read
programmatically, not this page.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.