Lex: Luxembourg Law MCP Server
Lex provides read-only, point-in-time retrieval and analysis of Luxembourg and EU legal texts via MCP tools. You can:
Retrieve exact document versions as of a specific date with
as_of(full, outline, or selected articles).Get a document's complete version history with
timeline.List all works in force on a given date with
in_force_on.Compare document states between two dates with
diff.Perform full-text search with filters and ranked results via
search(returns metadata only).Trace every distinct version of a specific article/provision with
article_history.Verify authenticity and chain of custody via
provenance.Check corpus coverage and known gaps by publisher with
coverage.Find articles that cite a given law with
cited_by.Identify which works gained new versions in a period with
changes_in_period.Use the curated CC-BY dataset of articles with validity dates for RAG applications.
The server is designed for machine readability, supporting AI agents and legal-tech workflows with verifiable, hallucination-free outputs.
Lex
Point-in-time retrieval of regulatory text. Regulators publish the current rule; every audit, investigation and dispute is about a past date. Lex keeps every version it has seen and answers "what did this say on 15 March 2022?" with the exact validity interval, the timeline, the instrument that changed it, and a hashed provenance record, and an honest, machine-readable refusal when it cannot know.
Live demo · Search held law · MCP endpoint · Dataset (CC-BY) · Examples · Architecture dossier · Benchmarks · Verify it yourself · Program · Retrieval + agent plan · Spec (D1-D82) · Corpus revalidation · Snapshot retention
74-second engineering demo

Dated retrieval → deterministic keyword or optional local hybrid search → exact EU article → verified temporal diff → evidence export → deployed architecture. Watch the narrated, continuous-browser MP4 or read the release evidence.
Related MCP server: conformi-search
Try it in 30 seconds
Give any MCP-capable AI the full toolset, no key, no install:
claude mcp add --transport http lex https://law.soufien.lu/mcpModern clients such as VS Code and Cursor connect to the hosted endpoint directly:
{ "servers": { "lex": { "type": "http", "url": "https://law.soufien.lu/mcp" } } }For a client that only accepts local stdio servers, bridge to the same hosted
endpoint with a pinned version of the third-party mcp-remote adapter (Node.js 18+):
npx -y mcp-remote@0.1.38 https://law.soufien.lu/mcpThe hosted endpoint is canonical: no legal corpus, vector files or Azure credentials are downloaded to the client. Lex also publishes its remote-server metadata to the official MCP Registry from GitHub Actions using OIDC. Lex intentionally does not publish an npm package: the command above is a compatibility bridge for older clients, not a second implementation.
The following is a historical V2 example. The public assistant is temporarily unavailable while Lex installs its deterministic V3 answer path; search, direct law pages and MCP remain available. Historical answer, verbatim:
Q: What did CRR Article 92 require as capital ratios on 1 March 2020, and has that text changed since?
Quoted verbatim (Article 92(1)) from the CRR version in force on that date: "Subject to Articles 93 and 94, institutions shall at all times satisfy the following own funds requirements: (a) a Common Equity Tier 1 capital ratio of 4,5 %; (b) a Tier 1 capital ratio of 6 %; (c) a total capital ratio of 8 %." ,
eu-eurlex:32013r0575:2019-12-25(valid 2019-12-25 → 2020-06-26), permalink.Article 92 has had seven distinct texts: 2013-06-26 → 2013-06-27, 2013-06-28 → 2019-12-24, 2019-12-25 → 2020-06-26, 2020-06-27 → 2021-06-28, 2021-06-29 → 2022-12-31, 2023-01-01 → 2024-12-31 and 2025-01-01 onward, each with its own permalink and sha256.
Every claim in that historical answer came from a deterministic tool call (the trace was shown under each reply); the model did not answer from its own memory. Do not take this file's word for it, the numbers above are checkable in one call, and if they ever drift from the live system, that is a bug worth reporting:
curl -s -X POST https://law.soufien.lu/mcp -H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"article_history",
"arguments":{"work":"eu-eurlex:32013r0575","anchor":"art_92"}}}'Who uses this
A compliance officer checking which text of an obligation was in force on the date of the facts, with a permalink and a hash for the file.
A legal-tech developer building RAG over law that must not hallucinate versions: per-article chunks with
valid_from/valid_toto filter before similarity (dataset).An external AI agent using the public MCP tools directly. The site's own assistant is unavailable during the V3 answer-path replacement.
A researcher tracking how one article's text evolved across amendments (
article_history: every distinct text state, dated).
What it never does
Lex answers what the rule was. It does not decide "were we compliant?", "does this apply to me?", or "what does this mean?", those are professional opinions. The evidence, index and MCP layers never generate or interpret legal text (fitness rule F10). The reviewed V3 assistant design may later explain retrieved evidence, but that path is currently contained and is not part of the record.
Architecture (one screen)
APPS Lex.Ingest (CLI) Lex.Mcp.Stdio (local host) Lex.Web (site + HTTP MCP) Lex.Ask (V3 replacement, contained)
PROTOCOL Lex.Mcp (legal tools + official MCP SDK bridge; transport-neutral library)
DERIVED Lex.Derive, evidence -> provision Markdown+JSON (immutable profiles include akn-lu/1, akn-lu/2, akn-lu-identical-scl-duplicate/1, akn-lu-document/1, pdf-memorial-lu/2, fmx4-eu/1, xhtml-eu/1)
ADAPTERS Lex.Sources.Legilux (Tier A, SPARQL) Lex.Sources.EurLex (Tier A, Cellar + Formex)
MODEL Lex.Law, Publisher, Work, Version, Expression, Observation. No publisher names.
FOUNDATION Lex.Temporal (interval algebra) Lex.Index (SQLite: filter-first, verified artifacts)One corpus repo per publisher; the corpus is human-readable JSON + git. The tree carries the legislative history,
git logcarries the ingest history, and the two are deliberately not the same (why).Bitemporal: valid time is the publisher's; transaction time is ours, as append-only observation chains inside hashed content. Nothing is ever overwritten; publisher corrections become visible events.
Two layers: verbatim publisher bytes (evidence) → deterministic per-article extraction (consumption). Every derived article hash-chains to the exact bytes the state published;
lex verify derivere-derives and byte-compares.Legal and temporal eligibility before fusion and final ranking, enforced by a non-optional
FilterSeton the only query entry point. Hybrid may use a bounded binary-vector preselection for speed, but an ineligible candidate can never enter the fused result set.Signed whole-artifact manifests (ECDSA P-256): a trust root pinned in the application verifies indexes, vectors, embedding assets, scope, benchmark and source commits before any file is mounted. The embedded index stamp remains public provenance, not its own trust root.
Release-gated assistant behavior: 25 frozen scenarios validate the typed plan, arguments, outcomes, UI effects, answer and latency against an immutable zero-traffic candidate. The catalog records author
Lex release engineering; Evaluation reviewer Soufien Hajji uses a separate signing authority. This project-owner review is not a third-party audit. Candidate and release-grader tokens are budgeted separately. The current maximum reservation is EUR 0.5362647 under an outer EUR 10 preflight and measured-use ceiling, not a live billing cutoff. The release dossier shows the CI/CD flow and evaluation mechanics.Honest refusals:
no_version_for_date,anchor_not_in_version,outside_observed_window,text_not_available,text_withheld, a flagged wrong answer is still a wrong answer, so Lex refuses instead.
Current coverage
Luxembourg (Legilux, Tier A): every work and dated version currently mounted
from the publisher's Consolidation catalogue. Nothing in that collection is
filtered out by legal form. Counts, dates, corpus commit and extraction-profile
mix are read from the index on the
live coverage page, rather than copied into
product prose that becomes stale after the next publisher run.
The consolidation catalogue is not all Luxembourg law. The same official
endpoint exposes 150,187 resources classified as Act, including laws,
grand-ducal regulations, ministerial regulations and orders that may never have
received a consolidation record. That broad number also contains notices and
other material that should not all enter lawyer-facing search. The measured
boundary and the proposed normative-act increment are documented in
Luxembourg scope.
Where official XML exists, text is retained as verbatim Akoma Ntoso. The
deterministic pdf-lu/1 fallback handles eligible born-digital consolidated
PDFs and records that article boundaries came from typography rather than
publisher markup. Narrow pdf-memorial-lu/2 recovery first verifies the requested
act inside an official-gazette issue, then exposes only a strongly identified
section and visibly labels its inferred boundaries in the reader. Thematic
folders, unverified gazette matches and fileless records remain metadata-only;
Lex does not trade provenance for a larger text count. Exact text availability
and extraction-profile mix are reported from the mounted artifact on the
coverage page.
EU (EUR-Lex/Cellar, Tier A): a reviewed Luxembourg-facing scope spanning financial services, AML, corporate, competition, tax, employment, consumer, procurement, environmental, judicial-cooperation, intellectual-property, data, digital, cyber and energy law, plus bounded legal-history relationships. The mounted index and live coverage page are the source of truth for work and version counts. Full text comes from the Publications Office's Formex 4 structural XML where served, including large consolidations the XHTML channel cannot carry. The present EU limit is scope, not format.
The derived dataset publishes its current counts and source commits in its release catalog. The broader Luxembourg original-act catalogue and approved EU scope are tracked by the temporal expansion program. Communal regulations are deliberately out of scope: 17,232 exist as published acts, none is ever consolidated, so there is no point-in-time history to hold. The fallback ladder for XML-less versions is spec D49.
Run it
LEX_CODE_COMMIT=$(git rev-parse HEAD)
LEX_ARTICLES_COMMIT=$(git -C ../lex-articles rev-parse HEAD)
LEX_LU_CORPUS_COMMIT=$(git -C ../lex-corpus-lu-legilux rev-parse HEAD)
LEX_EU_CORPUS_COMMIT=$(git -C ../lex-corpus-eu-eurlex rev-parse HEAD)
# One exact completed-enumeration identity. Reuse it only when retrying that same run.
LEX_INGEST_RUN_ID=manual-example-001
# ingest (paced, sequential; official open-data channels only)
dotnet run --project src/Lex.Ingest -- ingest --publisher lu-legilux \
--corpus ../lex-corpus-lu-legilux --code-commit "$LEX_CODE_COMMIT" \
--run-id "$LEX_INGEST_RUN_ID"
# derive the per-article layer, build the signed index
dotnet run --project src/Lex.Ingest -- derive --publisher lu-legilux --corpus ../lex-corpus-lu-legilux --out ../lex-articles
dotnet run --project src/Lex.Ingest -- index --corpus ../lex-corpus-lu-legilux --articles ../lex-articles \
--out indexes/index-lu-legilux.db --keyfile signing-key.pem \
--capability-policy deploy/capability-policy.json \
--code-commit "$LEX_CODE_COMMIT" --articles-commit "$LEX_ARTICLES_COMMIT" \
--corpus-commit "$LEX_LU_CORPUS_COMMIT"
# resumable large semantic backfill on a reviewed Windows DirectML adapter
dotnet build src/Lex.Ingest -c Release -p:UseDirectML=true
src/Lex.Ingest/bin/Release/net10.0/Lex.Ingest index \
--corpus ../lex-corpus-eu-eurlex --articles ../lex-articles \
--out indexes/index-eu-eurlex.db --embedding-model model \
--vectors indexes/index-eu-eurlex.vectors \
--embedding-directml-device 1 --embedding-batch-size 256 \
--embedding-max-batch-tokens 32768 \
--embedding-cache build-cache/eu-eurlex-embeddings.db \
--capability-policy deploy/capability-policy.json \
--code-commit "$LEX_CODE_COMMIT" --articles-commit "$LEX_ARTICLES_COMMIT" \
--corpus-commit "$LEX_EU_CORPUS_COMMIT"
# The chunker fixes legal-text boundaries before the GPU groups immutable chunks
# into 32/64/128/256/512-token inference buckets. A fixed padded-token budget reduces
# the item count for long buckets so one reviewed batch size cannot exhaust the GPU.
# Masked padding is never stored.
# web demo + MCP (stdio) locally
LEX_INDEX_DIR=indexes dotnet run --project src/Lex.Web
LEX_INDEX_DIR=indexes dotnet run --project src/Lex.Mcp.StdioLex.Mcp contains the legal tools and official SDK bridge, not a deployment entry point.
The standalone stdio executable is isolated in Lex.Mcp.Stdio; production composes the same
library into Lex.Web for Streamable HTTP. Co-hosting is deliberate while site and MCP traffic
share one immutable index set and one scale/SLA boundary. D67 records the measured triggers for
extracting an independently deployed MCP service rather than adding a second runtime for optics.
The generated key above is for local development only. Production publication uses GitHub OIDC to ask the non-exportable Azure Key Vault key to sign the whole-artifact manifest, then deploys a zero-traffic candidate revision.
MCP tools
as_of (full / outline / per-article select) · timeline · in_force_on ·
diff · search · article_history · provenance · coverage ·
cited_by · changes_in_period.
The same read-only tools cover Luxembourg and EU material. Search spans every
mounted publisher by default and can filter jurisdiction, date, hierarchy,
legal form, binding status, domain and language. Keyword retrieval is
deterministic FTS5/BM25. Hybrid adds the pinned local encoder and fixed rank
fusion when verified vectors are mounted; no generative model participates in
retrieval. A unique segment of an official publisher short title such as RGPD,
GDPR, DORA, or AI Act resolves deterministically; collisions require
clarification. Official publisher subjects, EuroVoc relations, and directory
coordinates support weak discovery but never become legal-text evidence or work
identity. No manually curated legal aliases are loaded. Model-derived weak discovery is
not active, and keyword remains the production default because the signed hybrid
holdout gate has not passed. The reviewed target V3 assistant uses the same tools,
claim-typed composition and a separately gated grounding step. It is not active until
the complete answer-dossier path passes review and promotion. Application code retains
work resolution, tool authorization, citation and gap authority. coverage exists to say what Lex does not have, because a system
that cannot state its own gaps cannot be trusted with a completeness question.
Contributing
Issues and PRs welcome, the highest-leverage areas:
A new publisher adapter (
ISourceAdapter, ~200 lines): any jurisdiction with an official machine-readable channel. The seam is publisher-pure by fitness test; adapters never touch files or git.Assistant release cases (evals/assistant-cases-v3.json): frozen typed-operation judgments, digest-attested by a project-owner reviewer identity distinct from the catalog author and run with the strict release evaluator. The gate has no keyword or grader fallback; cases specify the exact operation contract or refusal boundary expected from a natural question.
Extraction improvements: profiles are immutable; improvements ship as a new profile beside the old (see
fmx4-eu/1besidexhtml-eu/1).
Contributions are accepted under the Developer Certificate of Origin
(git commit -s).
Licence
Code: Apache-2.0 (LICENSE). The code licence does not extend
to corpus data or index artefacts, see each corpus repository's NOTICE
(three layers: official acts outside copyright / Lex's compilation rights /
code licence inapplicable). Derived dataset: CC-BY-4.0 (LU) and EU
reuse-with-attribution, licence inline in every file.
Support
This is free and open, and it stays that way whatever you decide. It is also not free to run: the live site, the nightly jobs and the storage sit on Azure infrastructure I pay for out of pocket, and I maintain it on my own time.
If it saved you an afternoon, you can buy me a coffee ☕ and put it towards the hosting bill. Starring the repo helps just as much, and costs nothing.
Available Tools
10 toolsarticle_historyAInspect
Every distinct text ONE provision (article/annex) has had, as validity intervals — plus its lifecycle events (inserted/removed/renumbered, renumbering detected mechanically by identical text hash). The answer to "what did Article X say over its life / when did it change".
| Name | Required | Description | Default |
|---|---|---|---|
| work | Yes | Work-level lex_id (publisher:workkey), version-level lex_id (version segment ignored), or verbatim publisher identifier. Unknown document -> call search first. | |
| anchor | Yes | provision anchor, e.g. art_1er (find it via search or as_of mode=outline) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full responsibility for behavioral disclosure. It discloses that renumbering is detected mechanically by identical text hash, and mentions validity intervals and lifecycle events. This goes beyond a simple 'get history' and provides meaningful behavioral detail, though it does not cover error conditions or response shape in depth.
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 a single, well-structured sentence that front-loads the core function and includes a clarifying question. Every phrase adds value, and there is no repetition or fluff.
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?
Despite lacking an output schema, the description explains what the tool returns (distinct texts, validity intervals, lifecycle events) and why to use it. It does not detail the exact output structure, but it gives enough context for an agent to understand the tool's purpose and invoke it correctly given the parameter descriptions.
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 covers both parameters (work and anchor) with descriptions, and the tool description does not add additional parameter-level detail beyond mentioning 'article/annex' which is already in the anchor description. Since schema description coverage is 100%, a baseline of 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 clearly states the tool's function: it returns every distinct text a provision has had along with validity intervals and lifecycle events. It directly answers the question 'what did Article X say over its life / when did it change', distinguishing it from related tools like as_of or diff by focusing on historical versions.
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 provides explicit usage context: use this tool when you need the history of a provision's text or to know when it changed. It does not explicitly reference alternative tools or exclusions, but the 'answer to...' wording gives a clear when-to-use signal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
as_ofAInspect
The state of one document as it stood on one date. Pure lookup, no ranking. mode=outline lists the provisions (articles/annexes) without text — use it first on long documents; mode=select returns only the named anchors' text; mode=full (default) returns the whole text. Every provision carries its own permalink and hash.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ISO date YYYY-MM-DD | |
| mode | No | full | outline | select (default full) | |
| work | Yes | Work-level lex_id (publisher:workkey), version-level lex_id (version segment ignored), or verbatim publisher identifier. Unknown document -> call search first. | |
| anchors | No | comma-separated provision anchors for mode=select, e.g. art_1er,art_33 | |
| language | No | optional language code, e.g. fr |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It clearly states 'Pure lookup, no ranking' and discloses the behavior of each mode, plus that every provision carries a permalink and hash. It doesn't mention edge cases like unknown documents, but that is covered in the parameter description.
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?
Three sentences, front-loaded with the core purpose and then structured details. No filler.
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 lookup with no output schema, the description covers the core behavior, modes, and a notable output feature (permalink/hash). It doesn't explicitly address error handling or pagination, but given the tool's simplicity and the rich parameter descriptions, it is sufficiently complete.
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%, but the description adds value by explaining the mode semantics and the default behavior, which goes beyond the schema's simple enum list. It also reinforces the meaning of anchors for select mode.
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+resource: 'The state of one document as it stood on one date.' This clearly distinguishes it from sibling tools like timeline or in_force_on by emphasizing a snapshot at a specific point in time. The explicit 'Pure lookup, no ranking' further separates it from search.
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 guidance on when to use each mode: 'use it first on long documents' for outline, and describes select vs full. It implies this is for point-in-time lookup rather than search or diff, though it doesn't explicitly name alternative tools or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
changes_in_periodAInspect
ACROSS the corpus: which works gained new versions between two dates, how many each, and when — the aggregate counterpart of diff/timeline (which cover ONE work). Use for "what changed between 2025 and 2026", "which laws changed most during the pandemic", "what moved last month". order=by_churn ranks by number of new versions; by_date (default) lists most recently changed first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | default 20 | |
| order | No | by_date (default) or by_churn | |
| offset | No | skip this many, for paging | |
| to_date | Yes | ISO date, end of window (inclusive) | |
| from_date | Yes | ISO date, start of window (inclusive) | |
| publisher | No | optional publisher id | |
| document_type | No | optional type code(s), comma-separated; prefix with ! to exclude, e.g. !RECUEIL,!CODE_RECUEIL for instruments only |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It discloses ordering behavior (by_churn ranks by number of new versions; by_date lists most recently changed first) and mentions aggregate output. However, it doesn't explicitly state read-only nature or any side effects, though it's implied as a query 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?
Three concise sentences front-load the core purpose, provide usage examples, and clarify key parameter behavior. No wasted words.
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 7-param tool with no output schema, the description covers the core output (works, version counts, dates), order semantics, and example use cases. It doesn't describe pagination defaults or return format in detail, but the schema covers limit/offset and the output is intuitive.
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 covers all parameters, but the description adds meaning for 'order' by explaining what each value does: 'by_churn ranks by number of new versions; by_date (default) lists most recently changed first'. This goes beyond the schema's simple enum description.
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+resource: 'which works gained new versions between two dates, how many each, and when'. It explicitly contrasts with diff/timeline as the 'aggregate counterpart', distinguishing it from 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?
The description explicitly says when to use this tool vs alternatives: 'the aggregate counterpart of diff/timeline (which cover ONE work)' and provides concrete example queries ('what changed between 2025 and 2026'). This gives clear guidance on appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cited_byAInspect
Which ARTICLES point at this law. The reverse of the cross-references the publisher writes into its own text ("modifie par la loi du 4 juin 2020"), captured at derive time. Answers "what depends on this law", "who amended it", "is anything still referring to it" — the question legal research is actually made of, and the one a search box cannot answer.
| Name | Required | Description | Default |
|---|---|---|---|
| work | Yes | the law being cited, e.g. lu-legilux:loi-2020-06-04-a476 | |
| limit | No | default 50 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden. It discloses a key behavioral trait: "captured at derive time," indicating the data is a snapshot rather than real-time. It also explains the underlying mechanism (reverse of publisher cross-references), giving insight into what results include. However, it does not explicitly state read-only behavior or response format, though the query-like semantics imply safety.
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 two sentences, front-loaded with the core purpose. The second sentence adds valuable behavioral and usage context, though the closing phrase "the question legal research is actually made of, and the one a search box cannot answer" is a rhetorical flourish that could be trimmed. Overall, it is appropriately sized and well-structured.
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?
Given the lack of output schema and annotations, the description does a good job explaining the tool's purpose, behavior, and use cases. It clearly indicates the output is a list of citing articles, but does not specify exact response fields or pagination details. For a moderate-complexity lookup tool, this is nearly complete but could be enhanced with response structure notes.
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% (both 'work' and 'limit' are described in the schema), so the baseline is 3. The description adds conceptual context about what "cited" means, but does not add parameter-specific details beyond the schema, such as how limit behaves or whether work accepts multiple formats.
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 "Which ARTICLES point at this law," a specific verb+resource pairing that clearly states the tool's function. It distinguishes itself from search by noting "the one a search box cannot answer" and differentiates from sibling tools by emphasizing the reverse nature of citations.
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 provides explicit use cases: "answers 'what depends on this law', 'who amended it', 'is anything still referring to it'." It implicitly contrasts with search, but does not explicitly mention sibling alternatives or exclusion criteria, so it has clear context without formal exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
coverageBInspect
What we hold and what we lack, tier by tier: counts, date ranges, history_begins, known gaps. This tool exists to say what we do NOT have.
| Name | Required | Description | Default |
|---|---|---|---|
| publisher | No | optional publisher id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It discloses that output is organized by tier and includes positive and negative coverage information, but it doesn't mention any operational details like response format, pagination, or data source limitations. This is adequate for a simple read tool but not rich.
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 tightly written sentences. The first lists key output categories, the second underscores the gap-reporting purpose. No filler.
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 and one optional filter, the description gives useful context but leaves open the output structure and the meaning of 'tier' and 'history_begins.' It is sufficient for basic understanding but not fully specified.
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 single parameter publisher is fully described in the schema as an optional publisher id. The description adds no additional semantics for how filtering works, so the baseline of 3 applies.
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 the tool reports coverage information ('what we hold and what we lack, tier by tier') and enumerates specific output dimensions (counts, date ranges, history_begins, known gaps). It clearly distinguishes this from sibling tools focused on history, diffs, or searches, though it doesn't explicitly name an alternative.
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?
No guidance is provided on when to use this tool versus siblings like provenance or diff. The statement 'This tool exists to say what we do NOT have' implies a gap-analysis use case, but there are no explicit alternative references or preconditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diffBInspect
What changed between two dates for one work: which versions applied, and where both texts are held, retrieve them via as_of to compare.
| Name | Required | Description | Default |
|---|---|---|---|
| work | Yes | Work-level lex_id (publisher:workkey), version-level lex_id (version segment ignored), or verbatim publisher identifier. Unknown document -> call search first. | |
| to_date | Yes | ISO date | |
| language | No | language code | |
| from_date | Yes | ISO date |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It mentions that the tool reports where versions are held and points to as_of for retrieval, but it does not disclose read-only status, permissions, side effects, or any error behavior.
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 a single sentence that is reasonably concise and front-loaded with the core purpose. However, the colon-and-comma structure makes it slightly convoluted and could be clearer.
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 or annotations, the description needs to convey the return behavior and workflow. It partially does by mentioning versions and locations, and instructing retrieval via as_of, but it does not describe the output format or handle edge cases like no changes between dates.
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 100%, so the baseline is 3. The description references work, from_date, and to_date in the context of comparing changes, but it does not add any semantics beyond the schema, and the optional 'language' parameter is not mentioned.
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 reports what changed between two dates for a given work, including which versions applied and where texts are held. However, it lacks an explicit verb like 'returns' or 'compares', and does not explicitly distinguish itself from sibling tools like timeline or changes_in_period.
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 provides an implied workflow: use diff to see changes, then retrieve texts via as_of. It does not explicitly state when to use diff versus alternatives like timeline or changes_in_period, and offers no exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
in_force_onAInspect
The set of works in force on a date, computed from validity intervals at query time, deduplicated by work. Carries a mandatory population disclosure.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ISO date | |
| limit | No | default 50 | |
| offset | No | pagination offset | |
| publisher | No | optional publisher id, e.g. lu-legilux | |
| document_type | No | optional type code, e.g. CODE |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries the behavioral disclosure burden. It discloses that the set is computed at query time from validity intervals, deduplicates by work, and carries a mandatory population disclosure. However, it does not explicitly state side effects or safety profile, though the read-only nature is implied.
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 two sentences with no wasted words. It front-loads the core purpose and adds the key behavioral nuances in a compact format.
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 query tool with 5 parameters and no output schema, the description adequately explains the core behavior, including deduplication and the mandatory population disclosure. It doesn't detail the response shape, but that is not required when no output schema exists and the tool's purpose is clear.
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 already provides descriptions for all 5 parameters, achieving 100% coverage. The description adds no additional parameter-specific details but sets the context that the 'date' parameter is central. With full schema coverage, the baseline score of 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 clearly defines the tool's function: it returns the set of works in force on a date, computed from validity intervals and deduplicated by work. This is specific enough to distinguish it from siblings like 'as_of' or 'timeline' which deal with different temporal queries.
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 does not explicitly state when to use this tool over alternatives, nor does it mention exclusions. The usage is implied by the semantics: if you need works active on a specific date, this is the tool, but no direct comparison to sibling tools is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
provenanceAInspect
Proof chain for one lex_id: source URI, retrieval time, record/body hashes, event chain, corpus commit, index build, stamp signature.
| Name | Required | Description | Default |
|---|---|---|---|
| lex_id | Yes | full lex_id | |
| language | No | optional |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the content of the proof chain (source URI, hashes, signatures), which implies a read-only verification operation, but it does not explicitly state that it is non-mutating or describe any potential side effects, errors, or prerequisites.
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 a single, well-structured sentence that front-loads the core purpose ('Proof chain for one lex_id') before listing details. Every word earns its place with no redundancy or unnecessary fluff.
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?
Since there is no output schema, the description compensates by listing the key elements returned (source URI, hashes, event chain, corpus commit, stamp signature). It is complete for a simple lookup tool, though it omits error or performance context and assumes the agent understands 'proof chain' terminology.
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 already describes both parameters, and coverage is 100%. The description adds that it is for 'one lex_id' and enumerates output components, but it does not elaborate on the 'language' parameter beyond what the schema says ('optional'), so it adds minimal extra meaning.
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 provides a 'Proof chain for one lex_id' and enumerates the specific components returned (source URI, hashes, event chain, etc.). This distinguishes it from sibling tools like timeline or diff, which serve different purposes.
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 this is for a single lex_id, but it provides no explicit guidance on when to use this tool versus alternatives like article_history or coverage. There are no usage examples, conditions, or exclusions mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchAInspect
Filtered-then-ranked full-text search (FTS; filters always run before ranking). Returns hits WITHOUT body text: lex_id, dates, snippet, hash. Full state via as_of.
| Name | Required | Description | Default |
|---|---|---|---|
| as_of | No | optional ISO date: only versions valid on this date | |
| limit | No | default 10 | |
| query | Yes | search terms | |
| works | No | optional comma-separated work ids: restrict the search to these works, for callers that know their subject | |
| publisher | No | optional publisher id | |
| document_type | No | optional type code |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden. It discloses the filter-then-rank order, the absence of body text in results, the specific fields returned, and the as_of behavior for full state. This is meaningful behavioral context beyond a generic 'search' claim, though it doesn't mention side effects (none expected for a read-only operation) or pagination details.
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 two sentences, front-loaded with the core purpose and immediately followed by the most critical behavioral and output details. Every clause earns its place; no fluff or repetition of schema fields.
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?
Without an output schema, the description adequately explains the return shape (lex_id, dates, snippet, hash) and the as_of option. It covers the main behavior for a search tool, though it doesn't mention default limit behavior or snippet generation details—but these are minor and largely inferable from the schema. Overall, it is complete for practical 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 100%, so baseline is 3. The description adds value by explaining that filters ('works', 'publisher', 'document_type') run before ranking, and by linking 'as_of' to full state retrieval. This enriches the schema's bare parameter descriptions, justifying a score above baseline.
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 identifies this as a full-text search tool with a specific pipeline ('filtered-then-ranked') and distinct output (hits without body text, listing exact fields). This distinguishes it from siblings like provenance, timeline, and diff, which serve different purposes.
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 for full-text search needs and clarifies that filters always run before ranking, which informs query construction. It also notes 'Full state via as_of,' guiding users to the as_of parameter for historical state, though it doesn't explicitly mention when not to use this tool or name alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
timelineBInspect
Every state a document has been in: validity intervals and version keys, publisher-asserted.
| Name | Required | Description | Default |
|---|---|---|---|
| work | Yes | Work-level lex_id (publisher:workkey), version-level lex_id (version segment ignored), or verbatim publisher identifier. Unknown document -> call search first. | |
| limit | No | max versions (default 100) | |
| offset | No | pagination offset |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It does reveal that the tool relies on publisher-asserted data and returns validity intervals and version keys, indicating a read-only operation. However, it does not discuss ordering, pagination behavior, or how to interpret the intervals, leaving gaps in transparency.
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 a single sentence with a clear structure: a subject ('Every state a document has been in'), a colon explaining the contents ('validity intervals and version keys'), and a qualifier ('publisher-asserted'). Every word contributes to the meaning, with no redundancy or filler.
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?
The description is concise but covers the core output type and data source. However, without annotations or an output schema, and given the presence of several sibling tools, the description does not fully clarify how this timeline differs or what a 'state' entails. It is adequate but leaves room for 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?
All three parameters (work, limit, offset) have schema descriptions, giving 100% coverage, so the baseline is 3. The tool description adds no parameter-specific meaning; it only provides high-level context about the output. Since the schema already documents the parameters clearly, the description does not need to compensate.
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 communicates that the tool returns the historical states of a document, specifying validity intervals and version keys, and notes the data is publisher-asserted. Though it lacks an explicit verb like 'list' or 'retrieve', the phrase 'Every state a document has been in' clearly implies the function. It distinguishes itself from siblings by focusing on temporal states and version keys, though it does not explicitly name any alternative tool.
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 provides no guidance on when to use this tool versus sibling tools such as provenance or as_of. The only usage hint appears in the schema's 'work' parameter ('Unknown document -> call search first'), but that is part of the structured parameter description, not the tool description itself. No alternatives or exclusions are mentioned.
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. Dates show when Glama detected each change.
10 tool updates
v1.0.0- First observed
article_history - First observed
as_of - First observed
changes_in_period - First observed
cited_by - First observed
coverage - First observed
diff - First observed
in_force_on - First observed
provenance - First observed
search - First observed
timeline
TDQS
Each tool targets a distinct legal research need: provenance, state-at-date, document history, force status, diffing, search, provision history, coverage, citations, and corpus-wide changes. The descriptions clearly differentiate overlapping tools like timeline vs article_history and diff vs changes_in_period.
All tool names are lowercase and use underscores for multi-word phrases, following a consistent pattern. While parts of speech vary, the formatting style is uniform, with no camelCase or mixed conventions.
With 10 tools, the server is well-scoped for legal research, covering discovery, retrieval, temporal analysis, and citation tracking. Each tool serves a unique purpose without redundancy.
The tool surface is largely complete, offering search, document retrieval, history, diffing, force status, and citations. The only notable gap is the absence of a forward-citation tool (which laws a given law references), though this can be mitigated by reading the text via as_of.
Maintenance
Related MCP Connectors
Keyless MCP access to official Luxembourg public data: laws, statistics, mobility, and more.
EU law, article-level: GDPR, NIS2, DORA, EU AI Act + more, with EUR-Lex citations. Keyless.
- acquisOAuthcom.acquislaw
Verified EU law: verbatim, signed provisions with EUR-Lex links. Read-only, not legal advice.
Free access to 3.3M French & EU court decisions + 1.5M law articles w/ history. 31 read-only tools
Related MCP Servers
- 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

conformi-searchofficial
AlicenseAqualityAmaintenanceInstallable MCP server for EU legal research with verifiable CELEX citations from the EUR-Lex corpus (DE/EN/FR).21MIT- AlicenseNot gradedqualityFmaintenanceEnables AI-powered legal research across 4,551 Luxembourg statutes, 260 case law decisions, and EU law integrations through natural language queries and 13 specialized tools.772Apache 2.0
- AlicenseNot gradedqualityFmaintenanceProvides structured access to EU treaties, regulations, directives, and CJEU case law via 14 tools for searching, retrieving, and analyzing legislation and court decisions.Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/SFHAJJI/lex'
If you have feedback or need assistance with the MCP directory API, please join our Discord server