recht-mcp
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., "@recht-mcpGround § 823 Abs. 1 BGB and show the current text"
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.
recht-mcp
An MCP server for German law: federal statutes and regulations, the Landesrecht of Bayern, Brandenburg, Nordrhein-Westfalen and Sachsen, and court decisions — for AI agents that need to ground a citation, read a provision, or follow the citation graph, and need to know when an answer is not complete.
This repository is the tool layer of the hosted server at
https://recht.nulegal.eu/v1/mcp. The hosted endpoint runs this code,
vendored at a pinned commit, over a private backend that reads the corpus
directly; recht-mcp runs the same code locally over the public REST API. The
corpus and the database stay on the service side — see
docs/DESIGN.md for exactly where the line runs.
The nine tools
Tool | What it does |
| Grounds up to 100 citations at once — |
| One query over statutes (lexical) and case law (semantic), with a per-jurisdiction roll-up for cross-Land comparison. |
| The text of one provision as Markdown (or JSON), optionally as of a date, with its gazette citation ( |
| Every stored version of a provision, with the archive floor marked. |
| Decisions citing a provision or a decision, by citation weight or newest first, with the citing court's own Randnummer. |
| What one decision cites: provisions (the weighted Normenkette) and decisions. |
| A decision as numbered passages; page through it or jump to a Randnummer. |
| Provisions whose text changed recently — the freshness feed as JSON. |
| What the corpus holds, and the limits every answer should be read against. |
Every tool is read-only. Each answer says what it is and what it is not:
version dates are first-observed dates, not Inkrafttreten; the norm-version
archive has a floor that every norm answer states; a zero from the citation
graph on a Land provision is labelled as "not indexed", not "never cited"; and
three kinds of miss — not_in_corpus, outside_coverage, known_missing —
are never collapsed into one. The full contract of each tool is in its
description (tools/list).
Related MCP server: legal-text-mcp-de
Use the hosted server (recommended)
No key, no signup. Point any MCP client that speaks Streamable HTTP at:
https://recht.nulegal.eu/v1/mcpClaude Code:
claude mcp add --transport http nulegal-recht https://recht.nulegal.eu/v1/mcpA client configured with JSON:
{
"mcpServers": {
"nulegal-recht": { "type": "http", "url": "https://recht.nulegal.eu/v1/mcp" }
}
}Developer documentation for the service and its REST API: https://recht.nulegal.eu/developers.
Run it locally
Requires Python 3.12+ and uv. The package has no third-party runtime dependencies.
git clone https://github.com/nulegal-startup/recht-mcp
cd recht-mcp
uv run recht-mcp # stdio
uv run recht-mcp --http # Streamable HTTP on http://127.0.0.1:8765/mcpOr without a checkout:
uvx --from git+https://github.com/nulegal-startup/recht-mcp recht-mcpA client that launches stdio servers:
{
"mcpServers": {
"nulegal-recht": {
"command": "uvx",
"args": ["--from", "git+https://github.com/nulegal-startup/recht-mcp", "recht-mcp"]
}
}
}Options: --http, --host (default 127.0.0.1), --port (default 8765),
--path (default /mcp), --base-url (or RECHT_MCP_BASE_URL; default
https://recht.nulegal.eu), --timeout, --log-level. The local HTTP server
binds to loopback and refuses browser requests from non-loopback origins.
The local server reads the same data the hosted one does, through the public
REST API, and gives the same answers with two documented exceptions (a
simplified citation grammar, and no other_laws hint on a provision miss) —
see docs/DESIGN.md.
Development
uv sync
uv run pytest -q # unit tests, offline
RECHT_MCP_LIVE=1 uv run pytest -q tests/test_live.py # against recht.nulegal.euThe live tests call every tool through the local server and compare several answers with the hosted endpoint's.
Data
The legal corpus served by the hosted endpoint — its structure and selection, the links between provisions and decisions, the version history — is licensed separately from this code, under CC BY 4.0. Attribution is required: „Quelle: nu:legal – recht.nulegal.eu“. The terms, including what is reserved, are at https://recht.nulegal.eu/lizenz and https://recht.nulegal.eu/nutzungsbedingungen.
The texts are non-official reading copies. The binding text of a statute is
the one in its official gazette; each norm answer names it (fundstelle,
authoritative_source).
Contributing and security
Issues are welcome; outside pull requests are not accepted yet — see CONTRIBUTING.md. Report vulnerabilities privately as described in SECURITY.md.
License
The code in this repository is licensed under the GNU Affero General Public
License, version 3 only (AGPL-3.0-only) — see LICENSE.
The legal corpus served by the hosted endpoint is licensed separately, under CC BY 4.0 with attribution required (see Data).
The nu:legal name and logo are not licensed.
Available Tools
9 toolsgetChangesRecent changesARead-onlyIdempotent
Which provisions got a new text recently, newest first — the freshness feed, as JSON. Poll it with since set to the newest observed you have already processed.
observed is the day the new text was FIRST SEEN here, which is not necessarily the day it came into force. Say so if you report a date. The window is the last 120 days; the law's own Änderungsverlauf goes further back.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| since | No | Only changes observed on or after this date. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, covering safety. The description adds valuable semantics: `observed` is first-seen date, not in-force date, and warns to say so when reporting. This contextual nuance goes beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight paragraphs: the first gives purpose and usage in one sentence; the second adds necessary nuance about the date semantics and window. No filler; front-loaded with the core action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only feed with two optional parameters, the description covers purpose, polling behavior, date semantics, and limits. An agent can correctly invoke it without further information; output format is noted as JSON, which is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema documents `since` with a pattern and description, and `limit` with defaults. The description enriches `since` by defining what 'observed' means and clarifies the recency ordering. With 50% schema coverage, the description compensates meaningfully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns provisions with recently changed text, ordered newest first, as a JSON freshness feed. This is a specific verb-resource-action combination that distinguishes it from siblings like search or getNorm.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit polling guidance is provided: set `since` to the newest observed value already processed. It also notes the 120-day window and contrasts with the law's own Änderungsverlauf, implying alternatives for older data, though it doesn't name the specific sibling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
getCoverageCorpus coverageARead-onlyIdempotent
Corpus scope with its holes stated. Call this once when your answer depends on whether an absence is real.
Returns totals (laws, provisions, versions, decisions, courts, citation edges), the per-source windows, the count of Aktenzeichen we can prove exist and do not hold, and limits: the version-archive floor, the federal scope of the citation graph, what a version date actually means, and why source windows differ.
Use it to tell outside_coverage from not_in_corpus. They are different answers and this API never collapses them.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and idempotentHint=true, signaling a safe, non-mutating operation. The description adds valuable context on the tool's return structure ('totals, per-source windows, Aktenzeichen counts, limits') and explains the semantic nuances of 'limits' (version-archive floor, federal scope, version date meaning, source window differences). It also clarifies that the tool does not conflate absence types, which goes beyond the annotations. A small gap is not detailing the exact format or pagination, but that is minor for a zero-parameter read-only tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences long and front-loads the most critical information: the tool's purpose and when to use it. The second sentence lists return elements and constraints, and the third reinforces a key distinction. Each sentence earns its place, though the second sentence is dense and might be slightly overwhelming, but it is not verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with a rich description, the description is nearly complete. It covers the tool's scope, what it returns, its limitations, and when to use it. The absence of an output schema is compensated by the detailed description of the return contents. The only minor gap is that it doesn't explicitly state that it requires no arguments, but that is trivially inferred from the zero-parameter schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema provides no parameter details. The description compensates by explaining the context and what the tool returns, which is more than sufficient for a no-parameter tool. While the schema is trivial, the description's detail on the tool's output ensures an agent understands what it will receive without needing parameter guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies the tool as reporting corpus coverage with a specific scope ('Corpus scope with its holes stated') and distinguishes it from siblings by clarifying it never collapses 'outside_coverage' with 'not_in_corpus'. It also mentions 'totals' and 'limits' to specify what the tool returns, making its purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The first sentence states a clear condition for use: 'Call this once when your answer depends on whether an absence is real.' It also explicitly tells users not to collapse two different answers, thereby directing when to avoid using this tool and what distinction it maintains. No alternative sibling is named, but the guidance is sufficient for a tool with zero parameters, as the condition is highly specific.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
getNormGet statute textARead-onlyIdempotent
The text of one provision, by default as clean Markdown — about a tenth the size of the reader page for the same provision, with no navigation, no scripts and no boilerplate.
law is the abbreviation as a citation writes it ('BGB', 'DSGVO', 'BDSG 2018', 'RVG'); ref is the bare number, with any letter suffix and no § or Art. ('622', '823', '3a', '83'). Aliases resolve, and CASE IS READ: 'LwG' is the federal Landwirtschaftsgesetz while 'LWG' is a Land statute (Bayern's Landeswahlgesetz, NRW's Landeswassergesetz), so write the abbreviation the way your citation writes it. A spelling that matches no law exactly still resolves case-insensitively, and a miss lists the other laws the abbreviation names under other_laws, each with a law_key you can call again with.
POINT IN TIME: as_of=YYYY-MM-DD returns the version stored for that date. Read version_coverage on every answer — the version archive begins 2019-06-10, and a date before that answers outside_coverage with the law's amendment register attached. That is a limit of our archive and says nothing about whether the provision existed.
Every answer carries first_observed, valid_to, date_precision and amendment_note. first_observed is the day we first saw the text, NOT the legal Inkrafttreten — do not compute a deadline from it without reading date_precision (day / week / launch; 'launch' means the date is a floor).
TRUST: fundstelle is the gazette citation of the authentic text — the citation a court accepts. authoritative_source names what our copy is (a consolidated, non-official reading version) and where the binding text lives. Quote the provision from markdown; the reader page at url carries per-Absatz anchors (#abs-N) if you want to deep-link a single Absatz.
| Name | Required | Description | Default |
|---|---|---|---|
| law | Yes | Law abbreviation, or a `law_key` (`slug` in search results) when an abbreviation is ambiguous. | |
| ref | Yes | Provision number without § or Art. A sub-unit ('Abs. 1', 'lit. f') is dropped: the whole provision is returned. | |
| as_of | No | Return the version stored for this date. | |
| format | No | 'markdown' (default, compact, quotable) or 'json' for the structured payload. | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only, idempotent, and non-destructive, and the description adds substantial behavioral detail beyond that: case-sensitive abbreviation handling, ambiguous-law fallback with other_laws, version archive boundaries, the distinction between first_observed and legal Inkrafttreten, and trust/citation semantics. This is rich, valuable context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: core purpose first, then parameter semantics, point-in-time behavior, response fields, and trust guidance. Clear section headers and front-loaded key facts make it easy for an agent to skim and apply.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description takes on full responsibility for explaining return values and did so thoroughly: version_coverage, outside_coverage, first_observed, valid_to, date_precision, amendment_note, fundstelle, authoritative_source, markdown, url, and other_laws are all mentioned with practical guidance. An agent has what it needs to invoke and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and each parameter has meaningful schema descriptions and examples. The description adds further semantic nuance for 'law' and 'ref', especially the citation-style abbreviation, case sensitivity, alias resolution, and dropping sub-units. Format is only lightly covered, but the schema enum and default already handle it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: it returns 'the text of one provision' as clean Markdown. It clearly distinguishes this from sibling list/version/search tools by emphasizing a single provision in compact form.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: how to cite law abbreviations, what ref means, how case-sensitivity and ambiguity resolve, and when to use as_of. It does not explicitly name sibling tools or state when not to use this tool, but the context is strong enough for an agent to route correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listCasePassagesList case passagesARead-onlyIdempotent
The full text of one decision, split into its paragraphs, each with a permalink you can cite.
rn is the Randnummer the COURT printed, read out of the decision's own markup. It is never inferred from position: where a document prints no numbers, rn is null and stays null. anchor_basis is derived per decision — only 'native_numbering' means our anchor and the printed number provably coincide, so pin-cite a Randnummer only when you see that value.
amtliche_seite is null everywhere: our texts carry no page breaks, so a BVerfGE-style page pin cannot be produced honestly.
SIZE. Long decisions run to several hundred paragraphs, so the default page is 30. Three ways to move: offset pages, limit widens (max 400 — enough for a whole decision when you really want it), and around jumps. pagination appears whenever there is more than the page you were handed.
around: 51 returns a window of limit passages CENTRED on Randnummer 51 — the right call when listCitingDecisions gave you a citing_rn, when a search hit came back anchored at …#rd_51, or when you want the passage around a pin cite and not the whole judgment. It takes the number the court printed, not a position, and a decision that prints no such number answers not_in_corpus rather than silently handing you a different passage. around and offset address the same list two different ways; give one.
| Name | Required | Description | Default |
|---|---|---|---|
| case | Yes | A juris doknr, an ECLI, or this site's decision URL as `search` returns it. | |
| limit | No | ||
| around | No | A Randnummer as the court printed it. Returns a window of `limit` passages centred on it. Not combinable with `offset`. | |
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is covered. The description adds substantial behavioral context beyond that: rn is read from the court's own markup and never inferred, anchor_basis values and when pin-citing is safe, amtliche_seite is always null because texts carry no page breaks, pagination appears only when there is more than one page, and around returns not_in_corpus rather than silently returning a different passage. This is rich, honest behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every section earns its place: the opening sentence states the core purpose, the rn/anchor_basis paragraph prevents citation misuse, the amtliche_seite paragraph prevents a false expectation, and the SIZE/around paragraphs give operational guidance. It is front-loaded with the most important facts. Slight redundancy in the around paragraph (repeats the centred-window idea) keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with 4 parameters, no output schema, and no nested objects, the description covers everything an agent needs: what the tool returns, how to identify the case, how to page, how to cite safely, and what to expect when a number is absent. The absence of an output schema raises the burden, and the description meets it by describing the return shape (paragraphs with permalinks, rn, anchor_basis, amtliche_seite, pagination).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50%: the schema documents `case` and `around` but not `limit` or `offset`. The description compensates by explaining limit's max (400, enough for a whole decision), offset's role in paging, and around's semantics (centred window, takes a printed number, not combinable with offset). It adds meaning beyond the schema, though it doesn't spell out offset's default or exact paging math, which the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise statement: 'The full text of one decision, split into its paragraphs, each with a permalink you can cite.' This clearly identifies the resource (case passages), the action (list), and the distinguishing output (paragraphs with permalinks). It also differentiates from siblings like listCitingDecisions and listCitedAuthorities by focusing on the decision's own text rather than citation relationships.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'the right call when listCitingDecisions gave you a citing_rn, when a search hit came back anchored at …#rd_51, or when you want the passage around a pin cite and not the whole judgment.' It also explains when not to use it (when you want the whole judgment, use limit; when you want a specific page, you can't because amtliche_seite is null). It names the alternative navigation methods (offset, limit, around) and their trade-offs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listCitedAuthoritiesList cited authoritiesARead-onlyIdempotent
Outgoing citation edges of one decision: the statute provisions it cites (with how often it cites each — that is the Normenkette, weighted) and the decisions it relies on.
treatment is null on every edge and stays null. Classifying an edge as gefolgt / abgegrenzt / aufgegeben is unbuilt work, and a wrong 'aufgegeben' in a brief is worse than no label at all. Read the citing passage yourself with listCasePassages.
A decision we can prove exists but do not hold answers known_missing, with the decisions that attest it — not a 404.
| Name | Required | Description | Default |
|---|---|---|---|
| case | Yes | A juris doknr, an ECLI, or this site's decision URL as `search` returns it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds crucial behavioral detail beyond annotations: `treatment` is always null and classifying edges is 'unbuilt work' (with a caution about using a wrong label in a brief), and the tool returns `known_missing` with attestations instead of a 404 for decisions that exist but are not held. This is exactly the kind of nuance an agent needs and is not in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is about 150 words and front-loaded with the core purpose. The treatment paragraph is somewhat lengthy but each sentence adds value (warning against unbuilt classification). The known_missing sentence is crisp. It is structured but not as tight as a two-sentence ideal.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description adequately explains the return semantics: statute provisions with counts, decisions relied on, treatment always null, and known_missing behavior. It also points to `listCasePassages` for deeper reading. For a read-only citation listing tool, this is sufficient for correct invocation and interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage for the single `case` parameter, explaining accepted formats (juris doknr, ECLI, or decision URL from `search`). The tool description adds nothing beyond that, so it correctly relies on the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('list') and resource ('outgoing citation edges of one decision'), and breaks down the two citation types: statute provisions with weighted counts (Normenkette) and decisions relied on. It clearly distinguishes from an incoming-citations tool by the phrase 'outgoing', and the detailed content leaves no ambiguity about what is returned.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: it is for a single decision's outgoing citations and is read-only. It explicitly directs to `listCasePassages` when you need to read the actual citing passage, which is a concrete alternative. However, it does not mention `listCitingDecisions` as the counterpart for incoming citations, so it lacks an explicit when-not-to-use statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listCitingDecisionsList citing decisionsARead-onlyIdempotent
Incoming citation edges. Give EITHER law + ref (which decisions apply this statute provision) OR case (which decisions cite this decision) — exactly one of the two.
Results are ranked by citation weight, then court tier, then recency. Read the ranking honestly: for a provision with many EU decisions the first ten can be almost all CJEU, and the German courts appear only further down. If total exceeds what you read, page on with offset (pagination.next_offset) before concluding anything about national case law.
NEWEST FIRST: pass sort: "recent" when the question is about current case law ('fünf aktuelle Entscheidungen zu …'). Paging works the same way. This ordering is bounded — for a handful of procedural giants (§ 154 VwGO, § 708 ZPO) it cannot be computed inside the query budget, and then the answer comes back in WEIGHT order and says so in sort_applied and sort_note. Check sort_applied before you describe a list as the most recent decisions.
For a decision, each citer carries citing_rn: the Randnummer of the CITING decision's own text that holds the citation, as that court numbered it, and the URL is anchored to it.
COVERAGE: the graph is built over federal case law. A Land provision can answer total: 0 because it is not indexed, not because no court has cited it — coverage.complete_for_this_norm tells you which, and for a Land provision you should fall back to search on the provision's wording.
| Name | Required | Description | Default |
|---|---|---|---|
| law | No | ||
| ref | No | ||
| case | No | A juris doknr, an ECLI, or this site's decision URL as `search` returns it. | |
| sort | No | 'weight' (default) is citation weight, then court tier, then recency. 'recent' is newest decision first; where it cannot be computed the answer falls back to 'weight' and says so in `sort_applied`. | weight |
| limit | No | ||
| offset | No | Rows to skip, for reading past the first page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description's added context is valuable. It discloses ranking internals (weight → court tier → recency), coverage gaps (Land provisions may yield total:0 even when cited), the bounded nature of 'recent' ordering with fallback to weight, and the meaning of citing_rn. None of this contradicts the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but well-structured into clear paragraphs (core modes, ranking, sorting, coverage). Every sentence adds operational value, and key constraints (exactly one mode, check sort_applied) are front-loaded. It could be trimmed slightly, but the density is justified for a tool with this complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema, the description covers all critical call-time knowledge: how to select parameters, ranking order, pagination, coverage limitations, and the citing_rn anchor. It explains edge cases like procedural giants and Land provisions, so an agent can call it correctly and interpret results without additional lookups.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50% (case, sort, offset have descriptions; law, ref, limit do not). The description clarifies the required pairing of law+ref and the alternative case, explains sorting behavior and pagination via offset, and adds the coverage caveat. While the schema already documents sort and offset, the description adds contextual meaning beyond the raw field definitions, compensating for the half without schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific purpose: listing incoming citation edges, with two mutually exclusive query modes (law+ref or case). It clearly distinguishes itself from siblings like listCitedAuthorities by focusing on incoming edges, and explicitly requires exactly one of the two modes, preventing ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance: the law+ref mode for statute provisions, case mode for decisions, and when to pass sort:"recent" for current case law. It also names a fallback to the `search` sibling for Land provisions, and instructs checking `sort_applied` before drawing conclusions. No exclusions are left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listNormVersionsList statute versionsARead-onlyIdempotent
Every stored version of one provision, newest first, so you can find out which dates getNorm(as_of=…) can actually answer before you ask.
Each entry carries first_observed (the day the text was first seen here — NOT the Inkrafttreten), valid_to, date_precision and the law-level amendment_note. at_archive_floor: true marks the version that was current when mirroring began: its date is a floor, not an amendment, and earlier amendments exist that are named in the law's Änderungsverlauf (linked as amendment_history_url) but whose text is not held.
There is no diff tool: fetch two versions with getNorm(as_of=…) and diff them yourself — a diff we computed would hide which side of it came from a floor date.
| Name | Required | Description | Default |
|---|---|---|---|
| law | Yes | ||
| ref | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Though the annotations already declare readOnlyHint and idempotentHint, the description adds substantial behavioral context beyond them: first_observed does NOT mean Inkrafttreten, at_archive_floor indicates a mirroring floor rather than an amendment, and earlier amendments may be listed in the Änderungsverlauf but not held. It even discloses the limitation that no diff is provided and explains why, which helps the agent set expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place: purpose, return-field semantics, floor-date caveat, and the no-diff guidance are all substantive. The description is front-loaded with the main use case and is organized in digestible paragraphs without repetition of schema or annotation values.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description fills that gap by enumerating all meaningful return fields and their semantics. It also explains the critical edge case of archive floor dates and names the amendment_history_url field, making the tool's behavior fully understandable for an agent attempting to use it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the burden falls on the description to explain law and ref. The description mentions 'one provision' and 'law', but it never explicitly defines law as the statute identifier or ref as the specific provision reference. The schema examples (BGB, 288) help, but the description itself does not compensate for the missing parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: listing every stored version of one provision, newest first. It also distinguishes the tool from getNorm by explaining that it reveals which as_of dates getNorm can actually answer. This differentiates it clearly from the sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use this tool before asking getNorm(as_of=…) so you know which dates are answerable. It also gives a strong when-not-to: there is no diff tool, so users should fetch two versions with getNorm and diff them manually. The alternative tool is named and the condition for using it is stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolveIdentifiersResolve legal citationsARead-onlyIdempotent
Ground a batch of German legal citations against the corpus. Call this BEFORE stating any citation you did not read here.
Takes the citation in the form you already hold it — including the court name, the dispositive word and the date a model normally writes around a docket. KEEP THEM IN: the court and the date are used to disambiguate. An Aktenzeichen is unique per court, not nationwide, and 21,021 dockets in this corpus are held by more than one decision, so 'OLG Bamberg, 4 U 120/24' resolves to Bamberg's decision where the bare '4 U 120/24' is ambiguous or lands on another court's. Where the string has to be rewritten to be read, the rewrite is reported back under normalised_from / normalised_to, never silently, and disambiguated_by says when it was YOUR court or date that picked the decision out. Where the court you named writes a suffix your citation dropped ('4 U 120/24 e'), the answer carries docket_completed with the full Aktenzeichen — cite that one.
Accepted kinds: norm citations ('§ 823 Abs. 1 BGB', '§§ 305-310 BGB', 'Art. 83 DSGVO'), Aktenzeichen ('2 C 9.22', '8 AZR 26/18'), ECLI ('ECLI:DE:BGH:2019:180619UVIIIZR247.18.0') and Fundstellen ('BVerfGE 65, 1'). Full prose citations work: 'BVerwG, Urteil vom 24.10.2023 - 2 C 9.22'.
It never returns a near match. A miss comes back as not_in_corpus (we hold nothing and know of nothing), attested / known_missing (the decision provably EXISTS — decisions we do hold cite it by Aktenzeichen, and they are listed as the evidence — but we do not have its text), ambiguous (with candidates) or unparseable. attested is not a failure: you may state that the decision exists, cite it, and say the text was not available to you. What you must not do is treat it as not_in_corpus.
A resolved norm carries fundstelle: the gazette citation of the authentic text, which is the citation a court accepts. Our own URL is a reading copy, and for Land law the gazette citation is the only source reference there is. Prefer it in anything you publish.
text on a resolved norm is a 300-character stub unless you pass include: ["text"], and text_truncated says which it is. Never verify a quotation against the stub: it is the head of the provision, not the Absatz you cited.
When you supply a date or a court that does not match the decision the docket resolves to, the result carries date_mismatch / court_mismatch with the actual value. That is the hallucinated-citation case this tool exists for: cite what is actually there, not what you held — and a court_mismatch usually means this is not the decision you meant at all.
| Name | Required | Description | Default |
|---|---|---|---|
| include | No | Opt-in extra payload. 'text' returns a norm's FULL text instead of the 300-character stub — the stub is the same 300 characters whichever Absatz you cited, so never verify a quotation against it. 'leitsatz' returns a decision's whole Leitsatz instead of its preview. An unknown value is refused, not ignored. | |
| citations | Yes | The citations, verbatim as you hold them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, but the description adds substantial behavioral disclosure: normalization reporting (normalised_from/normalised_to), disambiguation via court/date, miss categories, date_mismatch/court_mismatch, docket_completed, fundstelle, and the 300-character stub danger. This far exceeds what annotations alone provide and contradicts nothing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but front-loaded with the most important rule, then organized into clear sections for citation kinds, outcome categories, fundstelle, text behavior, and mismatch flags. Most sentences carry distinct, decision-relevant information, though some length could be trimmed without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of explaining return behavior, and it does so thoroughly: miss enumerations, disambiguation evidence, docket completion, gazette fundstelle, text truncation, and mismatch warnings are all covered. Minor omissions like batch-level atomicity do not undermine an agent's ability to call and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds critical parameter semantics: the court and date must be kept because Aktenzeichen are not unique nationwide, include values are opt-in with unknown values refused rather than ignored, and 'text' returns full text instead of the stub. It also gives concrete accepted citation formats, enriching both parameters well beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Ground a batch of German legal citations against the corpus,' naming a specific verb and resource, and it is clearly distinct from a bare search or retrieval tool. It enumerates accepted citation kinds, but it never explicitly names or contrasts sibling tools such as search or getNorm, so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit decision rule: 'Call this BEFORE stating any citation you did not read here.' It also explains how to interpret different miss outcomes (attested vs not_in_corpus) and what the agent may or must not do with them. However, it does not name alternative tools or state when to prefer a sibling, so exclusions are implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchSearch German lawARead-onlyIdempotent
One query over BOTH corpora: federal and Land statutes (lexical, with concept pinning) and court decisions (semantic — natural-language questions work well here and are the better shape for case law).
Search both unless you have a reason not to. A term of art often does not appear in the statute that governs it: 'Verzugspauschale' matches no provision (§ 288 BGB says 'Pauschale in Höhe von 40 Euro') while 184 decisions use the word. scope='norms' alone will read as 'nothing here' in exactly those cases.
CROSS-LAND COMPARISON: a single query returns the parallel provisions of the Bund and of every covered Land side by side, each row jurisdiction-labelled, plus a by_jurisdiction roll-up. Ask 'Videoüberwachung öffentlich zugänglicher Räume' and you get BDSG § 4 next to the Land data-protection and police provisions. Full text is held for Bayern, Brandenburg, Nordrhein-Westfalen and Sachsen.
Decision hits come back already anchored at the best-matching Randnummer (…#rd_51), so you can quote a paragraph rather than a document, AND carry doknr — the key listCasePassages, listCitedAuthorities and listCitingDecisions take, so you can go straight from a search hit to that decision's passages or its authorities without resolving anything first. Query in German; write raw umlauts, they are handled.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | German query. Keywords, a citation, or a full question. | |
| limit | No | ||
| scope | No | 'all' (default) searches both. Narrow only when you know which corpus answers. | all |
| include_repealed | No | Include repealed (aufgehobene) provisions. Off by default; turn it on when researching an older state of the law. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only/idempotent annotations, the description discloses important behavior: lexical search with concept pinning for statutes, semantic search for decisions, cross-Land jurisdiction roll-ups, full-text coverage for four Länder, best-match Randnummer anchoring, doknr propagation, and umlaut handling. This is substantial contextual disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense, with front-loaded essentials and clear section-like paragraphs. Every sentence contributes useful information, and the examples illustrate rather than pad.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex, two-corpus tool with no output schema, the description covers the important invocation, scope, result-shape, and follow-up workflow. It stops short of describing pagination, result ordering, or exact response structure, but the schema covers limit constraints and the rest is sufficient for correct use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, and the description significantly expands meaning for `q` (German, natural-language questions, raw umlauts) and `scope` (why narrowing to norms can fail, default 'all' behavior). It does not add anything about `limit`, but the parameter is relatively self-explanatory.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a specific action and resource: 'One query over BOTH corpora: federal and Land statutes ... and court decisions'. It distinguishes this search tool from sibling retrieval/list tools by emphasizing the dual-corpus search behavior and result features like `doknr` and `#rd_51` anchors.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use and when-not-to-use guidance: 'Search both unless you have a reason not to', warns that scope='norms' alone reads as empty for terms of art, recommends natural-language questions for case law, and tells the agent how to proceed with sibling tools using `doknr`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v1.0.1- First observed
getChanges - First observed
getCoverage - First observed
getNorm - First observed
listCasePassages - First observed
listCitedAuthorities - First observed
listCitingDecisions - First observed
listNormVersions - First observed
resolveIdentifiers - First observed
search
TDQS
Scored across 9 tools
The tools are largely distinct: resolveIdentifiers handles citation grounding, search handles discovery, getNorm/listNormVersions handle statute text, listCitingDecisions/listCitedAuthorities/listCasePassages handle citation graph and case text, getChanges/getCoverage handle freshness and scope. Minor overlap exists between search and getNorm (both can retrieve norm text) and between listCitingDecisions and listCitedAuthorities (both expose citation edges), but the descriptions clearly delineate their roles.
Most tools follow a consistent verb_noun pattern: resolveIdentifiers, getNorm, listNormVersions, listCitingDecisions, listCitedAuthorities, listCasePassages, getChanges, getCoverage. The outlier is 'search', which is a bare verb rather than verb_noun, but it is a common and recognizable convention. Overall the pattern is predictable and readable.
Nine tools is well within the ideal 3-15 range and each tool serves a distinct, necessary function for a legal research server: citation resolution, search, norm retrieval, version history, citation graph (in/out), case text, change feed, and coverage metadata. No tool feels redundant or superfluous.
The surface covers the full research workflow: discover (search), resolve (resolveIdentifiers), read (getNorm, listCasePassages), trace (listCitingDecisions, listCitedAuthorities), track versions (listNormVersions, getChanges), and verify scope (getCoverage). The only minor gap is the absence of a diff tool, but the descriptions explicitly acknowledge this and provide a workaround (fetch two versions and diff manually).
Maintenance
Related MCP Connectors
Verified, citable German & EU law for any LLM. Daily updates from official sources, hosted in DE.
Verified, citable German & EU law for any LLM. Daily updates from official sources, hosted in DE.
Resolve, search and verify legal citations against the official sources, with provenance.
German federal and Land statutes plus court decisions for agents. Keyless, read-only, CC BY 4.0.
Related MCP Servers
- FlicenseAqualityBmaintenanceProvides access to the official German Federal Legal Information Portal (rechtsinformationen.bund.de) enabling AI agents to search German federal laws, court decisions, and legal documentation with authoritative citations from official sources.523-
- AlicenseNot gradedqualityDmaintenanceCite-grade German legal-text infrastructure for LLM agents, providing access to federal, Länder, and EU laws with cryptographic provenance.2Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to search and analyze German legal texts using vector embeddings and semantic search.90MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying 6,870 German federal statutes, case law, and legislative preparatory works directly from AI assistants and MCP-compatible clients.65 npm4Apache 2.0