Connect an AI assistant (MCP)
Formalized law is delivered over Model Context Protocol: any MCP client — an agent, an editor, your own code — gets a set of tools, each of which returns a computed answer with a proof and provenance. An assistant connected this way does not paraphrase the statute: it asks, receives a document, and relays it. That is the public interface; there is no separate REST API.
The server is public — no key, no registration, no OAuth. Before connecting a client, see what one call returns.
Ask with one call
Section titled “Ask with one call”The question comes from the Labour Code of Kazakhstan: a worker with one child under eighteen months is given a twenty-minute feeding break. Is that break shorter than the legal minimum? The corpus is in Russian, so the names of persons in the example are Russian too; the field names are English.
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_ask", "arguments":{ "kind":"truth", "package":"kz-labour-code", "predicate":"feeding_break_too_short", "args":["Айгуль","Работодатель"], "facts":[ {"predicate":"child_feeding_break_minutes","args":["Айгуль","Работодатель",20]}, {"predicate":"children_under_eighteen_months","args":["Айгуль",1]} ], "legalTime":"2026-09-01"}}}'What is in the call: the kind of question (truth — is this fact
established), the act (package), the question itself (predicate
with its arguments), the facts of the case, and the date the law is
projected on (legalTime). Every one of these is part of the answer, not a
setting.
Read the four things that came back
Section titled “Read the four things that came back”The reply has a human line in content[].text and the same answer as a
document in structuredContent. Four fields carry the answer:
| Field | What it says | In this example |
|---|---|---|
answer.truthStatus |
one of four statuses: TRUE_ONLY, FALSE_ONLY, BOTH, NEITHER |
TRUE_ONLY — established: the break is shorter than the minimum |
rulesApplied |
identifiers of the rules that fired | the rule “for one child — not less than thirty minutes” among them |
provenance |
which act answered, jurisdiction, legalTime, and the articles of the rules that fired |
the Labour Code, KZ, the date you passed |
programHash, caseHash, resultHash (inside provenance) |
the law, the case, and the outcome as hashes | repeat the call with the same inputs and the bytes match |
That is the whole contract: a status, the rules, the address of each provision, and hashes that reproduce the answer. No sentence in the reply was written by a model.
Take the facts away
Section titled “Take the facts away”Run the same call with "facts": []. The status becomes NEITHER — not
established — and the answer carries whyNot: the candidate rules and the
status of each of their premises. It names the fact that was missing. That
is not “no”; it is “the law had nothing to read”. The difference between
NEITHER and FALSE_ONLY is the first thing to learn about these answers:
How to read an answer.
Connect a client
Section titled “Connect a client”The same tools over MCP, for an agent or an editor:
claude mcp add --transport http law-dsl https://mcp.arxo.io/mcpA client configured from a file needs three lines:
{ "mcpServers": { "law-dsl": { "type": "http", "url": "https://mcp.arxo.io/mcp" } } }Transport is Streamable HTTP, stateless: no session is opened,
Mcp-Session-Id is not required. Requests go POST to /mcp; GET
answers 405, a batch answers 400.
From code — npm install @arxo/law-client, a method per tool:
the same from code. An application that executes a
canon itself, without a host, starts from the Quickstart.
The live list of tools is whatever the server returns on tools/list. That
list is the only source of truth about the set. Do not copy a count from
this page. A tool-by-tool reading, with parameters and a minimal call for
each — MCP tool reference.
Find your own question
Section titled “Find your own question”You do not need to know a predicate name in advance. law_search takes a
question in your own words and returns addresses: predicates with
signatures, rules, articles — each with the next call already filled in.
Then law_rules says which facts the rule needs. The working session walks
that path on the same question, from the first search to the proof:
find the norm.
Corpus slices
Section titled “Corpus slices”/mcp is the whole corpus. The same host has slices by legal order: each
is a separate server with its own name, a jurisdiction in every answer, and
a catalogue that does not contain foreign acts.
claude mcp add --transport http law-dsl-kz https://mcp.arxo.io/mcp/kzclaude mcp add --transport http law-dsl-islam https://mcp.arxo.io/mcp/islam| Path | What it sees | Notes |
|---|---|---|
/mcp |
the whole corpus | Kazakhstan is the main jurisdiction; other acts are named as their own |
/mcp/kz |
law of the Republic of Kazakhstan | official calendar; law_ask kind="deadline" works |
/mcp/islam |
Islamic doctrine: fiqh, faraid, the Quran | not the law of a state; no calendar; deadline refuses |
Slices do not carry the author workbench (law_draft_*, law_pin,
law_measure, law_check) or adversarial analytics (law_loophole,
law_amend): they are absent from tools/list, and a direct call refuses
with a reason. The server instructions name what is missing so an agent
does not plan those calls.
A slice is a selector over acts plus the closure of their imports: an act
that a fiqh formalization cites from Kazakhstani law is present in the
islam slice and named in the server instructions as borrowed.
Call order
Section titled “Call order”The tools are not peers: one of them is the entry, and starting with another yields silence that is easy to take for absence of a norm.
| Step | Call | Why |
|---|---|---|
| 1 | law_search |
the question in your own words → addresses: predicates with signatures, rules, articles |
| 2 | law_packages |
exact signatures and constants of the act you found |
| 3 | law_rules |
which facts the rule needs — instead of guessing |
| 4 | law_ask |
the question itself: truth, collect, calc, deadline, positions |
Do not start from the catalogue. Act titles rarely match the words of
the question (“Newton’s laws of motion” do not contain the word “physics”),
and an empty catalogue is a property of search by title, not a conclusion
about the corpus. An empty law_search result is an honest “not
formalized”; inventing predicate names after it is forbidden — the server
will refuse.
A published answer
Section titled “A published answer”A law_ask answer can be published to Arxo Lens and embedded on any page
as a card. The result, its statuses and the snapshot hash come from the
saved answer; “How to cite” on the answer page gives a citation pinned to
that hash.
Grouped by role — again, tools/list is authoritative:
| Group | Tools | What they do |
|---|---|---|
| Discovery | law_search, law_packages, law_rules, law_sources |
find an address, take a signature, read a rule, get official text and its hash |
| Question | law_ask, law_case_ask, law_explain |
ask the law; unfold the proof into the chain “rule ← premises → conclusion” |
| Robustness and bounds | law_argue, law_loophole, law_amend |
did the conclusion stand against counter-arguments; is there a sequence of acts to a goal with no single violation; what minimal amendment yields the target outcome |
| Time and process | law_editions, law_process, law_process_run |
what changed between two legal dates; what stages a process has; how a particular case will run from a log |
| Structure and completeness | law_query, law_measure, law_check, law_screen |
a LawQL query of the formalization; both completeness measures; a compiler check of a .law file; a population screen |
| Draft workbench | law_pin, law_draft_check, law_draft_eval, law_draft_verbalize, law_draft_differential, law_draft_impact |
pin document bytes and take a draft act through layers of checking |
| Passports and reports | law_passport, law_report |
read a package passport; file a report that the formalization diverges from the source |
| Published answers | law_prepare_answer, law_publish_answer, law_revoke_answer |
freeze, publish, and revoke a reproducible HTML answer |
The workbench is a sandbox. Drafts are not law, they do not enter the
corpus, and they are not visible to law_ask. That contour is for whoever
formalizes an act, not for whoever asks the law.
Limits
Section titled “Limits”| What | Value | Why |
|---|---|---|
| Rate | 3 requests per second per IP, burst 10 | an open computer; law_draft_* execute submitted drafts |
| Request body | 1 MB | mirror of the server’s own body limit |
| Timeout | 120 s per request | a pathological request refuses with an honest error instead of computing for minutes |
Exceeding the rate yields 429, not a silent queue. Limits sit in front
of the server, on the transport layer, and do not affect the semantics of
an answer: the same question through your own deployment yields the same
bytes.
The tools mutate nothing: the engines are deterministic, file input is isolated, execution has its own limits. Openness costs only server CPU — hence the limits, and the absence of registration.
Your own deployment
Section titled “Your own deployment”The public server is convenient, not mandatory. The same code runs locally.
The public host is a Rust binary (law-mcp-server); Python is no longer
the production MCP host.
cargo run --quiet --manifest-path engines/lawc/Cargo.toml \ --package law-mcp --bin law-mcp-serverThat is stdio transport — exactly what .mcp.json in this repository
declares. The network variant adds -- --http, default
127.0.0.1:8722. Binding off loopback requires an explicit decision:
either LAW_MCP_TOKEN (Bearer on every request) or LAW_MCP_PUBLIC=1.
A public address without authentication does not come up by silent
configuration — that is checked, not implied.
What to do with the answer
Section titled “What to do with the answer”An MCP answer is not text to paraphrase. It is a document with fields. How to read it — How to read an answer. Short, for an agent:
- “not established” and an error are passed to the user as they are and are not replaced with general knowledge of another country’s law;
- on “not established”, look at
whyNot— it names the fact that was missing; - jurisdiction and legal time are named in the answer; do not paraphrase an answer without them.
Writing .law packages is a different door: Connect: the editor.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.