Skip to main content

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

Project description

๐Ÿ‡จ๐Ÿ‡ญ Part of the Swiss Public Data MCP Portfolio

โš–๏ธ openlex-mcp

Version License: MIT Python 3.11+ MCP No Auth Required

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

๐Ÿ‡ฉ๐Ÿ‡ช Deutsche Version


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)

Prerequisites

  • Python 3.11+
  • uv (recommended) or pip
  • Internet connection (for initial data download and live metadata)

Installation

# 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

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

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

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

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

Or with the installed entry point:

{
  "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: New Web Service โ†’ connect GitHub repo
  3. Set start command: python -m openlex_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."


Available Tools

Search & Browse

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

Article Extraction

Tool Description
zhlaw_get_article Extract a specific article from a law (e.g. Art. 28 VSG)
zhlaw_search_articles Search within all articles of a specific law

Metadata & Cache

Tool Description
zhlaw_get_law_metadata Get live metadata from zh.ch (PDF links, validity status)
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?" zhlaw_get_law
"Find laws about data protection" zhlaw_search_laws
"Show me Art. 55 VSG" zhlaw_get_article
"Which education laws mention Schulleitung?" zhlaw_find_education_laws
"Find all articles about Elternrat in the VSG" zhlaw_search_articles
"Is LS 412.100 still in force?" 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

Project Structure

openlex-mcp/
โ”œโ”€โ”€ src/openlex_mcp/
โ”‚   โ”œโ”€โ”€ __init__.py              # Package
โ”‚   โ”œโ”€โ”€ __main__.py              # Entry point for python -m
โ”‚   โ”œโ”€โ”€ server.py                # 8 MCP tool definitions (FastMCP)
โ”‚   โ”œโ”€โ”€ api_client.py            # zh.ch HTTP client + metadata extraction
โ”‚   โ”œโ”€โ”€ data_cache.py            # SQLite + FTS5 cache management
โ”‚   โ””โ”€โ”€ law_parser.py            # Article extraction from law texts
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ test_server.py           # Unit + integration tests
โ”œโ”€โ”€ .github/workflows/ci.yml     # GitHub Actions (Python 3.11/3.12/3.13)
โ”œโ”€โ”€ pyproject.toml
โ”œโ”€โ”€ claude_desktop_config.json   # Example config for Claude Desktop
โ”œโ”€โ”€ CHANGELOG.md
โ”œโ”€โ”€ CONTRIBUTING.md
โ”œโ”€โ”€ LICENSE
โ”œโ”€โ”€ README.md                    # This file (English)
โ””โ”€โ”€ README.de.md                 # German version

Known Limitations

  • HuggingFace dataset: The html_content field is unreliable (cross-contaminated between laws); the server uses pdf_content instead, which is correct but has PDF extraction artefacts (hyphenation, layout artefacts)
  • Article parser: PDF text extraction sometimes merges article boundaries; complex nested articles may not parse perfectly
  • Initial load: First start requires ~25s to download and index 974 laws from HuggingFace (~38 MB SQLite database)
  • zh.ch metadata: No official API; metadata extraction relies on HTML patterns that may change
  • Offline mode: Full-text search works offline after initial load; live metadata requires internet

Testing

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

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

Changelog

See CHANGELOG.md


Contributing

See CONTRIBUTING.md


License

MIT License โ€” see LICENSE


Author

Hayal Oezkan ยท malkreide


Credits & Related Projects

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openlex_mcp-0.1.0.tar.gz (26.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openlex_mcp-0.1.0-py3-none-any.whl (24.1 kB view details)

Uploaded Python 3

File details

Details for the file openlex_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: openlex_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 26.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openlex_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a925ba9c4ef6f0f8142590cf3d9ccb7ede4580370f44380b84c3f3cdfeaa7ffb
MD5 72b89f97ef42a4cba74f4a5e226b7252
BLAKE2b-256 69f67b9dfda96b3ff9f797e68543f9c7eb0a78b2f21e05df83e144c5273e12c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for openlex_mcp-0.1.0.tar.gz:

Publisher: publish.yml on malkreide/openlex-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openlex_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: openlex_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 24.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openlex_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ab998540771fcb113f6c407bdcfcb023e0d137b39e28a4fa8e54873b396ae93
MD5 0a8f8143fcd3342e79f71655e491714e
BLAKE2b-256 8fcf4b8d6ec53622c9b1b4e73a46b83348ebaf8b9efe7b9cd74e76c7e4aace71

See more details on using hashes here.

Provenance

The following attestation bundles were made for openlex_mcp-0.1.0-py3-none-any.whl:

Publisher: publish.yml on malkreide/openlex-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page