Skip to main content
Glama
SFHAJJI

Lex: Luxembourg Law MCP Server

Lex

CI License Live MCP Coverage

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

Lex live temporal search, hybrid retrieval, comparison and deployment evidence

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/mcp

Modern 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/mcp

The 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_to to 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 log carries 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 derive re-derives and byte-compares.

  • Legal and temporal eligibility before fusion and final ranking, enforced by a non-optional FilterSet on 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.Stdio

Lex.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/1 beside xhtml-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 tools
article_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".

ParametersJSON Schema
NameRequiredDescriptionDefault
workYesWork-level lex_id (publisher:workkey), version-level lex_id (version segment ignored), or verbatim publisher identifier. Unknown document -> call search first.
anchorYesprovision anchor, e.g. art_1er (find it via search or as_of mode=outline)

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesISO date YYYY-MM-DD
modeNofull | outline | select (default full)
workYesWork-level lex_id (publisher:workkey), version-level lex_id (version segment ignored), or verbatim publisher identifier. Unknown document -> call search first.
anchorsNocomma-separated provision anchors for mode=select, e.g. art_1er,art_33
languageNooptional language code, e.g. fr

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNodefault 20
orderNoby_date (default) or by_churn
offsetNoskip this many, for paging
to_dateYesISO date, end of window (inclusive)
from_dateYesISO date, start of window (inclusive)
publisherNooptional publisher id
document_typeNooptional type code(s), comma-separated; prefix with ! to exclude, e.g. !RECUEIL,!CODE_RECUEIL for instruments only

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workYesthe law being cited, e.g. lu-legilux:loi-2020-06-04-a476
limitNodefault 50

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
publisherNooptional publisher id

TDQS

B3.3/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
workYesWork-level lex_id (publisher:workkey), version-level lex_id (version segment ignored), or verbatim publisher identifier. Unknown document -> call search first.
to_dateYesISO date
languageNolanguage code
from_dateYesISO date

TDQS

B3.2/5.0
Behavior2/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesISO date
limitNodefault 50
offsetNopagination offset
publisherNooptional publisher id, e.g. lu-legilux
document_typeNooptional type code, e.g. CODE

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
lex_idYesfull lex_id
languageNooptional

TDQS

A3.6/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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.

timelineBInspect

Every state a document has been in: validity intervals and version keys, publisher-asserted.

ParametersJSON Schema
NameRequiredDescriptionDefault
workYesWork-level lex_id (publisher:workkey), version-level lex_id (version segment ignored), or verbatim publisher identifier. Unknown document -> call search first.
limitNomax versions (default 100)
offsetNopagination offset

TDQS

B3.3/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

  1. 10 tool updatesv1.0.0
    • First observedarticle_history
    • First observedas_of
    • First observedchanges_in_period
    • First observedcited_by
    • First observedcoverage
    • First observeddiff
    • First observedin_force_on
    • First observedprovenance
    • First observedsearch
    • First observedtimeline

TDQS

A4/5.0
Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

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