The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Fedlex MCP listing page.
:switzerland: Part of the Swiss Public Data MCP Portfolio
MCP Server for Swiss federal law, consultations & official terminology — search the SR, monitor consultation deadlines, and translate terms across the national languages via Claude Desktop or Claude.ai
fedlex-mcp connects AI assistants (Claude) with three official Swiss SPARQL data sources:
jolux:Consultation) — the pre-parliamentary phase in which anyone can comment on a draft.All three are SPARQL-based, which is exactly why they live in one server rather than three: no new technology stack, only new queries against known patterns.
Metaphor: USB-C for federal law. Fedlex tells you what you have to respond to. TERMDAT tells you what it is called in the other national languages.
"Which education-related consultations are currently open, until when does the deadline run, which office is in charge — and what are the key technical terms in French and Italian for the response?"
A single conversation chains three tools across two endpoints:
Every open consultation carries deadline, days_remaining (computed at
request time in Europe/Zurich, 0 = deadline is today) and a derived
status — an expired consultation never shows up as running. Fedlex says
what you must respond to and by when; TERMDAT says how to name it in the
other national languages.
Use
topic="education", notkeyword="Volksschule". Fedlex consultations have no subject taxonomy — filtering is free-text over the title, and the word "Volksschule" appears in zero consultation titles. Thetopicfilter expands to a disclosed keyword union (Bildung, Schule, Berufsbildung, Hochschule, …) and reports exactly which terms it searched.
Run via uv's uvx — no clone or manual install needed. Add to your MCP client config (mcpServers for Claude Desktop, Cursor and Windsurf; use a top-level servers key for VS Code in .vscode/mcp.json):
Or with uvx (no permanent installation):
Try it immediately in Claude Desktop:
"Show me all valid federal laws on vocational training" "What does the Data Protection Act say? Is it still in force?" "Which consultations on education are open right now, and until when?" "What is 'Volksschule' called in French and Italian in official terminology?"
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
Or with uvx:
Config file locations:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.jsonFor use via claude.ai in the browser (e.g. on managed workstations without local software):
Render.com (recommended):
python -m fedlex_mcp.server --http --port 8000https://your-app.onrender.com/sse"stdio for the developer laptop, SSE for the browser."
| # | Tool | Source | Description |
|---|---|---|---|
| 1 | fedlex_search_laws | Fedlex | Search the Systematic Compilation (SR) by keyword in title |
| 2 | fedlex_get_law_by_sr | Fedlex | Get a law by its SR number (e.g. 235.1 = Data Protection Act) |
| 3 | fedlex_get_recent_publications | Fedlex | Latest publications from the Official Compilation (AS) |
| 4 | fedlex_get_upcoming_changes | Fedlex | Laws entering into force soon (legal monitoring) |
| 5 | fedlex_search_gazette | Fedlex | Search the Federal Gazette (BBl) |
| 6 | fedlex_get_law_history | Fedlex | All versions of a law (version history) |
| 7 | fedlex_search_treaties | Fedlex | International treaties (SR numbers starting with 0.) |
| 8 | fedlex_get_open_consultations | Fedlex | Deadline monitoring — open consultations (eventEndDate >= today, Europe/Zurich); each with days_remaining + derived status, sorted by shortest deadline; optional topic/keyword |
| 9 | fedlex_search_consultations | Fedlex | Full-text search over consultation title/description, with filters (topic, status, deadline range, office) |
| 10 | fedlex_get_consultation | Fedlex | Detail for one eventId: deadline, days_remaining, office, derived status, documents |
| 11 | termdat_lookup_term | LINDAS | Term → equivalents in de/fr/it/rm/en incl. definition |
| 12 | termdat_get_concept | LINDAS | Full TERMDAT entry for a URI or ID |
| Query | Tool |
|---|---|
| "Show me all valid federal laws on vocational training" | fedlex_search_laws |
| "What does the Data Protection Act say?" | fedlex_get_law_by_sr |
| "Which laws enter into force in the next 3 months?" | fedlex_get_upcoming_changes |
| "Show me the version history of the DSG" | fedlex_get_law_history |
| "Which consultations on education are open, and until when?" | fedlex_get_open_consultations |
| "Find closed consultations about the language act" | fedlex_search_consultations |
| "Give me the full detail and documents for consultation proj/2026/71/cons_1" | fedlex_get_consultation |
| "What is 'Volksschule' called in French and Italian?" | termdat_lookup_term |
| "Show the full TERMDAT entry 40109" | termdat_get_concept |
→ More use cases by audience →
Two isolated SPARQL endpoints behind one server. Separate httpx clients and
timeouts mean a LINDAS outage never breaks the fedlex_* tools, and vice versa.
JOLux Ontology — federal law (Fedlex)
JOLux Ontology — consultations (Fedlex, same endpoint)
There is no subject taxonomy on jolux:Consultation — thematic filtering is
free-text over eventTitle only, and status is derived from the deadline
(not the source status field).
Legislative lifecycle — where consultations sit (all in this one server):
The consultation stage is the earliest public point of influence — the tools above answer what is open and until when, before a draft reaches the Bundesblatt.
schema.org — terminology (TERMDAT via LINDAS, graph fch/termdat)
SPARQL endpoints: https://fedlex.data.admin.ch/sparqlendpoint · https://lindas.admin.ch/query
Licence: Free reuse per fedlex.admin.ch; TERMDAT via LINDAS under open reuse.
ARCH A — live SPARQL only, for all three data areas, consistent with the existing Fedlex integration (decided 2026-07-18).
Both sources are unauthenticated SPARQL endpoints with acceptable latency, so no
dump/offline fallback is needed: if the Fedlex endpoint is down the server cannot
function anyway, and adding a cache would only mask that. LINDAS is a separate
endpoint, and its outage must not degrade the fedlex_* tools.
Isolation requirement: Fedlex and LINDAS use separate httpx clients, separate
timeouts and separate error/status reporting. A LINDAS timeout cannot fail a
fedlex_* call and vice versa (covered by an isolation test).
| Code | Language |
|---|---|
de | German (default, most complete coverage) |
fr | French |
it | Italian |
rm | Romansh |
jolux:Consultation has
no subject/classification taxonomy (verified live 2026-07-20) — filtering
is substring search over the title only. topic="education" expands to a
disclosed keyword union and deliberately over-matches (a too-narrow filter
would falsely reassure); expect some false positives (e.g. "Ausbildung" inside
an unrelated title) and, for niche wording, possible false negatives. The
response always states which terms were searched.days_remaining is
computed at request time, never cached. 0 = the deadline is today.Live findings (verified 2026-07-20):
| Query | Status | Records | Note |
|---|---|---|---|
COUNT(?s) {?s a jolux:Consultation} | OK | 2,553 | full inventory |
hasSubTask with start/end dates | OK | 2,505 of 2,553 | 48 without any deadline |
Open consultations (eventEndDate >= today) | OK | 42 | deadlines into autumn 2026 |
consultation-status vocabulary | OK | 7 values | /0../6, /2 = running |
| Title contains "volksschule" / "lehrplan" | OK | 0 / 0 | anchor term itself finds nothing → use topic |
Title contains "bildung" (single) vs topic="education" union | OK | 44 vs 66 | keyword union is broader |
REGEX(LCASE(?t), "a|b") alternation | BROKEN | 0 | silently empty on this endpoint → OR-chained CONTAINS instead |
/2
("Laufend"/running) and eventEndDate are two independent signals. The
server derives status from the date: past deadline ⇒ Abgeschlossen,
regardless of what the source status claims — so an expired consultation is
never listed as running. When the two disagree the record is marked
status_conflict: true and keeps the raw label in status_source.| Query | Status | Records | Note |
|---|---|---|---|
COUNT(DISTINCT ?s) a schema.ld:Term in graph | OK | 77,692 | |
Language tags on schema:name | OK | de/fr/it/en | rm effectively absent (0) |
Search schema:name = "Volksschule" | OK | 1 | returns term URI …/termdat/40109/3/de |
Concept URI …/termdat/40109 | OK | – | 4 language variants + definition |
…/termdat/40109) carry the
preferred names and the definition; term URIs with a language/position suffix
(…/termdat/40109/3/de) are synonyms/variants linked via schema:hasPart. The
tools accept both forms and normalise internally to the concept ID.Swiss federal legislation runs a chain, and this server covers one part of it — the pre-parliamentary consultation. The full chain is representable across three MCP servers:
fedlex_*consultation* tools.parlament-mcp — debates, motions, votes in the Federal Assembly.swiss-democracy-mcp — federal popular votes. Consultations are a distinct, earlier stage — no overlap, but the same legislative lifecycle.This server is in Phase 1 (read-only). All tools are annotated
readOnlyHint: true / destructiveHint: false and only ever query the public
Fedlex SPARQL endpoint — there are no write, send, or filesystem capabilities.
| Phase | Scope | Status |
|---|---|---|
| 1 — Read-only | Query SR/AS/BBl/treaties | ✅ current |
| 2 — Write-capable | (none planned) | — |
| 3 — Multi-agent | (none planned) | — |
A transition to a later phase would require an audit re-run and the human-in-the-loop controls described in the audit catalog before any write-capable tool is added.
This server speaks two protocol eras over the same endpoint. The client's first request on a connection decides which one applies; a later claim from the other era is refused.
| Era | Revision | Who reaches it |
|---|---|---|
initialize handshake | 2024-11-05 … 2025-11-25 | What today's clients speak. The server answers with the revision asked for, or with the 2025-11-25 ceiling when the request asks for something newer. |
| Per-request envelope | 2026-07-28 | A request carrying the 2026-07-28 _meta envelope opens a modern connection. |
Both revisions are pinned in
tests/test_protocol_version.py and asserted
against the installed SDK, so a Dependabot bump of mcp cannot move either one
silently. The handshake ceiling is measured against a live initialize through
the assembled ASGI stack, not read off a constant name.
Note that the SDK's LATEST_PROTOCOL_VERSION is an alias for the modern
era, not for the handshake era — pinning against it alone would leave the era
that current clients actually negotiate free to drift.
Update policy. When the gate fails, do not edit the constant blindly: read
the spec changelog between the two revisions, verify the server still behaves,
then move the constant, this section, README.de.md and
CHANGELOG.md together.
Two consequences of the modern revision are visible in this server:
Mcp-Method, Mcp-Name and
Mcp-Protocol-Version ride on every streamable-HTTP request, and a browser
may only send a header the server allow-lists. See CORS_ROUTING_HEADERS in
server.py.tools/list,
resources/list, resources/templates/list and server/discover answer with
ttlMs 300000 and cacheScope public (CACHE_HINTS). resources/read
deliberately does not: it returns federal law, and a client must not treat a
repealed enactment as fresh for five minutes.readOnlyHint: true / destructiveHint: false / idempotentHint: true.limit parameters conservatively (default 20, max 100). The server enforces a 45s timeout per request per endpoint and retries only transient failures.fedlex_* tools.See CHANGELOG.md
See CONTRIBUTING.md
See SECURITY.md for the security posture, hardening controls, and how to report a vulnerability.
MIT License — see LICENSE
Hayal Oezkan . malkreide