# Open Legal Data (Germany)

> German court decisions (Rechtsprechung) and laws (Gesetze) with citation graph and citation checks.

- name: io.openlegaldata/de
- version: 0.16.5
- connection class: R0 (autonomous)
- trust: 100/100
- quality: 85/100 (new)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/io.openlegaldata%2Fde
- tools: https://api.protogrid.dev/v1/servers/io.openlegaldata%2Fde/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "de": {
      "type": "http",
      "url": "https://de.openlegaldata.io/mcp"
    }
  }
}
```


## Trust

- hygiene: 100
- liveness: 100
- freshness: 100
- provenance: 100
- drivers: +repository +namespace-matches-repo +dns-namespace +website +reachable +uptime-100% +updated-3d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 85/100 (new)

### protocol: 75 (weight 25)

- warn `protocol.modern`: newest supported version is 2025-11-25; 2026-07-28 not supported, older versions are deprecated until 2027-07-28
- n/a `protocol.stateless`: only applies to 2026-07-28 servers
- pass `protocol.transport`: streamable HTTP
- n/a `protocol.list_ttl`: only applies to 2026-07-28 servers

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 94 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 9 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 19 of 19 tools declare readOnlyHint or destructiveHint
- pass `tools.directory_hints`: every tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint
- pass `tools.token_cost`: about 6,829 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump
- pass `tools.hidden_text`: no hidden text in tool names, descriptions, schemas or annotations

### stability: n/a (weight 15)

- n/a `stability.changes`, `stability.rug_pull`, `stability.new_links`: tool history recorded for 3 of the 7 days needed

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 19, about 6,829 tokens to load them all
- tool set hash: 88043a44da4b48f372fa6675c3cf187b
- tools last changed: 2026-11-11T03:39:28.679Z
- badge: [![protogrid quality](https://protogrid.dev/badge/io.openlegaldata/de.svg)](https://protogrid.dev/servers/io.openlegaldata/de)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-11-11 `search_legal` changed (description)
  - before: Search BOTH legislation and court cases in one call. Returns the most relevant law sections AND court decisions for the query, **grouped by type**. Use this when a legal question may be answered by statute or by case law and you don't yet know which — e.g. "Eigenbedarf" surfaces § 573 BGB *and* the leading BGH decisions together. For type-specific control (citation filters, court/date filters), use ``search_cases`` / ``search_laws``. Results are grouped rather than merged into one ranked list on purpose: court decisions are long and out-score short statute texts on relevance, so a naive merged ranking returns only cases and buries the on-point law. Args: query: Search query text (supports Lucene syntax and "phrases"). limit: Max results per type (default 5, max 25). Values above 25 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``.
  - after: Search BOTH legislation and court cases in one call. Returns the most relevant law sections AND court decisions for the query, **grouped by type**. Use this when a legal question may be answered by statute or by case law and you don't yet know which — e.g. "ortsübliche Vergleichsmiete" surfaces § 558 BGB *and* BGH decisions together. For type-specific control (citation filters, court/date filters), use ``search_cases`` / ``search_laws``. Matching is on the words of the text: a law section is found only if it contains the query terms. Colloquial terms that the statute doesn't use (e.g. "Eigenbedarf"; § 573 BGB says "die Räume als Wohnung für sich ... benötigt") find case law but not that section. Then search with the statute's wording, or read the cases' cited sections via ``get_case_references``. Results are grouped rather than merged into one ranked list on purpose: court decisions are long and out-score short statute texts on relevance, so a naive merged ranking returns only cases and buries the on-point law. Args: query: Search query text (supports Lucene syntax and "phrases"). limit: Max results per type (default 5, max 25). Values above 25 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``.
- 2026-11-11 `submit_feedback` changed (description)
  - before: Send feedback about OLDP or this MCP server to the OLDP team. Use this to report bugs (wrong results, errors, broken tools), problems with the legal data (missing or wrong decisions, laws or references), or to request features. Only submit feedback the user wants to send or has agreed to; do not include personal data or confidential case details. Requires a signed-in connection (OAuth or API token); anonymous calls return an error with a sign-up link. Args: category: One of ``feature_request``, ``bug_report``, ``data_issue`` or ``other``. message: The feedback itself, in English or German (20-5000 characters). For bugs, describe what you did, what you expected and what happened instead. subject: Optional one-line summary (max 200 characters). context: Optional technical context (max 2000 characters), e.g. the tool name and arguments involved, case IDs, ECLI or law references. Returns: ``{"submitted": true, ...}`` on success, otherwise ``{"error": ...}``.
  - after: Send feedback about OLDP or this MCP server to the OLDP team. Use this to report bugs (wrong results, errors, broken tools), problems with the legal data (missing or wrong decisions, laws or references), or to request features. Only submit feedback the user wants to send or has agreed to; do not include personal data or confidential case details. Requires a signed-in connection (OAuth or API token); anonymous calls are answered with HTTP 401 and an OAuth challenge, so the client can offer the user to sign in. Args: category: One of ``feature_request``, ``bug_report``, ``data_issue`` or ``other``. message: The feedback itself, in English or German (20-5000 characters). For bugs, describe what you did, what you expected and what happened instead. subject: Optional one-line summary (max 200 characters). context: Optional technical context (max 2000 characters), e.g. the tool name and arguments involved, case IDs, ECLI or law references. Returns: ``{"submitted": true, ...}`` on success, otherwise ``{"error": ...}``.
- 2026-11-11 `search_laws` changed (description)
  - before: Full-text search across law sections via Elasticsearch. Returns matching law sections with highlighted snippets. Does NOT return full text - use get_law_section to retrieve the complete content of a specific section. Args: query: Search query text (supports Lucene syntax). book_code: Optional filter by law book code (e.g. "BGB"). limit: Maximum results (default 10, max 50). Values above 50 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``.
  - after: Full-text search across law sections via Elasticsearch. Returns matching law sections with highlighted snippets. Does NOT return full text - use get_law_section to retrieve the complete content of a specific section. Args: query: Search query text (supports Lucene syntax). book_code: Optional filter by law book code, any case (e.g. "BGB", "BranntwMonG"). An unknown code returns an error with ``suggestions`` instead of an empty result. limit: Maximum results (default 10, max 50). Values above 50 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``.
- 2026-11-11 `list_law_books` changed (description)
  - before: List available German law books (e.g. BGB, StGB, GG). Returns law books with their codes, titles, and section counts. Use this to discover what legislation is available before searching for specific law sections. Args: latest_only: Only show latest revisions (default True). search: Search book codes and titles. limit: Maximum results (default 50, max 200). Values above 200 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``.
  - after: List available German law books (e.g. BGB, StGB, GG). Returns law books with their codes, titles, and section counts. Use this to discover what legislation is available before searching for specific law sections. Args: latest_only: Only show latest revisions (default True). search: Search book codes and titles. Best matches come first (exact code, code prefix, code part, whole word in the title, part of a title word); ``match`` on each result says which. If ``search`` is exactly a book code, titles that only contain it inside a longer word (e.g. "BGBl." for "BGB") are left out. limit: Maximum results (default 50, max 200). Values above 200 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``.
- 2026-11-11 `search_cases` changed (description)
  - before: Full-text search for German court cases via Elasticsearch. Returns matching cases with highlighted snippets. Does NOT return full case text - use get_case to retrieve complete content. The citation filters compose with ``query`` so you can answer "cases citing § 823 BGB that mention 'Mietrecht'" in one call — pass ``query="Mietrecht"`` together with ``cited_law_book="bgb"`` and ``cited_law_section="823"``. For "give me ALL citing cases" without keyword refinement, prefer the dedicated ``get_cases_for_law`` / ``get_citing_cases`` tools. ``cited_case_id`` is mutually exclusive with the law citation filter — if both are supplied, the law filter wins. Args: query: Search query text (supports Lucene syntax). court_code: Filter by court code (e.g. "BGH", "BVerfG"). start_date: Filter cases from this date (YYYY-MM-DD). end_date: Filter cases up to this date (YYYY-MM-DD). decision_type: Filter by decision type (e.g. "Urteil", "Beschluss"). cited_law_book: Restrict to cases citing a law from this book slug (e.g. "bgb"). Requires ``cited_law_section``. cited_law_section: Restrict to cases citing this law section slug (e.g. "823"). Requires ``cited_law_book``. cited_case_id: Restrict to cases citing the case with this id. sort: Result order — "relevance" (default), "date" (newest first), or "most_cited" (most-cited first, for finding landmark precedent). The response echoes the applied ``sort``; any other value returns an error. Each result carries ``citing_cases_count`` so you can see how often it is cited. With relevance sort each result also carries ``match_quality`` ("high"/"medium"/"low" relative to the top hit) so you can tell where relevance drops off; it is left out for "date" and "most_cited", where the score is not the ranking signal. limit: Maximum results (default 10, max 50). Values above 50 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``.
  - after: Full-text search for German court cases via Elasticsearch. Returns matching cases (with ``file_number``) and highlighted snippets. Does NOT return full case text - use get_case to retrieve complete content. The citation filters compose with ``query`` so you can answer "cases citing § 823 BGB that mention 'Mietrecht'" in one call — pass ``query="Mietrecht"`` together with ``cited_law_book="bgb"`` and ``cited_law_section="823"``. For "give me ALL citing cases" without keyword refinement, prefer the dedicated ``get_cases_for_law`` / ``get_citing_cases`` tools. ``cited_case_id`` is mutually exclusive with the law citation filter — if both are supplied, the law filter wins. Args: query: Search query text (supports Lucene syntax). court_code: Filter by court code (e.g. "BGH", "BVerfG"). start_date: Filter cases from this date (YYYY-MM-DD). end_date: Filter cases up to this date (YYYY-MM-DD). decision_type: Filter by decision type (e.g. "Urteil", "Beschluss"). cited_law_book: Restrict to cases citing a law from this book slug (e.g. "bgb"). Requires ``cited_law_section``. cited_law_section: Restrict to cases citing this law section slug, as in the ``slug`` of get_law_section (e.g. "823" for § 823 BGB, "art-14" for Art. 14 GG). Requires ``cited_law_book``. cited_case_id: Restrict to cases citing the case with this id. sort: Result order — "relevance" (default), "date" (newest first), or "most_cited" (most-cited first, for finding landmark precedent). The response echoes the applied ``sort``; any other value returns an error. Each result carries ``citing_cases_count`` so you can see how often it is cited. With relevance sort each result also carries ``match_quality`` ("high"/"medium"/"low" relative to the top hit) so you can tell where relevance drops off; it is left out for "date" and "most_cited", where the score is not the ranking signal. limit: Maximum results (default 10, max 50). Values above 50 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``.
- 2026-11-11 `get_case_statistics` changed (description)
  - before: Get aggregated case statistics. Returns case counts grouped by time period, optionally filtered by court, state, or jurisdiction. Args: court_id: Filter by court ID. state: Filter by state name or slug. jurisdiction: Filter by jurisdiction. Accepts the English shortcuts ("ordinary", "labor", …) or the stored German values ("Ordentliche Gerichtsbarkeit", …). date_after: Count cases from this date (YYYY-MM-DD, default: 1 year ago). date_before: Count cases up to this date (YYYY-MM-DD, default: today). group_by: Time grouping: "month" (default) or "year". Returns an ``{"error": ...}`` payload (instead of silently zero results) when an unknown court_id, state, jurisdiction, group_by, or malformed date is supplied — the previous behavior swallowed bad inputs as ``total: 0`` and was the dangerous failure mode called out in the MCP audit.
  - after: Get aggregated case statistics. Returns case counts grouped by time period, optionally filtered by court, state, or jurisdiction. Without ``date_after`` only the **last 12 months** are counted. For counts over a longer period ("per year since 2018"), pass ``date_after`` (e.g. "2018-01-01") together with ``group_by="year"``. The response's ``date_range`` shows the period that was counted. Args: court_id: Filter by court ID. state: Filter by state name or slug. jurisdiction: Filter by jurisdiction. Accepts the English shortcuts ("ordinary", "labor", …) or the stored German values ("Ordentliche Gerichtsbarkeit", …). date_after: Count cases from this date (YYYY-MM-DD, default: 365 days ago). date_before: Count cases up to this date (YYYY-MM-DD, default: today). group_by: Time grouping: "month" (default) or "year". Returns an ``{"error": ...}`` payload (instead of silently zero results) when an unknown court_id, state, jurisdiction, group_by, or malformed date is supplied — the previous behavior swallowed bad inputs as ``total: 0`` and was the dangerous failure mode called out in the MCP audit.
- 2026-11-11 `filter_cases` changed (description)
  - before: Structured filtering of court cases using the database. Unlike search_cases (which uses full-text search), this tool filters cases using exact database fields. Returns case metadata without full content. Args: court_id: Filter by court database ID. court_slug: Filter by court slug (e.g. "bgh"). date_after: Cases from this date onward (YYYY-MM-DD). date_before: Cases up to this date (YYYY-MM-DD). file_number: Exact file number (Aktenzeichen). ecli: Exact ECLI identifier. decision_type: Decision type (e.g. "Urteil", "Beschluss"). limit: Maximum results (default 20, max 50). Values above 50 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``. offset: Skip first N results for pagination (default 0).
  - after: Structured filtering of court cases using the database. Unlike search_cases (which uses full-text search), this tool filters cases using exact database fields. Returns case metadata without full content, newest first, with ``total`` and ``has_more``. If an exact count takes too long, ``total`` is a lower bound and ``total_is_lower_bound`` is true. A filter combination too broad to answer in time (e.g. a rare ``decision_type`` without court or date filter) returns an ``error`` with a ``hint`` to narrow it. Args: court_id: Filter by court database ID. court_slug: Filter by court slug (e.g. "bgh"). date_after: Cases from this date onward (YYYY-MM-DD). date_before: Cases up to this date (YYYY-MM-DD). file_number: Exact file number (Aktenzeichen). ecli: Exact ECLI identifier. decision_type: Decision type (e.g. "Urteil", "Beschluss"). limit: Maximum results (default 20, max 50). Values above 50 are clamped; the response then includes ``limit_clamped: true`` and the original ``requested_limit``. offset: Skip first N results for pagination (default 0).
- 2026-11-11 `get_court` changed (description)
  - before: Get detailed information about a specific court. Look up a court by ID, slug, or code. Returns full details including address, contact information, and case count. Args: court_id: Court database ID. slug: Court slug (e.g. "ag-berlin-charlottenburg"). code: Court ECLI code (e.g. "AGBCHAR").
  - after: Get detailed information about a specific court. Look up a court by ID, slug, or code. Returns full details including address, contact information, and case count. Args: court_id: Court database ID. slug: Court slug (e.g. "ag-charlottenburg"). code: Court ECLI code (e.g. "AGBECH" for the Amtsgericht Charlottenburg, "BGH").

Full history: https://api.protogrid.dev/v1/servers/io.openlegaldata%2Fde/changes

## Remotes

- https://de.openlegaldata.io/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

_none_

## Tools (19)

- `filter_cases`: Structured filtering of court cases using the database.

        Unlike search_cases (which uses full-text search), this tool filters
        cases using exact database fields. Returns case metadata without
        full content, newest first, with ``total`` and ``has_more``. If an
        exact count takes too long, ``total`` is a lower bound and
        ``total_is_lower_bound`` is true. A filter combination too broad to
        answer in time (e.g. a rare ``decision_type`` without court or date
        filter) returns an ``error`` with a ``hint`` to narrow it.

        Args:
            court_id: Filter by court database ID.
            court_slug: Filter by court slug (e.g. "bgh").
            date_after: Cases from this date onward (YYYY-MM-DD).
            date_before: Cases up to this date (YYYY-MM-DD).
            file_number: Exact file number (Aktenzeichen).
            ecli: Exact ECLI identifier.
            decision_type: Decision type (e.g. "Urteil", "Beschluss").
            limit: Maximum results (default 20, max 50). Values above 50
                are clamped; the response then includes
                ``limit_clamped: true`` and the original ``requested_limit``.
            offset: Skip first N results for pagination (default 0).
        
- `get_case`: Retrieve a court case by ID or slug.

        By default returns the case metadata and the complete, untruncated
        ``content`` as plain text (HTML tags removed, entities decoded,
        whitespace normalized; one line per paragraph, Randnummern as line
        prefix). To read a long decision piece by piece, request a snippet
        with ``offset`` and/or ``length``; both count characters of that
        plain text. In snippet mode ``content`` is omitted and a ``snippet``
        object is returned:
        ``text``, ``offset``, ``length``, ``total_length``, ``has_more`` and
        ``next_offset``. Pass ``next_offset`` as ``offset`` to continue
        reading until ``has_more`` is false.

        Args:
            case_id: Case database ID.
            slug: Case URL slug.
            offset: Start position in plain-text characters (default 0).
            length: Number of plain-text characters to return. 0 (default)
                means "until the end". Leave both at 0 for the full content.
            full_text: Deprecated and ignored (content is never truncated).
                Passing it adds a ``deprecation_warnings`` entry to the
                response.
        
- `get_case_references`: Get forward references FROM a case (what this case cites).

        Returns all laws and cases that the given case references in its
        text. Useful for understanding the legal basis of a decision.

        Args:
            case_id: The database ID of the case.
        
- `get_cases_for_law`: Find all cases that cite a specific law section.

        Returns cases that reference the given statute section in their
        text. Useful for understanding how courts interpret a specific
        provision. To narrow the citing set by keyword, court, or date,
        use ``search_cases(query=..., cited_law_book=..., cited_law_section=...)``
        instead.

        Args:
            book_code: Law book code (e.g. "BGB", "StGB").
            section: Section identifier (e.g. "823").
            law_id: Direct law database ID (alternative to book_code+section).
            sort: "date" (default, newest first) or "most_cited" — the
                latter surfaces the landmark decisions interpreting this
                provision (most-cited first).
            limit: Maximum results (default 20, max 50). Values above 50 are
                clamped; the response then includes ``limit_clamped: true``
                and the original ``requested_limit``.
        
- `get_case_statistics`: Get aggregated case statistics.

        Returns case counts grouped by time period, optionally filtered
        by court, state, or jurisdiction.

        Without ``date_after`` only the **last 12 months** are counted.
        For counts over a longer period ("per year since 2018"), pass
        ``date_after`` (e.g. "2018-01-01") together with ``group_by="year"``.
        The response's ``date_range`` shows the period that was counted.

        Args:
            court_id: Filter by court ID.
            state: Filter by state name or slug.
            jurisdiction: Filter by jurisdiction. Accepts the English
                shortcuts ("ordinary", "labor", …) or the stored German
                values ("Ordentliche Gerichtsbarkeit", …).
            date_after: Count cases from this date (YYYY-MM-DD, default:
                365 days ago).
            date_before: Count cases up to this date (YYYY-MM-DD, default: today).
            group_by: Time grouping: "month" (default) or "year".

        Returns an ``{"error": ...}`` payload (instead of silently zero
        results) when an unknown court_id, state, jurisdiction, group_by,
        or malformed date is supplied — the previous behavior swallowed
        bad inputs as ``total: 0`` and was the dangerous failure mode
        called out in the MCP audit.
        
- `get_citing_cases`: Get reverse references TO a case (cases that cite this case).

        Find all cases that reference the given case in their text.
        Useful for understanding the impact and precedent value of a
        decision. To narrow the citing set by keyword, court, or date,
        use ``search_cases(query=..., cited_case_id=case_id)`` instead.

        Args:
            case_id: The database ID of the cited case.
            sort: "date" (default, newest first) or "most_cited" (the most
                influential citing cases first).
            limit: Maximum results (default 20, max 50). Values above 50 are
                clamped; the response then includes ``limit_clamped: true``
                and the original ``requested_limit``.
        
- `get_court`: Get detailed information about a specific court.

        Look up a court by ID, slug, or code. Returns full details including
        address, contact information, and case count.

        Args:
            court_id: Court database ID.
            slug: Court slug (e.g. "ag-charlottenburg").
            code: Court ECLI code (e.g. "AGBECH" for the Amtsgericht
                Charlottenburg, "BGH").
        
- `get_law_section`: Get the full text of a specific law section.

        Retrieve law text by book code and section number, or by law ID.
        For example, get_law_section(book_code="BGB", section="823") returns
        the text of section 823 of the German Civil Code.

        By default the complete, untruncated ``content`` is returned as plain
        text (HTML tags removed, entities decoded, whitespace normalized; one
        line per paragraph or list item). Set ``offset`` and/or ``length`` to
        get a ``snippet`` of that plain text instead (see get_case for the
        snippet fields and pagination via ``next_offset``).

        Args:
            book_code: Law book code (e.g. "BGB", "StGB", "GG").
            section: Section identifier. Accepts bare numbers ("823",
                "20", "16a") or prefixed forms ("§ 823", "§823",
                "Art. 14", "Art 14", "Artikel 1"). The prefix spelling
                does not have to match the book: "Art. 20", "Artikel 20"
                and "20" all find Art 20 GG. Only exact sections match,
                never a longer number that contains the input. The
                ``section`` field on the response is whatever the DB
                stores, which differs by book convention: BGB / StGB /
                ZPO etc. store ``§ N`` (e.g. ``"§ 823"``), article-based
                books store e.g. ``"Art 1"`` (GG) or ``"Art. 6"``
                (DSGVO).
            law_id: Direct law database ID (alternative to book_code+section).
            offset: Start position in plain-text characters (default 0).
            length: Number of plain-text characters to return. 0 (default)
                means "until the end". Leave both at 0 for the full content.
        
- `get_platform_info`: Get OLDP platform coverage summary.

        Returns an overview of the data available on the Open Legal Data
        Platform, including counts of cases, laws, courts, and references.
        Call this first to understand what data you can search and retrieve.
        
- `get_server_instructions`: Return MCP server instructions (if any). Always call first.
- `get_similar_cases`: Find court cases textually similar to a given case.

        Seeds an Elasticsearch "more like this" query with the full text of
        the given case and returns the most similar OTHER cases, ranked by
        similarity. Useful for comparative research: once you have one
        on-point decision, surface neighbouring case law without crafting a
        keyword query. For keyword- or citation-scoped neighbours instead,
        use search_cases.

        Args:
            case_id: The database ID of the seed case.
            limit: Maximum results (default 10, max 50). Values above 50 are
                clamped; the response then includes ``limit_clamped: true``
                and the original ``requested_limit``.
        
- `list_courts`: Browse and filter German courts.

        Returns a list of courts matching the given filters. Use this to
        discover which courts are available before searching for cases.

        Args:
            court_type: Filter by court type code (e.g. "AG", "LG", "OLG",
                "BGH", "VG", "OVG", "BVerwG", "ArbG", "LAG", "BAG").
            state: Filter by state name or slug (e.g. "Berlin", "bayern").
            jurisdiction: Filter by jurisdiction. Accepts the English
                shortcuts "ordinary", "administrative", "labor", "social",
                "fiscal", "constitutional" or the stored German values
                ("Arbeitsgerichtsbarkeit", …). The Bundespatentgericht
                (BPatG) belongs to ``ordinary``; there is no separate
                patent-jurisdiction category — filter on
                ``court_type="BPatG"`` if you specifically want patent
                cases.
            level_of_appeal: Filter by court level. Accepts the English
                shortcuts "local", "regional", "high", "federal" or the
                stored German values ("Amtsgericht", …).
            search: Search court names and aliases.
            limit: Maximum results to return (default 50, max 100). Values
                above 100 are clamped; the response then includes
                ``limit_clamped: true`` and the original ``requested_limit``.
        
- `list_law_books`: List available German law books (e.g. BGB, StGB, GG).

        Returns law books with their codes, titles, and section counts.
        Use this to discover what legislation is available before searching
        for specific law sections.

        Args:
            latest_only: Only show latest revisions (default True).
            search: Search book codes and titles. Best matches come first
                (exact code, code prefix, code part, whole word in the
                title, part of a title word); ``match`` on each result says
                which. If ``search`` is exactly a book code, titles that only
                contain it inside a longer word (e.g. "BGBl." for "BGB")
                are left out.
            limit: Maximum results (default 50, max 200). Values above 200
                are clamped; the response then includes
                ``limit_clamped: true`` and the original ``requested_limit``.
        
- `search_cases`: Full-text search for German court cases via Elasticsearch.

        Returns matching cases (with ``file_number``) and highlighted
        snippets. Does NOT return full case text - use get_case to retrieve
        complete content.

        The citation filters compose with ``query`` so you can answer
        "cases citing § 823 BGB that mention 'Mietrecht'" in one call —
        pass ``query="Mietrecht"`` together with ``cited_law_book="bgb"``
        and ``cited_law_section="823"``. For "give me ALL citing cases"
        without keyword refinement, prefer the dedicated
        ``get_cases_for_law`` / ``get_citing_cases`` tools.
        ``cited_case_id`` is mutually exclusive with the law citation
        filter — if both are supplied, the law filter wins.

        Args:
            query: Search query text (supports Lucene syntax).
            court_code: Filter by court code (e.g. "BGH", "BVerfG").
            start_date: Filter cases from this date (YYYY-MM-DD).
            end_date: Filter cases up to this date (YYYY-MM-DD).
            decision_type: Filter by decision type (e.g. "Urteil", "Beschluss").
            cited_law_book: Restrict to cases citing a law from this
                book slug (e.g. "bgb"). Requires ``cited_law_section``.
            cited_law_section: Restrict to cases citing this law section
                slug, as in the ``slug`` of get_law_section (e.g. "823" for
                § 823 BGB, "art-14" for Art. 14 GG). Requires
                ``cited_law_book``.
            cited_case_id: Restrict to cases citing the case with this id.
            sort: Result order — "relevance" (default), "date" (newest
                first), or "most_cited" (most-cited first, for finding
                landmark precedent). The response echoes the applied
                ``sort``; any other value returns an error. Each result
                carries ``citing_cases_count`` so you can see how often it
                is cited. With relevance sort each result also carries
                ``match_quality`` ("high"/"medium"/"low" relative to the
                top hit) so you can tell where relevance drops off; it is
                left out for "date" and "most_cited", where the score is
                not the ranking signal.
            limit: Maximum results (default 10, max 50). Values above 50 are
                clamped; the response then includes ``limit_clamped: true``
                and the original ``requested_limit``.
        
- `search_laws`: Full-text search across law sections via Elasticsearch.

        Returns matching law sections with highlighted snippets. Does NOT
        return full text - use get_law_section to retrieve the complete
        content of a specific section.

        Args:
            query: Search query text (supports Lucene syntax).
            book_code: Optional filter by law book code, any case (e.g.
                "BGB", "BranntwMonG"). An unknown code returns an error
                with ``suggestions`` instead of an empty result.
            limit: Maximum results (default 10, max 50). Values above 50 are
                clamped; the response then includes ``limit_clamped: true``
                and the original ``requested_limit``.
        
- `search_legal`: Search BOTH legislation and court cases in one call.

        Returns the most relevant law sections AND court decisions for the
        query, **grouped by type**. Use this when a legal question may be
        answered by statute or by case law and you don't yet know which —
        e.g. "ortsübliche Vergleichsmiete" surfaces § 558 BGB *and* BGH
        decisions together. For type-specific control (citation filters,
        court/date filters), use ``search_cases`` / ``search_laws``.

        Matching is on the words of the text: a law section is found only
        if it contains the query terms. Colloquial terms that the statute
        doesn't use (e.g. "Eigenbedarf"; § 573 BGB says "die Räume als
        Wohnung für sich ... benötigt") find case law but not that section.
        Then search with the statute's wording, or read the cases' cited
        sections via ``get_case_references``.

        Results are grouped rather than merged into one ranked list on
        purpose: court decisions are long and out-score short statute
        texts on relevance, so a naive merged ranking returns only cases
        and buries the on-point law.

        Args:
            query: Search query text (supports Lucene syntax and "phrases").
            limit: Max results per type (default 5, max 25). Values above 25
                are clamped; the response then includes ``limit_clamped:
                true`` and the original ``requested_limit``.
        
- `submit_feedback`: Send feedback about OLDP or this MCP server to the OLDP team.

        Use this to report bugs (wrong results, errors, broken tools),
        problems with the legal data (missing or wrong decisions, laws or
        references), or to request features. Only submit feedback the user
        wants to send or has agreed to; do not include personal data or
        confidential case details. Requires a signed-in connection (OAuth or
        API token); anonymous calls are answered with HTTP 401 and an OAuth
        challenge, so the client can offer the user to sign in.

        Args:
            category: One of ``feature_request``, ``bug_report``,
                ``data_issue`` or ``other``.
            message: The feedback itself, in English or German
                (20-5000 characters). For bugs, describe what you did, what
                you expected and what happened instead.
            subject: Optional one-line summary (max 200 characters).
            context: Optional technical context (max 2000 characters), e.g.
                the tool name and arguments involved, case IDs, ECLI or law
                references.

        Returns:
            ``{"submitted": true, ...}`` on success, otherwise ``{"error": ...}``.
        
- `validate_citation`: Check if a legal citation exists in the OLDP database.

        Validates Aktenzeichen (file numbers), ECLI identifiers, or
        paragraph references (e.g. "§ 823 BGB"). Use this to verify
        citations before presenting them to users.

        Args:
            citation: The citation to validate (e.g. "VI ZR 123/22",
                "ECLI:DE:BGH:2023:...", "§ 823 BGB").
            citation_type: Type hint: "auto" (default), "file_number",
                "ecli", or "law_reference".
        
- `whoami`: Show who you are connected as and your remaining request budget.

        Call this before a long task to check how many requests are left,
        or to learn how to get a larger budget. Every HTTP request to the
        MCP server counts against the budget, including this call; once
        nothing is left, requests (this one too) are rejected with HTTP 429
        until the window frees up. Returns:

        - ``authenticated``: whether the connection is signed in.
        - ``user``: ``username`` and ``profile_complete``, or null.
        - ``auth_method``: ``oauth``, ``api_token``, ``legacy_token`` or
          ``session``; null when anonymous.
        - ``rate_limit``: ``tier`` (``anonymous``, ``registered``,
          ``enriched`` or ``custom``), ``bucket`` (``shared`` when all
          anonymous users of this connector share one budget, ``ip`` or
          ``user``), ``limit`` per ``window_seconds``, ``used``,
          ``remaining``, and ``retry_after_seconds`` once nothing is left.
          Signed-in users share one budget between MCP and the REST API.
        - ``upgrade``: how to get a larger budget (``action``, ``url``,
          ``limit``, ``message``), or null. Pass the ``message`` and
          ``url`` on to the user when the budget is too small for the task.
        
