
Fedlex Mcp
io.github.malkreide由 GitHub 帳號 malkreide 發布v2.1.0更新於 Oct 24, 2026
Swiss federal law, consultations (Fedlex) & TERMDAT terminology (LINDAS) via SPARQL
概覽
本機 MCP 伺服器,讓助理透過公開 SPARQL 端點查詢瑞士聯邦法律、聯邦諮詢程序與官方 TERMDAT 術語。
- 可以做什麼
- 檢索聯邦法律:依關鍵字搜尋 SR、依 SR 編號查詢、版本歷程、最新官方彙編出版物、即將生效的法律、聯邦公報檢索與國際條約。監控諮詢程序:列出開放諮詢及截止日期與剩餘天數,依主題、狀態、截止範圍與主管機關全文檢索,並檢視單一諮詢詳情。查詢術語:在德語、法語、義大利語、羅曼什語與英語之間對照術語,並取得完整 TERMDAT 概念條目。
- 適用情境
- 適合處理瑞士聯邦立法、追蹤聯邦諮詢截止日期,或查找法律與行政術語的官方多語譯法。適用於研究與起草輔助,不涵蓋邦(州)級法律,也不構成法律意見。
- 執行需求
- 以 PyPI 套件形式透過 uvx 在本機以 stdio 執行,也可從原始碼安裝。需要 Python 3.11+ 以及 uv 或 pip。無需 API 金鑰或帳號;兩個 SPARQL 端點皆為公開服務,需要網路存取。另有選用 HTTP 模式供瀏覽器用戶端使用。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Fedlex Mcp,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
:switzerland: Part of the Swiss Public Data MCP Portfolio
:balance_scale: fedlex-mcp
[Version] [License: MIT] [Python 3.11+] [MCP] [No Auth Required] [CI]
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
Overview
fedlex-mcp connects AI assistants (Claude) with three official Swiss SPARQL data sources:
- Federal law via the Fedlex SPARQL endpoint — the Systematic Compilation (SR), Official Compilation (AS), Federal Gazette (BBl) and treaties.
- Consultations (Vernehmlassungen) via the same Fedlex endpoint (
jolux:Consultation) — the pre-parliamentary phase in which anyone can comment on a draft. - TERMDAT, the Federal Chancellery's terminology database, via the LINDAS SPARQL endpoint — official term equivalents across de/fr/it/rm/en.
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.
Features
- :balance_scale: 12 tools, 2 resources across federal law, consultations and terminology
- :mag: SPARQL-powered — two isolated endpoints (Fedlex + LINDAS), no shared failure mode
- :globe_with_meridians: 5 languages — German, French, Italian, Romansh, plus English for terminology
- :unlock: No API key required — all data under open reuse licences
- :cloud: Dual transport — stdio (Claude Desktop) + Streamable HTTP (cloud)
Anchor demo query
"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.
Prerequisites
- Python 3.11+
- uv (recommended) or pip
Installation
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):
Installation from source
Or with uvx (no permanent installation):
Quickstart
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?"
Configuration
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
Or with uvx:
Config file locations:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Cloud Deployment (SSE for browser access)
For use via claude.ai in the browser (e.g. on managed workstations without local software):
Render.com (recommended):
- Push/fork the repository to GitHub
- On render.com: New Web Service -> connect GitHub repo
- Set start command:
python -m fedlex_mcp.server --http --port 8000 - In claude.ai under Settings -> MCP Servers, add:
https://your-app.onrender.com/sse
"stdio for the developer laptop, SSE for the browser."
Demo
[Demo: Claude using fedlex_search_laws]
Available Tools
Example Use Cases
→ More use cases by audience →
Architecture
Two isolated SPARQL endpoints behind one server. Separate httpx clients and
timeouts mean a LINDAS outage never breaks the fedlex_* tools, and vice versa.
Data Model
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.
Architecture decision
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).
Languages
Project Structure
Known Limitations
- SPARQL complexity: Very broad keyword searches may time out (45s timeout)
- Language coverage: German has the most complete data; other languages may have gaps
- Historical data: Not all historical versions of laws have machine-readable metadata
- Rate limiting: The endpoints may throttle high-frequency requests
Consultations — scope and reliability (read this before relying on it)
- Federal only. No cantonal consultations. Fedlex holds federal (Bund) consultations. Cantonal consultations — often the more relevant ones for a school authority (Schulamt) — are not in Fedlex and not covered here. This is a hard scope boundary, not a gap to be worked around.
- This is not a push service. MCP is pull-based: the server answers on request which consultations are open and which expire soon. It cannot notify, schedule, or alert. Recurrence comes from you or an external scheduler — never from the server. "No open consultations" means nothing is open right now, not nothing is coming.
- Thematic filtering is free-text, and imperfect.
jolux:Consultationhas 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. - Coverage / latency: ~2,553 consultations; the historical corpus 1960–1991 sits with the Federal Archives, out of scope. Newly opened consultations appear with the upstream Fedlex publication latency (not real-time).
- Deadlines end on the calendar day in Europe/Zurich;
days_remainingis computed at request time, never cached.0= the deadline is today.
Live findings (verified 2026-07-20):
- Quirk 1 — the deadline wins over the status field. Status
/2("Laufend"/running) andeventEndDateare two independent signals. The server derivesstatusfrom 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 markedstatus_conflict: trueand keeps the raw label instatus_source.
TERMDAT (LINDAS) — findings (verified 2026-07-18)
- Quirk 2 — reality-check discrepancy (stated plainly). The Federal Chancellery communicates roughly 400,000 TERMDAT entries. LINDAS contains 77,692. The difference is unexplained — presumably only the validated, released subset is published as Linked Data. A negative terminology hit does not mean the term is missing from TERMDAT; it only means it is not in the LINDAS subset. Every TERMDAT response carries this note so the model draws no false conclusion.
- Quirk 3 — two URI levels. Concept URIs (
…/termdat/40109) carry the preferred names and the definition; term URIs with a language/position suffix (…/termdat/40109/3/de) are synonyms/variants linked viaschema:hasPart. The tools accept both forms and normalise internally to the concept ID.
What this tool is not
- Not a subscription or alerting service. It does not watch, notify, e-mail, or remind. It answers when asked. Any recurring check is driven by you or an external scheduler, outside the server.
- Not a cantonal source. Federal (Bund) consultations only — see Known Limitations.
- Not legal advice. It returns public metadata and links to official documents. Deadlines and status are derived mechanically from the published data; verify anything decision-critical against the linked Fedlex page.
Related processes across the portfolio
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:
- Consultation (pre-parliamentary): this server —
fedlex_*consultation*tools. - Parliamentary phase:
parlament-mcp— debates, motions, votes in the Federal Assembly. - Popular vote / referendum:
swiss-democracy-mcp— federal popular votes. Consultations are a distinct, earlier stage — no overlap, but the same legislative lifecycle.
Project Phase
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.
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.
MCP Protocol Version
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.
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.
Four consequences of the modern revision are visible in this server:
- CORS names the routing headers.
Mcp-Method,Mcp-NameandMcp-Protocol-Versionride on every streamable-HTTP request, and a browser may only send a header the server allow-lists. SeeCORS_ROUTING_HEADERSinserver.py. - The listing methods carry a freshness hint.
tools/list,resources/list,resources/templates/listandserver/discoveranswer withttlMs300000 andcacheScopepublic(CACHE_HINTS).resources/readdeliberately does not: it returns federal law, and a client must not treat a repealed enactment as fresh for five minutes. - No log notifications. The logging capability is deprecated as of
2026-07-28(SEP-2577). Up to v2.0.1 every tool sentnotifications/messageviactx.info()/ctx.error()— on handshake connections without ever declaring theloggingcapability, on modern ones as a deprecated call the SDK dropped. Observability now sits with the operator (structlog on stderr, optional OpenTelemetry); a failure reaches the caller in the tool result itself (isError: true, see below). serverInfocarries the package version. In2026-07-28the identity is stamped into the_metaof every response, not sent once atinitialize. Up to v2.0.1 itsversionwas an empty string.
Tool failures carry isError: true. The spec reports an execution error
(Fedlex or LINDAS unreachable, a body that is not JSON) as a tool result with
isError: true, not as a JSON-RPC error. Since 2025-11-25 arguments that
violate the input schema count as execution errors too, so the model can correct
its input; the SDK answers those itself before the tool runs, without an
envelope — measured in both eras, and likewise for an unknown tool name. Up to
v2.0.1 the server's own failures came back
with isError: false, and only match_type: "error" inside the envelope said
so. The envelope still travels as structuredContent; "nothing found"
(match_type: "none") is a valid answer and is not flagged. Every registered
tool is checked in both eras in
tests/test_tool_errors.py.
Long SPARQL calls report progress. A call can take up to 45 s, and the time
sits almost entirely in attempts and the back-off between them. A client that
sends a progressToken receives one notifications/progress per attempt —
"Anfrage an Fedlex (Versuch 1 von 3)", on a retry "Fedlex: Versuch 2 von 3 nach
HTTP 503" — with no total, since none exists that would not be invented. Over
streamable HTTP in 2026-07-28 the response switches to SSE for this; without a
token nothing is sent. Unlike logging, server-to-client progress is not
deprecated. See tests/test_progress.py.
Both eras are exercised over the wire in
tests/test_modern_era.py: a session-less
server/discover and tools/call through the assembled ASGI stack, and a tool
call in each era that must produce neither a log notification nor an SDK
deprecation warning.
Testing
Safety & Limits
- Read-only: All tools perform SPARQL SELECT queries only — no data is written, modified, or deleted on either endpoint. All 12 tools are annotated
readOnlyHint: true/destructiveHint: false/idempotentHint: true. - No personal data: Fedlex holds public law, gazettes and consultation metadata; TERMDAT holds official terminology. No personally identifiable information (PII) is processed or stored by this server.
- Rate limits: The Fedlex and LINDAS SPARQL endpoints are public services without a documented rate limit; use
limitparameters conservatively (default 20, max 100). The server enforces a 45s timeout per request per endpoint and retries only transient failures. - Endpoint isolation: Fedlex and LINDAS use separate clients and timeouts — a LINDAS outage does not affect the
fedlex_*tools. - Data freshness: Results reflect the endpoints at query time. No caching is performed by this server.
- Terms of service: Data is subject to the reuse conditions of fedlex.admin.ch — free reuse for commercial and other purposes.
- No guarantees: This server is a community project, not affiliated with the Swiss Federal Chancellery. Availability depends on the upstream SPARQL endpoint.
Changelog
See CHANGELOG.md
Contributing
See CONTRIBUTING.md
Security
See SECURITY.md for the security posture, hardening controls, and how to report a vulnerability.
License
MIT License — see LICENSE
Author
Hayal Oezkan . malkreide
Credits & Related Projects
- Fedlex: fedlex.admin.ch — Swiss Federal Chancellery
- TERMDAT / LINDAS: lindas.admin.ch — Linked Data service of the Swiss administration
- Protocol: Model Context Protocol — Anthropic / Linux Foundation
- Related: parlament-mcp — Swiss Federal Assembly (parliamentary phase)
- Related: swiss-democracy-mcp — Swiss federal popular votes (referendum phase)
- Related: swiss-cultural-heritage-mcp — Swiss cultural heritage data
- Related: zurich-opendata-mcp — City of Zurich open data
- Related: swiss-transport-mcp — Swiss public transport
- Portfolio: Swiss Public Data MCP Portfolio
來源:README.md,提交 7996a03
工具
0版本歷史
2- v2.1.0最新Sep 27, 2026
- v2.0.1Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分