Server data from the Official MCP Registry
Parliament OData, Swissvotes, referendums, voting results
About
Parliament OData, Swissvotes, referendums, voting results
Security Report
Valid MCP server (1 strong, 2 medium validity signals). No known CVEs in dependencies. Package registry verified. Imported from the Official MCP Registry. Trust signals: trusted author (60/61 approved).
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.
How to Install
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-malkreide-swiss-democracy-mcp": {
"args": [
"swiss-democracy-mcp"
],
"command": "uvx"
}
}
}Documentation
View on GitHubFrom the project's GitHub README.
π³οΈ swiss-democracy-mcp
π¨π Part of the Swiss Public Data MCP Portfolio β connecting AI models to Swiss institutional data sources.
π English | π©πͺ Deutsche Version
An MCP server providing access to Swiss direct democracy data, covering all federal popular votes since 1848 and elections since 1900.
Demo Query
Β«Wie hat der Kanton ZΓΌrich bei der AHV 21 Initiative 2022 abgestimmt,
und welche Parteien unterstΓΌtzten die Vorlage?Β»
β democracy_search_votes(keyword="AHV 21", year_from=2022)
β democracy_get_cantonal_results(vote_number="551")
β democracy_get_party_positions(vote_number="551")
β More use cases by audience β
Data Sources
| Source | Coverage | Auth |
|---|---|---|
| Swissvotes (Uni Bern) | All federal votes since 1848 Β· 874 columns Β· party positions Β· cantonal results | None β |
| BFS / opendata.swiss | Real-time & archive (since 1981) Β· municipality level | None β |
| SRGSSR Polis | Votes & elections since 1900 Β· municipality detail | OAuth2 key |
Tools
Phase 1 β Swissvotes (No Auth Required)
| Tool | Description |
|---|---|
democracy_search_votes | Search all federal popular votes since 1848 by keyword, date range, legal form, outcome, policy domain |
democracy_get_vote_detail | Full details for a specific vote: official title, parliamentary positions, national result, signatures |
democracy_get_party_positions | Party recommendations (FDP, SP, SVP, Die Mitte, GPS, GLP, β¦) with campaign finance data |
democracy_get_cantonal_results | Results for all 26 cantons: yes%, turnout, accepted flag |
democracy_list_vote_dates | List all voting dates with number of proposals per date |
Phase 2 β BFS Real-Time (No Auth Required)
| Tool | Description |
|---|---|
democracy_bfs_list_vote_dates | List all BFS voting dates (archive + current) |
democracy_bfs_get_vote_results | Real-time or archived results at national, cantonal, or municipality level |
Phase 3 β SRGSSR Polis (API Key Required)
| Tool | Description |
|---|---|
democracy_polis_list_votations | Historical votations since 1900 with municipality-level data |
democracy_polis_get_votation_detail | Full Polis detail, optionally with all municipality results |
democracy_polis_list_elections | National Council, Council of States, and cantonal elections since 1900 |
Installation
Claude Desktop (stdio)
Add to claude_desktop_config.json:
{
"mcpServers": {
"swiss-democracy": {
"command": "uvx",
"args": ["swiss-democracy-mcp"],
"env": {
"SRGSSR_CONSUMER_KEY": "your_key_here",
"SRGSSR_CONSUMER_SECRET": "your_secret_here"
}
}
}
}
The
SRGSSR_*variables are optional. Without them, all Swissvotes and BFS tools remain fully functional. Only the Polis tools require credentials.
Cloud / Render.com (Streamable HTTP)
pip install swiss-democracy-mcp
# Bind to all interfaces ONLY inside a container/cloud environment:
MCP_TRANSPORT=streamable_http MCP_HOST=0.0.0.0 MCP_PORT=8000 python -m swiss_democracy_mcp.server
MCP_HOST defaults to 127.0.0.1 (loopback). Set MCP_HOST=0.0.0.0 only
inside a sandboxed container/cloud deployment β never on a local machine, where
it would expose the server to your whole network.
Architecture
βββββββββββββββββββββββββββββββββββββββββββββββ
β Claude / LLM Host β
ββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β MCP (stdio / Streamable HTTP)
ββββββββββββββββΌβββββββββββββββββββββββββββββββ
β swiss-democracy-mcp β
β β
β βββββββββββββββββββββββββββββββββββββββ β
β β Swissvotes CSV Cache (24h TTL) β β
β β All 874 columns, since 1848 β β
β ββββββββββββββββ¬βββββββββββββββββββββββ β
β β β
β ββββββββββββββββΌβββββββββββββββββββββββ β
β β BFS / opendata.swiss (no auth) β β
β β Real-time & archive since 1981 β β
β ββββββββββββββββ¬βββββββββββββββββββββββ β
β β β
β ββββββββββββββββΌβββββββββββββββββββββββ β
β β SRGSSR Polis (OAuth2, optional) β β
β β Votes & elections since 1900 β β
β βββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββ
Transport: stdio for Claude Desktop Β· Streamable HTTP for cloud/Render.com
Auth pattern: No-Auth-First β Swissvotes & BFS work without any credentials
Cache: Swissvotes CSV is loaded once at startup and cached for 24 hours
Configuration
All configuration is via environment variables (see .env.example):
| Variable | Default | Purpose |
|---|---|---|
MCP_TRANSPORT | stdio | stdio (local) or streamable_http (cloud) |
MCP_HOST | 127.0.0.1 | HTTP bind address β set 0.0.0.0 only in a container |
MCP_PORT | 8000 | HTTP port |
LOG_LEVEL | INFO | structured JSON logs go to stderr |
MCP_CORS_ORIGINS | β | comma-separated CORS allow-origins for the HTTP transport. Empty means no browser client is permitted; * allows any origin and is logged as a warning. stdio clients are unaffected |
MCP_ALLOWED_HOSTS | β | comma-separated inbound Host allow-list. Only needed for a non-loopback bind |
SRGSSR_CONSUMER_KEY / SRGSSR_CONSUMER_SECRET | β | optional, only for democracy_polis_* tools |
Secrets are held as SecretStr and never logged. See
docs/secret-management.md and
docs/security.md.
MCP Primitives
This server intentionally exposes Tools only (no Resources or Prompts). It is
a Phase-1 read-only data wrapper (see docs/roadmap.md); the
tool surface is small (10 use-case-oriented tools) and every response is
self-contained with source provenance. Resources (e.g. vote://{anr}) are a
candidate for a later phase once the URI scheme stabilises.
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 and asserted
against the installed SDK, so a Dependabot bump of mcp cannot move either one
silently. This server builds no ASGI app to send an initialize through, so
the gate asserts the SDK constants rather than a measured response β the
weaker form, named rather than left unsaid.
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.
Portfolio Synergy
Combine with other servers in the Swiss Public Data MCP portfolio:
- zurich-opendata-mcp β add Zurich city-level statistics to vote analysis
- swiss-statistics-mcp β enrich with BFS demographic data by canton
- srgssr-mcp β link SRF news archive content to specific vote dates
Example multi-server query:
Β«Vergleiche die Abstimmungsresultate zur AHV-Reform mit der Altersstruktur der KantoneΒ»
β swiss-democracy-mcp + swiss-statistics-mcp
Safety & Limits
- Read-only: All tools perform HTTP GET requests only β no data is written, modified, or deleted upstream.
- Egress allow-list (SSRF protection): Outbound requests are restricted to a fixed allow-list of trusted hosts (
swissvotes.ch,opendata.swiss,*.bfs.admin.ch,api.srgssr.ch), HTTPS only. Caller-supplied URLs (the BFSresult_url) are additionally resolved and rejected if they point at private, loopback or cloud-metadata IP ranges. - No personal data: Swissvotes, BFS and SRGSSR Polis expose aggregate democratic data (vote results, party positions, cantonal/municipality tallies). No personally identifiable information (PII) is processed or stored by this server.
- Rate limits: Swissvotes is a single CSV downloaded once per 24h and cached in memory. BFS / opendata.swiss and SRGSSR Polis are public APIs without documented rate limits β keep
limitand date ranges conservative. The server enforces a 30s timeout per request. - Data freshness: Real-time BFS results reflect the upstream feed at query time (no local caching). Swissvotes is refreshed every 24h from the Uni Bern mirror.
- Terms of service: Data is subject to the ToS of each source β swissvotes.ch (CC BY 4.0, Uni Bern), opendata.swiss (mostly CC-BY / Open by Default), SRGSSR Polis (free tier, non-commercial use only). Always cite the upstream source in downstream products.
- No guarantees: This server is a community project, not affiliated with the University of Bern, the Federal Statistical Office, or SRG SSR. Availability depends on upstream APIs.
Known Limitations
- Swissvotes coverage: Cantonal-level results are available since 1848; municipality-level results only via SRGSSR Polis (since ~1990s depending on the vote).
- BFS archive: Real-time service covers federal votes since 1981 only.
- Polis tools: Require free registration at developer.srgssr.ch. Non-commercial use only.
- CSV cache: The Swissvotes dataset is ~several MB and is cached in memory for 24 hours. Memory footprint is accordingly higher than API-only servers.
Testing
# Unit tests (no network required)
PYTHONPATH=src pytest tests/ -m "not live" -v
# Live tests (require network access)
PYTHONPATH=src pytest tests/ -m "live" -v
Where the test data comes from
The fixtures under tests/fixtures/ are recorded from the live sources and
dated. Source, retrieval date, selection rule and SHA-256 for every file:
tests/fixtures/PROVENANCE.md.
python scripts/record_fixtures.py # re-record
The selection rule is the point here. The Swissvotes dataset has 714 rows
and 874 columns, and the recorded rows are chosen by property, not by
position. "The first N rows" would cut away exactly the cells the fixture
exists for: the placeholders 9999 ("no information") and . ("not
applicable"), which appear in 667 of the 714 votes. A fixture without them
would look clean and prove nothing β which is precisely why nobody noticed the
tools were passing them through as if they were values.
The byte-order mark stays in the file too, because the source sets one and the server strips it explicitly. Without it the fixture could not show that it has to.
SRGSSR Polis needs OAuth credentials and is listed under NOT RECORDED in
PROVENANCE.md rather than given a date it never had.
Contributing
See CONTRIBUTING.md (π©πͺ Deutsch).
Security
See SECURITY.md (π©πͺ Deutsch) for the security posture and vulnerability reporting.
License
MIT β see LICENSE.
Data licenses:
- Swissvotes: Creative Commons BY 4.0
- BFS / opendata.swiss: Open use
- SRGSSR Polis: Non-commercial use only β see developer.srgssr.ch
Author
Hayal Oezkan Β· github.com/malkreide
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):
{
"mcpServers": {
"swiss-democracy-mcp": {
"command": "uvx",
"args": [
"swiss-democracy-mcp"
]
}
}
}
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Git
Freeby Modelcontextprotocol Β· Developer Tools
Read, search, and manipulate Git repositories programmatically
Fetch
Freeby Modelcontextprotocol Β· Developer Tools
Web content fetching and conversion for efficient LLM usage
Toleno
Freeby Toleno Β· Developer Tools
Toleno Network MCP Server β Manage your Toleno mining account with Claude AI using natural language.
mcp-creator-python
Freeby mcp-marketplace Β· Developer Tools
Create, build, and publish Python MCP servers to PyPI β conversationally.
MCP Marketplace
Freeby mcp-marketplace Β· Developer Tools
Search and install MCP servers from inside your AI client.
MarkItDown
Freeby Microsoft Β· Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
