Skip to main content
ClaudeWave

MCP Server for Canton Zurich legislation (ZH-Lex) — full-text search, article extraction, and education law tools

MCP ServersOfficial Registry0 stars0 forksPythonMITUpdated today
ClaudeWave Trust Score
87/100
Trusted
Passed
  • Open-source license (MIT)
  • Actively maintained (<30d)
  • Clear description
  • Topics declared
Last scanned: 6/11/2026
Install in Claude Code / Claude Desktop
Method: pip / Python · -e
Claude Code CLI
claude mcp add openlex-mcp -- python -m -e
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "openlex-mcp": {
      "command": "python",
      "args": ["-m", "openlex_mcp.server"],
      "env": {
        "MCP_HOST": "<mcp_host>"
      }
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Install first: pip install -e
Detected environment variables
MCP_HOST
Use cases

MCP Servers overview

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

# ⚖️ openlex-mcp

![Version](https://img.shields.io/badge/version-0.2.5-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/openlex-mcp)

> MCP Server for Canton Zurich legislation (ZH-Lex) — full-text search, article extraction, and education law tools for ~970 cantonal laws

[🇩🇪 Deutsche Version](README.de.md)

<p align="center">
  <img src="assets/demo.png" alt="Demo: Claude searches Zurich education law via MCP tool call" width="720">
</p>

---

## Overview

`openlex-mcp` provides AI-native access to the entire legal collection of Canton Zurich (Zürcher Gesetzessammlung). It combines full-text data from HuggingFace with live metadata from the official zh.ch website, storing everything in a local SQLite database with FTS5 full-text indexing for sub-50ms search performance.

| Source | Data | Access |
|--------|------|--------|
| **HuggingFace** | 974 ZH laws — full text (PDF extracts) | Cached locally as SQLite + FTS5 |
| **zh.ch ZH-Lex** | Current metadata, PDF links, validity status | Live HTTP requests |

Built for the Schulamt (school department) of the City of Zurich, but covers all areas of cantonal law — from tax law to building regulations.

**Anchor demo query:** *"What does the Volksschulgesetz say about parental involvement? Show me Art. 55 VSG and find all articles that mention 'Elternrat'."*

---

## Features

- ⚖️ **8 tools** covering search, retrieval, article extraction, and cache management
- 🔍 **FTS5 full-text search** across ~970 cantonal laws with BM25 ranking
- 📑 **Article extraction** — parse individual articles (Art. / §) with paragraph detection
- 🏫 **Education law shortcuts** — specialized search for LS 412.x series (Volksschulgesetz, Lehrpersonalverordnung, etc.)
- 🌐 **Live metadata** from zh.ch for current validity status and PDF links
- 💾 **Hybrid architecture** — cached full-text (HuggingFace) + live metadata (zh.ch)
- 🔓 **No API key required** — all data under open licenses (CC-BY-SA 4.0)
- ☁️ **Dual transport** — stdio (Claude Desktop) + Streamable HTTP (cloud)

---

## Development Phase

**Current phase: Phase 1 — Read-Only.** All tools are read-only (`readOnlyHint: true`); no writes to external systems. See [ROADMAP.md](ROADMAP.md) for the phase plan and transition gates before any write or multi-agent capability is added.

---

## Prerequisites

- Python 3.11+
- [uv](https://github.com/astral-sh/uv) (recommended) or pip
- Internet connection (for initial data download and live metadata)

---

## Installation

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

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

---

## Quickstart

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

# Streamable HTTP — binds to 127.0.0.1:8000 by default (localhost only)
python -m openlex_mcp.server --http --port 8000
```

### Network binding

By default the HTTP transport binds to **`127.0.0.1`** (localhost only). The host
and port are configurable via the `MCP_HOST` / `MCP_PORT` environment variables
(or the `--host` / `--port` CLI flags, which take precedence).

**Never** bind to `0.0.0.0` outside a container — it exposes the server to your
local network (NeighborJack risk). For containerized/cloud deployments set
`MCP_HOST=0.0.0.0` explicitly; when that happens outside a detected container the
server logs a warning.

Try it immediately in Claude Desktop:

> *"What is the Volksschulgesetz (VSG)?"*
> *"Find all Zurich laws about data protection"*
> *"Show me Art. 1 of the Volksschulgesetz"*
> *"Which education laws mention 'Schulleitung'?"*

---

## Configuration

### Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

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

Or with the installed entry point:

```json
{
  "mcpServers": {
    "openlex": {
      "command": "openlex-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 openlex_mcp.server --http --port 8000`
4. Set environment variable `MCP_HOST=0.0.0.0` so the container is reachable
   (the code default is `127.0.0.1`; Render sets the `RENDER` env var, so no
   NeighborJack warning is logged)
5. Set `MCP_CORS_ORIGINS=https://claude.ai` so the browser can read the
   `Mcp-Session-Id` header (comma-separated list; **no wildcard** — defaults to
   empty, i.e. no cross-origin access)
6. In claude.ai under Settings → MCP Servers, add: `https://your-app.onrender.com/sse`

> 💡 *"stdio for the developer laptop, SSE for the browser."*

---

## Available Tools

### Search & Browse

| Tool | Description |
|------|-------------|
| `openlex__zhlaw_search_laws` | Full-text search across all ~970 ZH laws (FTS5 + BM25 ranking) |
| `openlex__zhlaw_get_law` | Retrieve a law by LS number (e.g. `412.100`) or abbreviation (e.g. `VSG`) |
| `openlex__zhlaw_list_laws` | List and filter laws by legal area prefix |
| `openlex__zhlaw_find_education_laws` | Specialized search in education law (LS 412.x series) |

### Article Extraction

| Tool | Description |
|------|-------------|
| `openlex__zhlaw_get_article` | Extract a specific article from a law (e.g. Art. 28 VSG) |
| `openlex__zhlaw_search_articles` | Search within all articles of a specific law |

### Metadata & Cache

| Tool | Description |
|------|-------------|
| `openlex__zhlaw_get_law_metadata` | Get live metadata from zh.ch (PDF links, validity status) |
| `openlex__zhlaw_update_cache` | Refresh the local data cache from HuggingFace |

### Key Legal Area Prefixes (LS Numbers)

| Prefix | Legal Area | Example |
|--------|-----------|---------|
| `131` | Constitution and popular rights | Kantonsverfassung |
| `170` | Administrative procedure | Datenschutzgesetz |
| `331` | Tax law | Steuergesetz |
| `412` | Education and schools | Volksschulgesetz (VSG) |
| `700` | Spatial planning and building | Planungs- und Baugesetz |
| `810` | Health | Gesundheitsgesetz |

### Example Use Cases

| Query | Tool |
|-------|------|
| *"What is the Volksschulgesetz?"* | `openlex__zhlaw_get_law` |
| *"Find laws about data protection"* | `openlex__zhlaw_search_laws` |
| *"Show me Art. 55 VSG"* | `openlex__zhlaw_get_article` |
| *"Which education laws mention Schulleitung?"* | `openlex__zhlaw_find_education_laws` |
| *"Find all articles about Elternrat in the VSG"* | `openlex__zhlaw_search_articles` |
| *"Is LS 412.100 still in force?"* | `openlex__zhlaw_get_law_metadata` |

---

## Architecture

```
┌─────────────────┐     ┌──────────────────────────────┐     ┌──────────────────────────┐
│   Claude / AI   │────▶│  OpenLex MCP                 │────▶│  HuggingFace             │
│   (MCP Host)    │◀────│  (MCP Server)                │◀────│  rcds/swiss_legislation   │
└─────────────────┘     │                              │     │  (974 ZH laws, cached)   │
                        │  8 Tools                     │     ├──────────────────────────┤
                        │  SQLite + FTS5 Cache         │────▶│  zh.ch ZH-Lex            │
                        │  Stdio | HTTP                │◀────│  (live metadata + PDFs)  │
                        │                              │     ├──────────────────────────┤
                        │  No authentication required  │     │  LexFind.ch              │
                        └──────────────────────────────┘     │  (links only)            │
                                                             └──────────────────────────┘
```

### Data Source Characteristics

| Source | Protocol | Coverage | Auth | License |
|--------|----------|----------|------|---------|
| HuggingFace `rcds/swiss_legislation` | Datasets API | 974 ZH laws (full text) | None | CC-BY-SA 4.0 |
| zh.ch ZH-Lex | HTTP/HTML | Current metadata, PDFs | None | Public |
| LexFind.ch | HTTP | Cross-cantonal links | None | Public |

### Design Decision: Tools-only (no MCP Resources)

All 8 endpoints are exposed as **Tools** rather than MCP Resources. Rationale:

- Every lookup is **parametric** — queries, abbreviations, article numbers vary per call. Static Resources (one URI per document) don't capture this naturally.
- The corpus is **974 laws × many articles** — registering each as a Resource URI would create an impractically large resource list.
- MCP Resource templates (`zhlex://laws/{sr_number}`) are a future consideration for Phase 2 if clients benefit from resource-level caching or subscriptions.

### Scaling Constraints

The Streamable-HTTP transport keeps session state **in-process** (FastMCP default). This has two implications:

- **Single-instance only** — horizontal scaling (multiple replicas) breaks active sessions because there is no shared session store (Redis, Durable Objects, etc.).
- **No sticky-session LB needed today** — a single-replica Render deployment naturally routes all requests to one process.

Before scaling beyond one instance: either add a shared session store **or** configure your edge load balance
educationllmmcpmodel-context-protocolpythonswiss-open-dataswiss-public-data-mcpzh-lexzurich-law

What people ask about openlex-mcp

What is malkreide/openlex-mcp?

+

malkreide/openlex-mcp is mcp servers for the Claude AI ecosystem. MCP Server for Canton Zurich legislation (ZH-Lex) — full-text search, article extraction, and education law tools It has 0 GitHub stars and was last updated today.

How do I install openlex-mcp?

+

You can install openlex-mcp by cloning the repository (https://github.com/malkreide/openlex-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is malkreide/openlex-mcp safe to use?

+

Our security agent has analyzed malkreide/openlex-mcp and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.

Who maintains malkreide/openlex-mcp?

+

malkreide/openlex-mcp is maintained by malkreide. The last recorded GitHub activity is from today, with 0 open issues.

Are there alternatives to openlex-mcp?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy openlex-mcp to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: malkreide/openlex-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/malkreide-openlex-mcp)](https://claudewave.com/repo/malkreide-openlex-mcp)
<a href="https://claudewave.com/repo/malkreide-openlex-mcp"><img src="https://claudewave.com/api/badge/malkreide-openlex-mcp" alt="Featured on ClaudeWave: malkreide/openlex-mcp" width="320" height="64" /></a>

More MCP Servers

openlex-mcp alternatives