# fedlex-mcp [Health: Active]

**Category:** ⚖️ Legal  
**Repository:** https://github.com/malkreide/fedlex-mcp  
**GitHub Stars:** 5  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/fedlex-mcp-2

## Description
Swiss federal law via Fedlex SPARQL endpoint

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `uvx` (confidence: high):

```json
"mcpServers": {
  "fedlex-mcp": {
    "command": "uvx",
    "args": ["fedlex-mcp"]
  }
}
```

## Documentation & README

> :switzerland: **Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide)**

# :balance_scale: fedlex-mcp

![Version](https://img.shields.io/badge/version-2.0.1-blue)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![MCP](https://img.shields.io/badge/MCP-Model%20Context%20Protocol-purple)](https://modelcontextprotocol.io/)
[![No Auth Required](https://img.shields.io/badge/auth-none%20required-brightgreen)](https://github.com/malkreide/fedlex-mcp)
![CI](https://github.com/malkreide/fedlex-mcp/actions/workflows/ci.yml/badge.svg)

> 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

[:de: Deutsche Version](https://github.com/malkreide/fedlex-mcp/blob/HEAD/README.de.md)

---

## Overview

`fedlex-mcp` connects AI assistants (Claude) with three official Swiss SPARQL data sources:

1. **Federal law** via the **Fedlex SPARQL endpoint** — the Systematic Compilation (SR), Official Compilation (AS), Federal Gazette (BBl) and treaties.
2. **Consultations (Vernehmlassungen)** via the *same* Fedlex endpoint (`jolux:Consultation`) — the pre-parliamentary phase in which anyone can comment on a draft.
3. **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:

```
fedlex_get_open_consultations(topic="education")
   → fedlex_get_consultation(event_id="proj/2026/71/cons_1")
   → termdat_lookup_term(term="Volksschule", target_languages=["fr","it"])
```

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"`, not `keyword="Volksschule"`.** Fedlex consultations
> have no subject taxonomy — filtering is free-text over the title, and the word
> "Volksschule" appears in **zero** consultation titles. The `topic` filter
> expands to a disclosed keyword union (Bildung, Schule, Berufsbildung,
> Hochschule, …) and reports exactly which terms it searched.

---

## Prerequisites

- Python 3.11+
- [uv](https://github.com/astral-sh/uv) (recommended) or pip

---

<!-- BEGIN GENERATED: install -->
## Installation

Run via [`uv`](https://docs.astral.sh/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`):

```json
{
  "mcpServers": {
    "fedlex-mcp": {
      "command": "uvx",
      "args": [
        "fedlex-mcp"
      ]
    }
  }
}
```
<!-- END GENERATED: install -->

---

## Installation from source

```bash
# Clone the repository
git clone https://github.com/malkreide/fedlex-mcp.git
cd fedlex-mcp

# Install
pip install -e .
# or with uv:
uv pip install -e .
```

Or with `uvx` (no permanent installation):

```bash
uvx fedlex-mcp
```

---

## Quickstart

```bash
# stdio (for Claude Desktop)
python -m fedlex_mcp.server

# Streamable HTTP (port 8000)
python -m fedlex_mcp.server --http --port 8000
```

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):

```json
{
  "mcpServers": {
    "fedlex": {
      "command": "python",
      "args": ["-m", "fedlex_mcp.server"]
    }
  }
}
```

Or with `uvx`:

```json
{
  "mcpServers": {
    "fedlex": {
      "command": "uvx",
      "args": ["fedlex-mcp"]
    }
  }
}
```

**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):**
1. Push/fork the repository to GitHub
2. On [render.com](https://render.com): New Web Service -> connect GitHub repo
3. Set start command: `python -m fedlex_mcp.server --http --port 8000`
4. 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](https://raw.githubusercontent.com/malkreide/fedlex-mcp/HEAD/docs/assets/demo.svg)

---

## Available Tools

| # | 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 |

### Example Use Cases

| 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 →

---

## 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.

```
+-------------------+     +------------------------------+     +--------------------------+
|   Claude / AI     |---->|  Fedlex MCP                  |---->|  Fedlex SPARQL Endpoint  |
|   (MCP Host)      |<----|  (MCP Server)                |<----|  fedlex.data.admin.ch    |
+-------------------+     |                              |     |  (law + consultations)   |
                          |  12 Tools . 2 Resources      |     +--------------------------+
                          |  Stdio | SSE                 |
                          |                              |     +--------------------------+
                          |  Isolated clients:           |---->|  LINDAS SPARQL Endpoint  |
                          |   - Fedlex  (law + cons.)     |<----|  lindas.admin.ch/query   |
                          |   - LINDAS  (TERMDAT)         |     |  (fch/termdat, TERMDAT)  |
                          |                              |     +--------------------------+
                          |  No authentication required  |
                          +------------------------------+
```

### Data Model

**JOLux Ontology — federal law (Fedlex)**

```
jolux:ConsolidationAbstract  <-  SR entry
  +-- jolux:isRealizedBy  ->  jolux:Expression (URI ends in /de, /fr, /it, /rm)
     +-- jolux:title               "Federal Act of 19 June 1992 on Data Protection"
     +-- jolux:titleShort          "DSG"
     +-- jolux:historicalLegalId   "235.1"

jolux:inForceStatus:  .../0 In force  ·  .../1 No longer published in SR  ·  .../3 No longer in force
```

**JOLux Ontology — consultations (Fedlex, same endpoint)**

```
jolux:Consultation
  +-- jolux:eventId                     "proj/2026/71/cons_1"
  +-- jolux:eventTitle                  multilingual (de/fr/it)
  +-- jolux:eventDescription            multilingual
  +-- jolux:consultationStatus          -> vocabulary URI (0..6, /2 = "Laufend"/running)
  +-- jolux:foreseenImpactToLegalResource  -> the legal resource it will amend (link to SR)
  +-- jolux:hasSubTask  ->  ?t
        +-- jolux:eventStartDate                      <- opened_on
        +-- jolux:eventEndDate                        <- the deadline (xsd:date, calendar day)
        +-- jolux:institutionInChargeOfTheEvent       <- lead department
        +-- jolux:institutionInChargeOfTheEventLevel2 <- lead office
        +-- jolux:opinionHasDraftRelatedDocument      <- consultation documents
```

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):**

```
  Vernehmlassung            Bundesblatt (BBl)          Systematische Sammlung (SR)
  (consultation)     ─────► (dispatch / act text) ───► (consolidated law in force)
  ────────────────         ─────────────────────      ───────────────────────────
  fedlex_get_open_          fedlex_search_gazette      fedlex_search_laws
    consultations           (eli/fga/…)                fedlex_get_law_by_sr
  fedlex_search_                                       fedlex_get_law_history
    consultations                                      (eli/cc/…)
  fedlex_get_consultation
        │  jolux:foreseenImpactToLegalResource
        └───────────────────────────────────────────► links a consultation forward
                                                       to the SR resource it amends
```

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`)**

```
<concept>  = https://register.ld.admin.ch/termdat/40109      (a schema.ld.admin.ch/Term, ValidatedEntry)
  +-- schema:name         preferred name per language (de/fr/it/en; rm effectively absent)
  +-- schema:description  multilingual definition
  +-- schema:hasPart  ->  <term> = .../termdat/40109/3/de     (synonym/variant, language + position suffix)
```

**SPARQL endpoints:** `https://fedlex.data.admin.ch/sparqlendpoint` · `https://lindas.admin.ch/query`
**Licence:** Free reuse per [fedlex.admin.ch](https://www.fedlex.admin.ch/de/broadcasters); 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

| Code | Language |
|------|----------|
| `de` | German (default, most complete coverage) |
| `fr` | French |
| `it` | Italian |
| `rm` | Romansh |

---

## Project Structure

```
fedlex-mcp/
+-- src/fedlex_mcp/
|   +-- __init__.py              # Package
|   +-- server.py                # 12 tools, 2 resources (Fedlex + LINDAS)
+-- tests/
|   +-- test_server.py           # Unit tests (mocked)
+-- .github/workflows/ci.yml     # GitHub Actions (Python 3.11/3.12/3.13)
+-- pyproject.toml
+-- CHANGELOG.md
+-- CONTRIBUTING.md               # Contributing guide (English)
+-- CONTRIBUTING.de.md            # Contributing guide (German)
+-- SECURITY.md                   # Security policy (English)
+-- SECURITY.de.md                # Security policy (German)
+-- LICENSE
+-- README.md                    # This file (English)
+-- README.de.md                 # German version
```

---

## 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: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.
- **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_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 |

- **Quirk 1 — the deadline wins over the status field.** Status `/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`.

### TERMDAT (LINDAS) — findings (verified 2026-07-18)

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

- **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 via `schema: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:

```
Vernehmlassung  →  Botschaft  →  Parlament  →  Referendum
(consultation)     (dispatch)    (debate)      (popular vote)
   fedlex-mcp        fedlex-mcp    parlament-mcp   swiss-democracy-mcp
```

- **Consultation (pre-parliamentary):** this server — `fedlex_*consultation*` tools.
- **Parliamentary phase:** [`parlament-mcp`](https://github.com/malkreide) — debates, motions, votes in the Federal Assembly.
- **Popular vote / referendum:** [`swiss-democracy-mcp`](https://github.com/malkreide) — 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.

| 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.

---

## 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.

| 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`](https://github.com/malkreide/fedlex-mcp/blob/HEAD/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`](https://github.com/malkreide/fedlex-mcp/blob/HEAD/CHANGELOG.md) together.

Two consequences of the modern revision are visible in this server:

- **CORS names the routing headers.** `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`.
- **The listing methods carry a freshness hint.** `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.

---

## Testing

```bash
# Unit tests (no API key required)
PYTHONPATH=src pytest tests/ -m "not live"

# Integration tests (live API calls)
pytest tests/ -m "live"
```

---

## 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 `limit` parameters 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](https://www.fedlex.admin.ch/de/broadcasters) — 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](https://github.com/malkreide/fedlex-mcp/blob/HEAD/CHANGELOG.md)

---

## Contributing

See [CONTRIBUTING.md](https://github.com/malkreide/fedlex-mcp/blob/HEAD/CONTRIBUTING.md)

---

## Security

See [SECURITY.md](https://github.com/malkreide/fedlex-mcp/blob/HEAD/SECURITY.md) for the security posture, hardening controls, and how to report a vulnerability.

---

## License

MIT License — see [LICENSE](https://github.com/malkreide/fedlex-mcp/blob/HEAD/LICENSE)

---

## Author

Hayal Oezkan . [malkreide](https://github.com/malkreide)

---

## Credits & Related Projects

- **Fedlex:** [fedlex.admin.ch](https://www.fedlex.admin.ch/) — Swiss Federal Chancellery
- **TERMDAT / LINDAS:** [lindas.admin.ch](https://lindas.admin.ch/) — Linked Data service of the Swiss administration
- **Protocol:** [Model Context Protocol](https://modelcontextprotocol.io/) — Anthropic / Linux Foundation
- **Related:** [parlament-mcp](https://github.com/malkreide) — Swiss Federal Assembly (parliamentary phase)
- **Related:** [swiss-democracy-mcp](https://github.com/malkreide) — Swiss federal popular votes (referendum phase)
- **Related:** [swiss-cultural-heritage-mcp](https://github.com/malkreide/swiss-cultural-heritage-mcp) — Swiss cultural heritage data
- **Related:** [zurich-opendata-mcp](https://github.com/malkreide/zurich-opendata-mcp) — City of Zurich open data
- **Related:** [swiss-transport-mcp](https://github.com/malkreide/swiss-transport-mcp) — Swiss public transport
- **Portfolio:** [Swiss Public Data MCP Portfolio](https://github.com/malkreide)

<!-- mcp-name: io.github.malkreide/fedlex-mcp -->

