Swiss Democracy Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Swiss Democracy Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
🇨🇭 Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide/swiss-public-data-mcp) — connecting AI models to Swiss institutional data sources.
🌐 English | [🇩🇪 Deutsche Version](README.de.md)
An MCP server providing access to Swiss direct democracy data, covering all federal popular votes since 1848 and elections since 1900.
Demo: Claude using democracy_search_votes, democracy_get_cantonal_results and democracy_get_party_positions
«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 →
| Source | Coverage | Auth |
|---|---|---|
| [Swissvotes](https://swissvotes.ch) (Uni Bern) | All federal votes since 1848 · 874 columns · party positions · cantonal results | None ✓ |
| [BFS / opendata.swiss](https://opendata.swiss/de/dataset/echtzeitdaten-am-abstimmungstag-zu-eidgenoessischen-abstimmungsvorlagen) | Real-time & archive (since 1981) · municipality level | None ✓ |
| [SRGSSR Polis](https://developer.srgssr.ch/api-catalog/srgssr-polis) | Votes & elections since 1900 · municipality detail | OAuth2 key |
| 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 |
| 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 |
| 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 |
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.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.serverMCP_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.
┌─────────────────────────────────────────────┐
│ 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
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 |
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.
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.
The protocol version is the one negotiated by mcp[cli]>=1.6.0 (FastMCP). SDK updates are tracked monthly via Dependabot; protocol bumps are recorded in CHANGELOG.md.
Combine with other servers in the Swiss Public Data MCP portfolio:
Example multi-server query: «Vergleiche die Abstimmungsresultate zur AHV-Reform mit der Altersstruktur der Kantone» → swiss-democracy-mcp + swiss-statistics-mcp
swissvotes.ch, opendata.swiss, *.bfs.admin.ch, api.srgssr.ch), HTTPS only. Caller-supplied URLs (the BFS result_url) are additionally resolved and rejected if they point at private, loopback or cloud-metadata IP ranges.limit and date ranges conservative. The server enforces a 30s timeout per request.# Unit tests (no network required)
PYTHONPATH=src pytest tests/ -m "not live" -v
# Live tests (require network access)
PYTHONPATH=src pytest tests/ -m "live" -vSee CONTRIBUTING.md (🇩🇪 Deutsch).
See SECURITY.md (🇩🇪 Deutsch) for the security posture and vulnerability reporting.
MIT — see LICENSE.
Data licenses:
<!-- mcp-name: io.github.malkreide/swiss-democracy-mcp -->
<!-- BEGIN GENERATED: install -->
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"
]
}
}
}<!-- END GENERATED: install -->
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.