Skip to main content
Glama

nl-eli-mcp

Install (one command)

Published on PyPI + MCP Registry (io.github.matematicsolutions/nl-eli-mcp). Run without cloning:

uvx nl-eli-mcp

Configure your MCP client (stdio):

{ "mcpServers": { "nl-eli-mcp": { "command": "uvx", "args": ["nl-eli-mcp"] } } }

Windows 11 with Smart App Control

Smart App Control blocks unsigned executables, which covers uvx.exe, pip.exe and the nl-eli-mcp.exe launcher that pip writes at install time. The python.exe and py.exe from the python.org installer are signed by the Python Software Foundation, so running the module through the interpreter works:

python -m pip install nl-eli-mcp
python -m nl_eli_mcp

pip.exe is blocked for the same reason, so install with python -m pip, not pip install. If python is not on PATH, use the Windows launcher: py -3 -m nl_eli_mcp.

{ "mcpServers": { "nl-eli-mcp": { "command": "python", "args": ["-m", "nl_eli_mcp"] } } }

Do not turn Smart App Control off to work around this - it cannot be re-enabled without reinstalling Windows.

Building from source: see Install.

An MCP server for the Dutch consolidated legislation BWB (Basiswettenbestand), served by KOOP over the official SRU API (zoekservice.overheid.nl, keyless). It gives an AI agent the version of an act in force on a given date, with a verifiable citation: a persistent identifier, a human-readable citation, and a link to the official source.

Part of the eu-legal-mcp line by MateMatic — one connector per EU member state, the same citation contract everywhere.

On ELI. The Netherlands does not publish native ELI (/eli/) URIs on consolidated BWB. To keep the line's contract honest, eli_uri carries the official persistent identifier instead — the wetten.overheid.nl/id toestand URI (e.g. http://wetten.overheid.nl/id/BWBR0005537/2026-06-04/0). The connector never fabricates an /eli/ URI and says so in its tool instructions. See DISCOVERY.md.

Related MCP server: Agent.ai MCP Server

Tools

Tool

What it does

nl_search(query, on_date=today)

Find acts by words in the title that are in force on a date. Returns distinct acts, each with the citation contract.

nl_get_act(bwb_id, on_date=today)

Metadata for one act (e.g. BWBR0005537) — identifier, title, authority, version date.

nl_get_text(bwb_id, on_date=today)

The full consolidated XML (BWB toestand) of one act.

nl_case_search(date_from, date_to, ...)

List court decisions (Rechtspraak Open Data) by date range / court / subject. No free-text; each hit carries a native ecli.

nl_get_decision(ecli)

A court decision by its ECLI (e.g. ECLI:NL:HR:2020:1) — court, dates, zaaknummer and full text.

nl_coverage()

Declare what this connector covers, when each family was captured, and - explicitly - what it does NOT cover. Every gap carries a fallback.

Legislation comes from the BWB (KOOP SRU); case law comes from Rechtspraak Open Data (data.rechtspraak.nl), keyed by native ECLI. Every response carries the citation contract:

  • eli_uri — the official persistent identifier (toestand URI; see the ELI note above).

  • human_readable_citation — the official short title (citeertitel), e.g. Algemene wet bestuursrecht.

  • source_url — the browsable wetten.overheid.nl page for that version.

Versions and dates

Each act has many time-stamped versions. The tools default to the version in force today; pass on_date (YYYY-MM-DD) to pin a historical or future version. An act with no version valid on that date returns not_found — retry with another on_date.

Install

pip install -e ".[dev]"

Register it with your MCP client (see .mcp.json.example):

{
  "mcpServers": {
    "nl-eli-mcp": {
      "command": "nl-eli-mcp",
      "env": {
        "NL_ELI_BASE_URL": "https://zoekservice.overheid.nl/sru/Search",
        "NL_ELI_CACHE_DIR": "~/.matematic/cache/nl-eli",
        "NL_ELI_AUDIT_DIR": "~/.matematic/audit"
      }
    }
  }
}

Design

  • Public data only. Read-only against the keyless KOOP SRU API and the official repository host; nothing is sent beyond the query / identifier and the date.

  • Audit log. Every call appends one JSON line to ~/.matematic/audit/nl-eli-mcp.jsonl (AI Act art. 12 record-keeping).

  • Vendor-neutral. No LLM provider, no telemetry; own backoff + on-disk cache.

  • No fabrication. Identifiers and titles are parsed from the source record. If KOOP's schema changes, the connector fails loudly rather than returning stale or invented data.

See CONSTITUTION.md (the 4 principles) and DISCOVERY.md (how the source was mapped).

Tests

pytest tests/test_instructions_drift.py tests/test_parse.py   # offline
pytest tests/test_smoke.py                                     # live KOOP API

Licence

Apache-2.0. The Dutch legislation served is official public data of the Kingdom of the Netherlands; this connector adds no rights over it.

Available Tools

6 tools
nl_coverageA
Read-onlyIdempotent

Declare what this connector covers, how it is sourced, and what it does NOT cover.

Call this before telling a user that the law "does not contain" something, and whenever a search comes back empty: the absence may be a gap in this connector rather than in the law. Every gap carries a fallback saying where to look instead.

Returns: Coverage with families, an as-of note, and a non-empty list of known gaps.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusNo
familiesNo
as_of_noteYesStates what the dates mean, and what they do not promise.
known_gapsNoNever empty. An empty list would mean 'not checked', not 'no gaps'.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnly, openWorld, idempotent), the description discloses important behavioral semantics: this tool is a safeguard against false negatives, may reveal connector gaps rather than legal absence, and returns a structured Coverage object with families, an as-of note, and fallback locations. This is substantive context not implied by 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose, then provides usage triggers, and ends with a clean return-value summary. Every sentence contributes meaningful guidance, with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with an output schema, the description covers why to call it, when to call it, what it returns, and what business consequence follows from its results. No critical operational information is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is no parameter semantics to document. The baseline for no-parameter tools is 4, and the description appropriately focuses on output semantics instead.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise purpose: 'Declare what this connector covers, how it is sourced, and what it does NOT cover.' This clearly identifies a distinct meta-tool that reports coverage rather than performing legal search or retrieval, differentiating it from siblings like nl_search and nl_get_act.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit call conditions: use before telling a user the law 'does not contain' something, and whenever a search comes back empty. It also explains the rationale—absence may be a gap in the connector not the law—and notes that every gap points to a fallback source, giving the agent actionable guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nl_get_actA
Read-onlyIdempotent

Fetch metadata for the version of a Dutch act in force on a date.

ParametersJSON Schema
NameRequiredDescriptionDefault
bwb_idYese.g. ``"BWBR0005537"``.
on_dateNooptional ``YYYY-MM-DD``; defaults to today.

Output Schema

ParametersJSON Schema
NameRequiredDescription
titleNo
bwb_idNo
eli_uriNo
act_typeNo
text_urlNo
authorityNo
source_urlNo
legal_areasNo
version_dateNo
date_modifiedNo
human_readable_citationNo

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description does not add behavioral details beyond stating it fetches metadata, which is consistent with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, front-loaded, no unnecessary words. Every part earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With comprehensive annotations and an existing output schema, the description is adequate for a simple metadata fetch tool. It could explicitly state that it only returns metadata, but that is implied.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with descriptions already present in the input schema. The description merely repeats these (e.g., example for bwb_id and default for on_date), adding no new meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it fetches metadata for a version of a Dutch act in force on a date, using a specific verb and resource. It is distinct from sibling tools that deal with cases, decisions, text, or search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The context is clear: this tool is for fetching metadata of Dutch acts. While no explicit alternatives or when-not-to-use guidance is provided, the sibling tool names alone allow inference of differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nl_get_decisionA
Read-onlyIdempotent

Fetch a Dutch court decision by its ECLI (Rechtspraak Open Data).

ParametersJSON Schema
NameRequiredDescriptionDefault
ecliYese.g. ``ECLI:NL:HR:2020:1``.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dateNo
ecliNo
textNo
courtNo
titleNo
issuedNo
subjectNo
byte_sizeNo
source_urlNo
zaaknummerNo
dataset_noteNo
human_readable_citationNo

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, destructiveHint=false. Description adds source context (Rechtspraak Open Data) but no additional behavioral details like error handling or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, 13 words, zero wasted information. Front-loaded with purpose and key identifier.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter fetch tool with output schema and thorough annotations, the description covers the essential purpose and source. No missing critical information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%. The description adds an example for the ecli parameter, but the schema already includes a similar example. No additional semantics beyond what schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the action (Fetch), resource (Dutch court decision), and method (by its ECLI). It distinguishes from siblings like nl_case_search by specifying the exact identifier.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implied usage: use when you have a known ECLI. However, no explicit guidance on when to avoid this tool or alternative tools (e.g., use nl_case_search if you don't have an ECLI).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nl_get_textA
Read-onlyIdempotent

Fetch the full consolidated XML of a Dutch act in force on a date.

ParametersJSON Schema
NameRequiredDescriptionDefault
bwb_idYese.g. ``"BWBR0005537"``.
on_dateNooptional ``YYYY-MM-DD``; defaults to today.

Output Schema

ParametersJSON Schema
NameRequiredDescription
bwb_idYes
formatNo
contentNo
eli_uriNo
on_dateYes
text_urlNo
byte_sizeNo
source_urlNo
dataset_noteNo
version_dateNo
human_readable_citationNo

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and idempotent behavior. The description adds context about the return format (XML) and date filtering, but does not disclose potential pagination or size limits. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence with no redundancy. Efficiently conveys the tool's purpose and constraints.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given rich annotations, output schema presence, and simple parameters, the description provides sufficient context for correct use without missing critical details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with clear parameter descriptions (bwb_id example, on_date format and default). The description adds no extra meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it fetches the full consolidated XML of a Dutch act, specifying scope (in force on a date) and distinguishing it from sibling tools like nl_get_act which may return different formats.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives such as nl_get_act or nl_search. The description implies usage for fetching XML data but does not exclude other use cases.

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.

  1. 1 tool updatev0.4.3
    • Addednl_coverage
  2. 5 tool updatesv0.2.0
    • First observednl_case_search
    • First observednl_get_act
    • First observednl_get_decision
    • First observednl_get_text
    • First observednl_search

TDQS

A4.2/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a clearly distinct operation: searching acts, fetching act metadata, fetching act text, searching cases, fetching a specific decision, and describing coverage. There is no realistic overlap that could lead an agent to pick the wrong tool.

Naming Consistency4/5

All tools share the nl_ prefix, which creates a recognizable namespace, but the internal pattern is not uniform: nl_get_* uses verb-first naming, while nl_case_search is object-first and nl_coverage is a bare noun. This is a minor inconsistency rather than a confusing mix.

Tool Count5/5

Six tools is well-scoped for a legal information connector covering both legislation and case law. Each tool serves a necessary retrieval or orientation purpose, and none feels redundant.

Completeness5/5

The set covers search, metadata retrieval, and full-text retrieval for acts, plus metadata-based search and full-decision retrieval for case law. The dedicated coverage tool explicitly documents limitations and fallbacks, which closes the main practical gap in legal data connectors.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    An intelligent MCP server that enables AI agents to crawl, index, and semantically search official framework documentation using local RAG. It prevents hallucinations by providing precise, up-to-date documentation excerpts directly into the AI's context window.
    1
    -
  • A
    license
    C
    quality
    D
    maintenance
    An MCP server that integrates with the Agent.ai API to provide web text extraction, web screenshots, and YouTube transcript capabilities through a dynamic function loading system.
    100
    14
    4
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that provides tools to fetch live, version-accurate documentation, changelogs, examples, and method signatures for npm and PyPI packages, preventing AI coding agents from hallucinating stale APIs.
    15
    ISC
  • F
    license
    Not graded
    quality
    D
    maintenance
    This MCP server provides LLMs with a live, curated knowledge base of AI agent research, world models, and source-code reviews, enabling personalized and context-aware responses. Users can either connect to the hosted knowledge or build and host their own vault.
    -