MCP Marketplace
BrowseHow It WorksFor CreatorsDocs
Sign inSign up
MCP Marketplace

The curated, security-first marketplace for AI tools.

Product

Browse ToolsSubmit a ToolDocumentationHow It WorksBlogFAQ

Legal

Terms of ServicePrivacy PolicyCommunity Guidelines

Connect

support@mcp-marketplace.ioTwitter / XDiscord

MCP Marketplace Β© 2026. All rights reserved.

Back to Browse

Openlex MCP Server

by Malkreide
Developer ToolsLow Risk10.0MCP RegistryLocal
Free

Server data from the Official MCP Registry

Canton Zurich legislation via ZH-Lex with full-text search and article extraction

About

Canton Zurich legislation via ZH-Lex with full-text search and article extraction

Security Report

10.0
Low Risk10.0Low Risk

Valid MCP server (1 strong, 3 medium validity signals). No known CVEs in dependencies. Package registry verified. Imported from the Official MCP Registry.

3 files analyzed Β· 1 issue found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

HTTP Network Access

Connects to external APIs or services over the internet.

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-malkreide-openlex-mcp": {
      "args": [
        "openlex-mcp"
      ],
      "command": "uvx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

πŸ‡¨πŸ‡­ 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.

SourceDataAccess
HuggingFace974 ZH laws β€” full text (PDF extracts)Cached locally as SQLite + FTS5
zh.ch ZH-LexCurrent metadata, PDF links, validity statusLive 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 for the phase plan and transition gates before any write or multi-agent capability is added.


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 β€” 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):

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

ToolDescription
openlex__zhlaw_search_lawsFull-text search across all ~970 ZH laws (FTS5 + BM25 ranking)
openlex__zhlaw_get_lawRetrieve a law by LS number (e.g. 412.100) or abbreviation (e.g. VSG)
openlex__zhlaw_list_lawsList and filter laws by legal area prefix
openlex__zhlaw_find_education_lawsSpecialized search in education law (LS 412.x series)

Article Extraction

ToolDescription
openlex__zhlaw_get_articleExtract a specific article from a law (e.g. Art. 28 VSG)
openlex__zhlaw_search_articlesSearch within all articles of a specific law

Metadata & Cache

ToolDescription
openlex__zhlaw_get_law_metadataGet live metadata from zh.ch (PDF links, validity status)
openlex__zhlaw_update_cacheRefresh the local data cache from HuggingFace

Key Legal Area Prefixes (LS Numbers)

PrefixLegal AreaExample
131Constitution and popular rightsKantonsverfassung
170Administrative procedureDatenschutzgesetz
331Tax lawSteuergesetz
412Education and schoolsVolksschulgesetz (VSG)
700Spatial planning and buildingPlanungs- und Baugesetz
810HealthGesundheitsgesetz

Example Use Cases

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

SourceProtocolCoverageAuthLicense
HuggingFace rcds/swiss_legislationDatasets API974 ZH laws (full text)NoneCC-BY-SA 4.0
zh.ch ZH-LexHTTP/HTMLCurrent metadata, PDFsNonePublic
LexFind.chHTTPCross-cantonal linksNonePublic

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 balancer to route on the Mcp-Session-Id header with a stick-table and an appropriate TTL.


MCP Protocol Version

ItemValue
Supported protocol version2025-11-25
SDKmcp[cli] >= 1.3.0 (FastMCP)
Pinned insrc/openlex_mcp/server.py β€” MCP_PROTOCOL_VERSION constant

Update policy

  1. When mcp is upgraded (via Dependabot PR), verify the protocol version in the SDK release notes.
  2. If the protocol version changes, update MCP_PROTOCOL_VERSION in server.py, regenerate docs/tool-hashes.json (PYTHONPATH=src python scripts/gen_tool_hashes.py > docs/tool-hashes.json), and note the change in CHANGELOG.md.
  3. Run pytest tests/ -m "not live" to confirm compatibility before merging.

Project Structure

openlex-mcp/
β”œβ”€β”€ src/openlex_mcp/
β”‚   β”œβ”€β”€ __init__.py              # Package
β”‚   β”œβ”€β”€ __main__.py              # Entry point for python -m
β”‚   β”œβ”€β”€ server.py                # 8 MCP tool definitions (FastMCP) + Settings
β”‚   β”œβ”€β”€ responses.py             # Typed structured response envelopes (SDK-002)
β”‚   β”œβ”€β”€ logging_config.py        # structlog JSON logging setup (OBS-003)
β”‚   β”œβ”€β”€ net.py                   # SSRF/egress-hardened outbound HTTP
β”‚   β”œβ”€β”€ 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/                       # 89 unit tests (parser, cache, net, tools…)
β”œβ”€β”€ scripts/gen_tool_hashes.py   # Tool-definition hash snapshot (SEC-022)
β”œβ”€β”€ docs/                        # network-egress, secret-management, tool-hashes
β”œβ”€β”€ .github/workflows/ci.yml     # GitHub Actions (Python 3.11/3.12/3.13)
β”œβ”€β”€ .github/dependabot.yml       # Weekly dependency PRs (ARCH-012)
β”œβ”€β”€ Dockerfile                   # Hardened multi-stage build (SEC-007/SCALE-004)
β”œβ”€β”€ compose.yml                  # Resource limits for local testing (SCALE-006)
β”œβ”€β”€ pyproject.toml
β”œβ”€β”€ claude_desktop_config.json   # Example config for Claude Desktop
β”œβ”€β”€ CHANGELOG.md
β”œβ”€β”€ ROADMAP.md                   # Phase plan + accepted-risk register
β”œβ”€β”€ CONTRIBUTING.md              # Contribution guide (English)
β”œβ”€β”€ CONTRIBUTING.de.md           # Contribution guide (German)
β”œβ”€β”€ SECURITY.md                  # Security policy (English)
β”œβ”€β”€ SECURITY.de.md               # Security policy (German)
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md                    # This file (English)
└── README.de.md                 # German version

Tool output format

All tools return a structured response envelope (not Markdown text), so MCP clients receive structuredContent they can parse directly:

{
  "source": "Kanton ZΓΌrich Rechtssammlung β€” HuggingFace … & zh.ch",
  "provenance": "cache",          // cache | live | parser | cache+parser | none
  "result_type": "law_summaries", // law_summaries | law_detail | articles | metadata | cache_status
  "count": 2,
  "message": null,                // human-readable guidance for empty/edge results
  "results": [ /* typed items */ ]
}

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

Safety & Limits

AspectDetails
AccessRead-only (readOnlyHint: true) β€” the server cannot modify or delete any data
Personal dataNo personal data β€” all sources are aggregated, public legal texts
Rate limitsBuilt-in per-query caps (max 50 search results, 5000 chars content preview)
Timeout30 seconds per HTTP call to zh.ch
EgressOutbound requests are restricted to an allow-list (www.zh.ch over HTTPS, plus the HTTP-only legacy permalink host www.zhlex.zh.ch), with SSRF IP-blocking and DNS-pinning β€” see docs/network-egress.md
AuthenticationNo API keys required β€” HuggingFace dataset is public, zh.ch is open
Security posture (Lethal Trifecta)Score 1 / 3: public data only (no private/sensitive data) βœ“ Β· GET-only egress to *.zh.ch β€” no POST, no webhooks, no email βœ“ Β· no code execution βœ“. Structurally safe by design.
Session handlingMcp-Session-Id generated and managed by the MCP SDK (cryptographically secure UUIDs). No user-identity binding β€” auth_model=none is correct for public read-only data. If authentication is ever added, bind sessions to the validated OAuth sub claim before deployment.
SecretsNo secrets held β€” all data sources are public. See docs/secret-management.md.
LicensesLaw data: CC-BY-SA 4.0 (rcds/swiss_legislation); zh.ch metadata: public
Terms of ServiceSubject to ToS of HuggingFace and Canton Zurich
DisclaimerThis server provides legal texts for informational purposes only β€” it does not constitute legal advice

To report a vulnerability, see the Security Policy.


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


Roadmap

See ROADMAP.md


Contributing

See CONTRIBUTING.md


Security

See SECURITY.md


License

MIT License β€” see LICENSE


Author

Hayal Oezkan Β· malkreide


Credits & Related Projects

  • Data: rcds/swiss_legislation β€” HuggingFace dataset (CC-BY-SA 4.0)
  • ZH-Lex: zh.ch Gesetzessammlung β€” Official Canton Zurich legal collection
  • LexFind: lexfind.ch β€” Cross-cantonal legislation database
  • Protocol: Model Context Protocol β€” Anthropic / Linux Foundation
  • Related: swiss-courts-mcp β€” Law text + case law = complete legal research
  • Related: zurich-opendata-mcp β€” Law text + city council decisions = full context
  • Portfolio: Swiss Public Data MCP Portfolio

Reviews

No reviews yet

Be the first to review this server!

0

installs

New

no ratings yet

Is this your server?

Claim ownership to manage your listing, respond to reviews, and track installs from your dashboard.

Claim with GitHub

Sign up with the GitHub account that owns this repo

Links

Source CodeDocumentationPyPI Package

Details

Published June 7, 2026
Version 0.2.3
0 installs
Local Plugin

More Developer Tools MCP Servers

Git

Free

by Modelcontextprotocol Β· Developer Tools

Read, search, and manipulate Git repositories programmatically

80.0K
Stars
4
Installs
6.5
Security
No ratings yet
Local

Fetch

Free

by Modelcontextprotocol Β· Developer Tools

Web content fetching and conversion for efficient LLM usage

80.0K
Stars
4
Installs
5.3
Security
No ratings yet
Local

Toleno

Free

by Toleno Β· Developer Tools

Toleno Network MCP Server β€” Manage your Toleno mining account with Claude AI using natural language.

137
Stars
496
Installs
8.0
Security
4.8
Local

mcp-creator-python

Free

by mcp-marketplace Β· Developer Tools

Create, build, and publish Python MCP servers to PyPI β€” conversationally.

-
Stars
68
Installs
10.0
Security
4.6
Local

MarkItDown

Free

by Microsoft Β· Content & Media

Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption

120.0K
Stars
24
Installs
6.0
Security
5.0
Local

FinAgent

Free

by mcp-marketplace Β· Finance

Free stock data and market news for any MCP-compatible AI assistant.

-
Stars
17
Installs
10.0
Security
No ratings yet
Local