precedent
Use the Precedent MCP server to assess decision-record standing, retrieve relevant decisions, inspect the citation/treatment graph, and validate draft decisions before they land.
Run
preflight(task, paths)to get token-budgeted decisions an agent must respect, with stale clauses pointing to controlling replacements.Check a decision’s clause-level standing and quoted treatment evidence with
decision_status.Hybrid-search decisions with
search_decisions; each hit includes its standing.Explain relationships between two decisions via citation/treatment paths with
explain_link.Run structural checks with
cite_checkfor stale statuses, reliance on superseded clauses, ghost paths, near-duplicates, and related findings.Inspect the graph model and examples with
graph_schema; run read-only Cypher withquery_graph.Find clauses overlapping a draft or touched files with
find_overlaps, distinguishing binding clauses from already out-of-force ones.Review a draft decision with
propose_decision: validatetreats/cites, see errors/warnings, standing changes, dependents, and generated ADR markdown; it is a dry run by default and can commit when requested.
The graph store can be served over Bolt/HTTP via relate serve, letting Neo4j Browser or any Neo4j driver open the same decision/clause/treatment graph and query it with Cypher (e.g. finding decisions whose header claims Accepted but whose standing is partial).
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@precedent Before I change auth, show which ADR clauses still apply."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Precedent
Case law for your codebase. Decision records are immutable, so later decisions quietly overrule parts of earlier ones while the old header still says Accepted. Precedent reads that prose once, builds the citation graph in Relate, and tells you — and your coding agent — which clauses are still good law.
▶ Try it in your browser · Demo video (1:33) · Method · Evaluation · Agent integration

Everything in that screenshot is answered by Relate compiled to WebAssembly, running in the browser tab — no server.
Use case
Teams (and agents) increasingly steer software with decision records: ADRs, RFCs, specs. The records are write-once, so a change of mind is a new record that says, in a sentence somewhere inside it, "§4 is superseded". Nothing updates the old one. A reader — human or LLM — who opens the original acts on dead clauses.
We ran Precedent on the real, public decision log of Relate itself — 533 ADRs in relatedb/relate:
decisions partly or wholly superseded by a later decision | 115 (21.6 %) |
…of which the header still says Accepted or Proposed | 111 |
flat full-text searches whose top‑5 contain at least one such decision | 74.5 % of 533 queries |
tasks where a model, given those documents, builds on an already‑overruled clause (24 tasks × 3 runs, Claude Sonnet 5.5) | 63.9 % → 4.2 % once |
| declared Accepted; §1, §4–5, §7–10 are out of force (ADR‑0229, ADR‑0276, ADR‑0307); §2–3, §6 still stand |
Which relationships matter? treatments — "A supersedes §4 of B", "C reverses A", "D withdraws part of E" — and the citations and code paths around them. That is a graph, and "is this still good law?" is a question about walking it.
Related MCP server: ratchet-mcp
What Precedent does
Standing | Per clause, not per document: in force, partly superseded, out of force, contested. Computed with grounded argumentation semantics, so "A overruled B, then C overruled A" resolves correctly (B is good law again). |
Evidence on every edge | Each treatment keeps the exact sentence it came from, the rule that fired and a confidence — a human can check any claim in one click. |
Preflight for agents |
|
A guard for agent‑written decisions |
|
Overlap finder |
|
Header patches |
|
cite‑check | Stale statuses, reliance on superseded clauses, ghost file paths, near‑duplicate decisions, temporal impossibilities. CI‑friendly ( |
Browser explorer | The same graph in your tab, queried with Cypher — try it. |
Try it
No install — open the explorer: search any decision to see which clauses still hold and who overruled the rest, browse all 533, or see the whole network. The Query tab runs your own Cypher on the same graph.
CLI (Python ≥ 3.10; uv recommended). The store is already in the repo — nothing to build, no keys, no network:
git clone https://github.com/ZNLong2203/precedent && cd precedent
uv sync
uv run precedent demo # 20-second tour
uv run precedent status ADR-0116 # clause-level standing + the quoted evidence
uv run precedent preflight "add support for creating and switching between multiple databases"
uv run precedent overlaps "Allow creating and dropping databases instead of three fixed namespaces" # before you write a decision
uv run precedent fix-status --limit 5 # which headers still say Accepted, and what they should say (--diff for a patch)
uv run precedent cite-check # 300+ structural findings, grouped
uv run precedent propose examples/proposal-multi-tenant.json # what-if: dry run of a draft ADRInspect the raw Relate store with the stock relate CLI (read-only, so git stays clean):
curl -sSfL https://relatedb.ai/install.sh | bash
relate -d data/relate-adr.rl --read-only "MATCH (d:Decision) WHERE d.status = 'accepted' AND d.standing = 'partial'
RETURN d.id, d.title, d.out_clauses ORDER BY size(d.out_clauses) DESC LIMIT 10"
relate serve --database data/relate-adr.rl --read-only --bolt 7687 --http 7474 --mcp 7475 --auth none # Bolt: the official Neo4j driver connects (examples/bolt_driver.py)With your coding agent — the repo ships a project‑scoped .mcp.json and a Claude Code skill. Open the repo in Claude Code, approve the precedent server, and ask: "Add support for multiple databases to Relate — what do I have to respect?" → what the agent sees.
How it uses Relate
Mode: single file (
data/relate-adr.rl, 17 MB, committed).Why this mode:
Not
:memory:— judges must be able to open the graph, and the standing it holds is the product.Not a directory — one file is the unit of sharing, of
githistory, and of forking: a.rlbundle copy is a complete, writable fork of the graph, which is how the guard simulates a draft against a read‑only store without touching it.The stock
relateCLI andrelate serve(Bolt/HTTP/MCP) open the committed file as‑is, and the official Neo4j Python driver queries it over Bolt (examples/bolt_driver.py, tested with driver 6.4.1).
What the graph models — decisions as cases, clauses as holdings, treatments as how later cases treat them:
graph LR
D((Decision)) -- HAS_CLAUSE --> C((Clause))
D -- "CITES {section, clauses, evidence}" --> E((Decision))
D -- "SUPERSEDES · REVERSES · WITHDRAWS<br/>AMENDS · REINSTATES · AFFIRMS<br/>{scope, clauses, evidence, rule, confidence, effective}" --> E
D -- "REFERS_TO {section}" --> P((CodePath))
D -- "SIMILAR {score, cited}" --> E 533 Decision, 1 591 Clause, 697 CodePath nodes; 3 741 CITES, 362 treatment edges, 2 548 SIMILAR. standing, out_clauses and controlled_by are derived by standing.py and written back, so plain Cypher answers "what is still good law?".
Relate capability | Where Precedent uses it |
Embedded Python library ( | the whole app runs in‑process — no server to start ( |
Single‑file |
|
Full‑text (BM25) + vector index / | hybrid retrieval: decisions + clauses + 96‑d offline LSA vectors fused with RRF ( |
Cypher: quantified paths, |
|
Explicit transactions + rollback, read‑your‑writes |
|
Whole store is one file → cheap fork | what‑if on a read‑only store ( |
| CLI and MCP open read‑only; the lock error is explained ( |
WebAssembly build ( | the explorer: every query runs in the tab |
MCP | our intent‑level server ( |
Bolt / HTTP via | the official Neo4j driver connects (example); Neo4j Browser is documented by Relate as compatible, but we have not tried it |
Setup and run
Prerequisites: Python 3.10+, uv (or pip install -e .). Optional: the relate CLI and Node (only to re‑vendor the WASM bundle).
uv sync --extra dev # install
uv run pytest # 72 tests, a few seconds (real Relate store, real MCP calls, 31 real ADRs)
uv run precedent --helpTo build a store for your own decision records (NNNN-title.md, ADR style):
uv run precedent index /path/to/repo --adr-dir docs/adr --out my.rl --name my/repo
uv run precedent cite-check --store my.rl
uv run precedent mcp --store my.rl # serve the tools to an agent (stdio)Reproduce the committed store and every number in the docs from the pinned upstream commit: make data eval (clones relatedb/relate at 1ebb65e).
Where the data lives
Path | What |
the persistent Relate store (single file; | |
the LSA basis used to embed queries for the vector index | |
all 178 negative treatments with an audit label (how) | |
the browser export of the same store | |
31 real ADRs used for regression tests |
How well does it work?
Full numbers and caveats in docs/evaluation.md. Headlines:
Precision of the 178 negative treatments (every one read against its evidence): 176 correct, 1 plausible, 1 wrong — but the rules were tuned on this audit; held‑out precision is unmeasured.
Agent behaviour (24 tasks, 3 runs each, a model with no tools): relied on an overruled clause in 46 of 72 runs with the documents alone, 48 of 72 with a generic warning, 3 of 72 with
preflight. The tasks were chosen where such a clause exists, only what the model says it relies on was scored, and the one residual miss is a decisionpreflightdid not surface — see §8.Recall of explicit overruling statements ≈ 91–97 % on a held‑out sample (statements phrased without any trigger word are invisible to that estimate).
0 of 184 dated treatments are temporally impossible (actor older than target).
Latency on the real graph:
status0.35 ms, hybrid search / preflight ≈ 45 ms (p50).
Limitations (honest list)
Rule‑based extraction tuned on one corpus (Relate's ADRs, written in a very regular style). Other styles will extract less; the evidence‑on‑every‑edge design makes errors cheap to spot. No LLM is used at runtime.
Clause granularity needs numbered clauses in
## Decision; otherwise supersession is tracked as "a part of it".Relate is single‑process and keeps the graph in RAM: one writer at a time (readers are fine), working set must fit in memory — a non‑issue for decision records.
The corpus never contains an overruling that is itself fully overruled, so the restoration path of the standing engine is covered by unit tests, not by the demo data.
The browser explorer is a sandbox copy; edits there never leave the tab.
Where models are involved
The shipped product makes no model calls. Two places involve a model: the gold audit labels were produced by an AI assistant rather than a human (see data/gold/README.md), and the evaluation calls one: scripts/agent_eval.py run feeds prompts to Claude Sonnet 5.5 through the claude CLI as the model under test (prompts, raw answers and per-call metadata are committed in data/agent-eval/).
License and attribution
Apache‑2.0 (LICENSE). The decision records analysed are © Neo4j, Inc. and contributors, Apache‑2.0, from relatedb/relate; see NOTICE. Vendored: @relate/relate-wasm (Apache‑2.0), force-graph (MIT). Relate and Neo4j are trademarks of Neo4j, Inc.; this project is not endorsed by Neo4j.
Available Tools
9 toolscite_checkCRead-onlyIdempotent
Structural findings: stale statuses, reliance on superseded clauses, ghost paths, near-duplicates...
Inputs: limit, categories. Returns: object
decision_statusBRead-onlyIdempotent
Is this decision still good law? Clause-level standing, who treated it and the quoted evidence, who relies on it.
Inputs: decision (required). Returns: object
explain_linkBRead-onlyIdempotent
Shortest path of citations/treatments between two decisions - why are they related?
Inputs: a (required), b (required). Returns: object
find_overlapsARead-onlyIdempotent
Before you write a decision: which existing clauses does your draft overlap? Paste the draft text (and/or the files it
touches). Flags clauses that still bind (declare them in treats if you change them) and clauses already out of force
(cite their replacement instead). A ranking, not a ruling - then verify with propose_decision.
Inputs: draft, limit, paths. Returns: object
graph_schemaARead-onlyIdempotent
The graph model and example Cypher for query_graph.
Inputs: no named parameters. Returns: object
preflightBRead-onlyIdempotent
Which decisions must you respect before doing task / touching paths? Returns good-law-aware
cards: live clauses are binding; stale clauses name the decision that replaced them.
Inputs: task, limit, paths, budget_tokens. Returns: object
propose_decisionA
Review a draft decision against the graph before it lands (dry run unless commit=true).
treats: [{target:'ADR-0116', kind:'SUPERSEDES'|'REVERSES'|'WITHDRAWS'|'AMENDS', clauses:[1,4], reason:'...'}].
cites: [{target:'ADR-0276', clauses:[1]}]. Returns errors (each with a fix), warnings, which decisions
change standing, who relies on what you overrule, and the ADR markdown to save.
Inputs: title (required), body, cites, commit, +4 more. Returns: object
query_graphBRead-onlyIdempotent
Run a READ-ONLY Cypher query. Rows are capped; a capped result says so in truncated.
Inputs: cypher (required), max_rows, parameters. Returns: object
search_decisionsBRead-onlyIdempotent
Hybrid search (BM25 + clause BM25 + vector) over decisions; each hit carries its standing.
Inputs: query (required), limit. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 9 tools
Each tool has a distinct role: preflight (pre-work obligations), find_overlaps (pre-authoring overlap check), decision_status (single-decision standing), cite_check (corpus-wide structural audit), search/explain/query for retrieval, and propose_decision for writes. The closest pair is preflight vs. find_overlaps, which both surface binding clauses, but their descriptions clearly separate 'before doing a task' from 'before writing a decision'. decision_status and cite_check also overlap mildly on staleness reporting, though at different granularities.
All names are lower snake_case, which is consistent. Most are verb_noun (search_decisions, explain_link, cite_check, find_overlaps, propose_decision, query_graph), but decision_status and graph_schema are noun_noun and 'preflight' is a bare noun with no verb, so the pattern is not fully uniform. Still readable and predictable enough.
Nine tools is well within the ideal range for a decision-graph server. Each tool maps to a recognizable workflow step (orient, search, inspect status, audit, draft, propose), and graph_schema is a small but justified companion to query_graph. No obvious redundancy or padding.
The surface covers the full decision lifecycle: search, standing checks, citation tracing, structural auditing, drafting, and committing via propose_decision. Minor gaps remain, such as no explicit get_decision for fetching a full decision body by ID (workable via search or query_graph) and no listing/timeline operation. Agents can work around these through the Cypher escape hatch, so no dead ends.
Maintenance
Related MCP Connectors
Append-only decisions with provenance, supersession, retrieval, and audited MCP actions.
Pre-execution governance for AI agents. Deterministic PASS/FAIL/REVIEW verdicts, replayable proof.
Govern proposed Action Cards with Decision Receipts before developer-owned execution.
Durable commitment lifecycle, verification, governance and recovery layer for agentic commerce.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceProvides a decision memory layer for codebases, enabling AI agents to search, retrieve, and record business decisions with metadata filters and full-text search.1MIT
- AlicenseAqualityBmaintenanceEnables AI agents to gate real-world side effects through a durable decision record, ensuring at-most-once initiation, deduplication, budget enforcement, and auditable outcomes across retries and failures.1562 npmApache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to read and update a repository's decision ledger, check which files a decision governs, find stale files after a decision reversal, and record or reverse decisions over MCP.20 npmApache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to locally record decisions with constraints, evidence, and answers; search validated precedents; and explicitly supersede prior calls while keeping linked history. Also provides tools for expanding records, reviewing active context, checking coverage and status, and finding duplicates or stale decisions without network access.301 npmMIT