Skip to content

Working session: the same from code

Everything done by hand on the previous pages is tool calls over the MCP protocol. From code they are made by the client @arxo/law-client: it is transport only, with no engine and no legal semantics. Answers about the law come from the server, computation is on the server, the client computes nothing.

Terminal window
npm install @arxo/law-client

ESM-only, any runtime with fetch and crypto.subtle. No key:

import { createMcpClient } from '@arxo/law-client/mcp';
const client = createMcpClient(); // public server, whole corpus

Slices by legal order are the same client with another address: a slice has its own catalogue and its own jurisdiction in every answer, and some tools are not served in it at all. So the set of tools is asked of the live server, not taken from a table in the client:

const tools = await client.listTools();

The client has a method per tool plus a general call(name, args). The session from the previous pages in full:

const found = await client.law_search({
query: 'перерыв для кормления ребёнка до полутора лет, продолжительность перерыва',
});
const predicate = found.structuredContent.candidates.find(c => c.kind === 'predicate');
const rules = await client.law_rules({ predicate: predicate.id.split('#')[1] });
const facts = rules.structuredContent.factsTemplate; // what to submit
const answer = await client.law_ask({
kind: 'truth',
package: predicate.package,
predicate: predicate.id.split('#')[1],
args: ['Айгуль', 'Работодатель'],
facts: [
{ predicate: 'child_feeding_break_minutes', args: ['Айгуль', 'Работодатель', 20] },
{ predicate: 'children_under_eighteen_months', args: ['Айгуль', 1] },
],
legalTime: '2026-09-01',
proof: true,
});

The answer arrives in two forms at once: text — what the server prints for a human, and structuredContent — the same fields as a document. Code reads the second.

if (answer.isError) {
// you asked the wrong thing: unknown predicate, wrong argument type,
// a limit exceeded. answer.text has the reason and a hint. This is not
// an answer of the law.
} else {
const { truthStatus } = answer.structuredContent.answer;
if (truthStatus === 'NEITHER') {
// the law is silent: look at structuredContent.whyNot — premise statuses
}
// TRUE_ONLY, FALSE_ONLY, BOTH — pass as they are, with provenance
}

Collapsing this to a boolean is the most common integration error. isError is about the call, NEITHER about the law, BOTH about a contradiction in the material; each has its own handler, and none turns into “no”.

The answer is reproducible, and code should use that: next to the outcome keep provenance whole — programHash, caseHash, resultHash, codeHash, legalTime, jurisdiction. That is enough to repeat the computation later and get the same bytes, or see what exactly changed: the law, the case, or the code.

Do not request a proof on every call: proof: true is for those answers that will go into law_explain or into an archive. The rest have proofRef.

The public server is convenient, not mandatory: the same code runs locally, and the client points at it by address. How — in Connect an AI assistant (MCP). What reproducibility of an answer means and what it does not prove — Why this can be trusted.

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.