Search and cite French case law and statutes with the LibreJustice MCP tools...
The user needs decisions whose reasoning states a precise proposition, applicable to the situation at hand, with a quotable excerpt.
The tools come from the LibreJustice MCP server; if search_decisions is missing from your session, connect it first: references/install-mcp.md.
Five rules dominate everything:
get_decision. An aiSummary or a snippet is not reading.aiSummary is a machine paraphrase, never the court's words; a snippet is verbatim but torn from context. Every quoted string in the answer is copied character-for-character from a get_decision or get_norm text of this session: not opened means not quotable. A quotation is one continuous span of one single text, cuts marked « […] » : merging passages, or decisions, into one pair of quotation marks is fabrication, one source per quote, two passages are two quotes. A sentence reporting a decision in your own voice (« la cour retient que… » followed by your summary or a parenthesized list) is prose, never a quotation.url verbatim: [CA Paris, 10 janv. 2024, n° 21/22203](https://librejustice.fr/decision/…). Never reconstruct or shorten a URL.get_decision text are the decision's fate on appeal. A [SORT DE CETTE DÉCISION SUR RECOURS : …] banner (also served as the appellateFate field) states what became of it on review. Copy it into the answer. It overrides your own docket sweep: a sweep that found nothing while the text carries a banner means the sweep missed the arrêt, never that none exists.A get_decision response may also carry commentaires, the court's own analysis served inline (body) and outbound links (url) to the rapporteur public's conclusions or related court documents. They are context and cite as commentary, never as the ruling: only the decision text quotes as the court's words.
Pin down (ask when the request leaves them open): the proposition in one sentence; who demands what and what winning means; the legally relevant date; the target courts; the exclusions; the proximity axes that decide transposability. A legal assertion inside the question (« c'est bien uniquement devant telle juridiction ? », « cet acte est nul, non ? ») is a claim to research, never an input: the complement of the assertion gets its own step-2 sweeps (its own queries and filters, including the courts or outcomes the assertion excludes), and the answer's opening sentence states your verified verdict, never an echo of the premise. Follow-ups refine, they never reset: « d'autres ? » = new decisions, same bar; « tu peux vérifier ? » = reopen the source, never restate with more confidence.
solution-filtered sweep per side, your first two search_decisions calls. Map each direction of the holding to outcomes, then run the same query twice with opposite solution filters, e.g. {"query": "convention de forfait en jours privée d'effet", "jurisdiction_code": ["ca_versailles"], "solution": ["SATISFACTION_TOTALE", "SATISFACTION_PARTIELLE"]} then the same with ["REJET"]. This is the only lever that separates the two directions of a line.Engine facts:
aiSummary or a snippet.21PA01295, 19-20.682, matched by exact key whatever the spelling, and served alone. A number or a case name inside a question (387763 Czabaj délai raisonnable, Danthony vice de procédure) keeps the question's hits and surfaces the designated decision in pinned: open it from there, never look for it in the ranking. pinned exists in auto only; a stated mode is served as stated.limit (max 20), no pagination. Read the date_lecture_year facet on every sweep: a year newer than the newest hit you opened, with a nonzero count, is unswept. Re-run with date_from/date_to on that year before concluding.date_from is the filter that silently hides a line's founding arrêt, often decades old. Bound dates only when the question itself is time-bounded or a facet year needs re-sweeping, never by default.legal_domain for the subject (PUBLIC_DROIT_ETRANGERS_NATIONALITE, SOCIAL_DROIT_TRAVAIL, COMMERCIAL_DROIT_ENTREPRISES_DIFFICULTE…), where a root covers its leaves (CIVIL also returns CIVIL_DROIT_LOCATIF, CIVIL_DROIT_PERSONNES_FAMILLE), office for the single-judge courts (JLD, JAF, JCP, JEX…), legal_article for the decisions citing one article ("code-civil|1240"). Each cuts the corpus before ranking.seat is the court unit itself, from its type down to its room: a dotted path, one segment per level ("CC", "CC.SOCIALE", "CA.PARIS", "CA.PARIS.P5.C6"). A path matches itself and everything under it, so "CC.SOCIALE" also returns the sections of that chamber and "CA" returns every cour d'appel. It says on one key what jurisdiction_type and jurisdiction_code say on two, and those two stay accepted. Take the paths from facets.seat, which serves the tree of the result set in hand: search, read the facet, then filter. Crossing a path with a period is how a line of one chamber is followed across a reorganisation.Open every hit of the target court that touches the issue. Open first, and always, every hit whose served solution sits on the user's side. Fewer than eight decisions opened by the end of this step means the research has not happened: go back to step 2 and change a real axis (court level, phrasing, dates) until eight full texts are read or the target courts' relevant hits are exhausted. Five verdicts per decision:
INFIRMATION kills the decision as support. CONFIRMATION = open that arrêt and cite the pair; the arrêt holds what the judgment held, never the opposite line's direction. No banner served = run the judgment's docket number, bare and unquoted, filtered to the appellate court: a number is matched by exact key, and quoting it drops the fallback. A sweep hit is the same case only if its « Décision déférée » header names your judgment, same court, same date : RG numbers collide across courts, and a hit from another ressort or another date is noise, never the fate. No banner and no sweep = « aucun recours lié dans le corpus »./norm/ links; open them with get_norm at the facts' date. A failed tool call (bad URL format, unknown code) is retried with the corrected argument, never silently dropped: an article the question turns on that you never managed to read voids every claim about it.Re-run the winning query with sort: "date_desc", once per direction, with that side's solution filter, per target court, and read the most recent decisions of each. When a court ruled both ways, the deliverable is a dated timeline, never a flat « court X says P »: either side of a flip, presented alone, misleads. A hit newer than every decision the answer names, seen in any list this session, is either opened and cited or excluded for a stated reason, never silently dropped.
« No decision of court X states P » is falsifiable with one citation. Before writing it: exact formula (both phrasings) + a descriptive query under the court filter; a solution-filtered sweep on P's outcomes; date_from widened; facets read. Last: re-scan the hits you did NOT open across every list of the session: one unopened hit whose solution sits on P's side voids the claim until opened. Counts: define the corpus; keep raw hits, deduplicated decisions and verified holdings apart. A counting table is built from the facets of one named query per column: never merge facets from different queries into one series. total and the facets count every decision matched under the current filters, not the page served: neither a count of the corpus nor a count of the hits. Two things distort that number. A multi-word query matches on ANY of its tokens, so its total counts whatever carries one word of it: it counts something only under a quoted formula, or under filters (court, dates, solution) narrow enough to define the corpus. And a decision found by meaning alone is counted only inside the window served, so the total of a purely descriptive query is a floor. A yearly series that starts or jumps abruptly usually marks the edge of source coverage, not the birth of the contentieux: say so instead of narrating the jump.
The shape is the user's: the format they asked for, or the one their earlier answers were in. What follows is what the answer has to carry, never how it looks. None of it is wording to reproduce: these are things to say, said in the language the user writes in, under whatever headings that language and that format call for.
date_desc + solution query of step 4 for that court and that direction.solution sweep never ran for it is the check that fails most.search_decisions call of this session: the query, the filters (solution, dates, courts), the sort, the hits opened. One entry per get_decision, in call order: the linked citation. Append the entry when the call is sent, then paste both lists into the answer. An entry for a call that never ran, or a filter listed but never sent, is fabrication; a search that ran but is missing (including a failed one) is a hole in the audit trail. Every decision link anywhere else in the answer copies an entry of the list of opened decisions, and no other count of decisions read is ever stated. A direction of the holding with no solution-filtered entry is unresearched: run it now, or write « non recherché » next to the list, a sentence always available and always true.Cite only decisions returned by the tools.
get_decision / get_norm texts. Found only in separate pieces, it is a splice: re-cut it into one quote per source, « […] » for internal cuts. Found only in a hit's aiSummary or snippet, or nowhere: rewritten from the fetched text, or unquoted. Then who speaks: the motifs of the decision it is attributed to, not a party's argument or moyen, not another decision.Quick lookups only: anything deeper (treaties, EU law, versions across recodifications) is the recherche-normes skill's job. get_norm returns an article as it stood on a given date: pass date and say which version you quote.