MCP server providing access to German laws with full-text search, paragraph retrieval, and law listing capabilities
Server implements 3 read-only tools with clear action verbs (get_*, search_*) and valid JSON Schema. Tool descriptions exist but lack depth and do not follow LLM-optimized guidance. Parameter descriptions are present and mostly adequate, though some lack format/constraint details. Output schemas are not explicitly documented. Error handling provides basic recovery hints but is not comprehensive. The server follows a single-responsibility principle (law lookup, paragraph retrieval, fulltext search) which is sound, but descriptions do not anticipate LLM selection criteria or downstream usage. No security or permission issues detected (read-only operations only).
Get a list of available german laws. If `law` is provided, list all laws with similar names.
Get the content of a paragraph of a german law. Example values: - law: BGB, HGB, SGB 5, etc ... - paragraph: 2, 14a, etc ...
Fulltext search over all laws or a specific list of laws. Args: query: The search query (e.g. "Schadensersatz", "Kündigung"). laws: Optional list of law codes to filter by (e.g. ["BGB", "HGB"]).
Tool descriptions lack LLM-optimized structure. They explain WHAT tools do but not WHEN to use them or prerequisites. For example, 'Get a list of available german laws' does not say 'Call this first to discover law abbreviations before using get_paragraph()'. This forces LLMs to infer selection strategy.
Output schemas are not explicitly documented in tool descriptions. Callers do not know what fields are returned or their types. For get_paragraph, the docstring says 'Get the content' but does not specify if the return is a string, JSON object, or structured text with metadata. This forces LLMs to infer structure from observed responses.
Parameter descriptions do not specify format, range, or valid patterns. E.g., 'law' parameter in get_paragraph says 'Law code abbreviation (e.g., BGB, HGB, SGB 5)' but does not state: are spaces allowed? case-insensitive? must match a known law? The 'paragraph' parameter says '14a' is valid but does not specify min/max length or allowed characters. LLMs may pass invalid values.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 65 | 2026-07-28+ | v2 |
| 2026-03-09 | C | 64 | - | v1 |
Error handling is minimal and does not classify errors as retryable vs user-fixable vs fatal. The code in get_lawlibrary returns a German-language message if >50 laws exist, telling users to filter. In search_laws, if a law is not found, it returns 'Law not available', but does not indicate whether this is because the law name was misspelled or the law truly does not exist in the database. No guidance on what to do next.
get_lawlibrary returns free-form JSON when many laws exist, but the response structure is not documented. Callers do not know if the JSON contains an array of law names, objects with {name, abbreviation, url}, or nested metadata. This forces downstream tool calls (get_paragraph) to guess the correct format for 'law' parameter.
No pagination guidance for search_laws. If a fulltext search matches thousands of paragraphs, the tool returns all of them as a JSON array. Large responses blow context windows and waste tokens. Tool description does not specify a limit or pagination mechanism (offset, limit, cursor). Baseline from rubric: paginated results require limit and total_count.