Skip to main content
Glama
malkreide

swiss-democracy-mcp

by malkreide

🗳️ swiss-democracy-mcp

CI PyPI Python License: MIT MCP Swiss Public Data 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: Claude using democracy_search_votes, democracy_get_cantonal_results and democracy_get_party_positions


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 →


Related MCP server: parlament-mcp

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

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 BFS result_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 limit and 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:


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"
      ]
    }
  }
}

Available Tools

10 tools
democracy_bfs_get_vote_resultsA
Read-onlyIdempotent

Ruft Echtzeit- oder Archiv-Abstimmungsresultate vom BFS ab.

Resultate auf Gemeinde-/Kantons-/Bundesebene, v.a. am Abstimmungssonntag.

Nutzt die direkte JSON-URL eines Abstimmungsdatums (aus democracy_bfs_list_vote_dates). Gibt Resultate pro Vorlage auf nationaler, kantonaler oder Gemeindeebene zurück. Am Abstimmungssonntag werden die Daten laufend aktualisiert.

Args: params (BfsVoteResultInput): Enthält: - result_url (str): URL aus democracy_bfs_list_vote_dates - level (str): 'national', 'cantonal' oder 'municipality'

Returns: str: JSON mit Abstimmungsresultaten pro Vorlage

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true. The description adds that data is updated continuously on voting Sunday and returns results per template, which provides useful behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise at about five sentences, well-structured with a use_case tag and clear sections. Every sentence adds value without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (two parameters, output JSON schema available, annotations present), the description is complete: it explains the purpose, prerequisite, parameter semantics, and real-time behavior. No gaps remain for an agent to misuse the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully describes both parameters with detailed descriptions (e.g., result_url has maxLength, minLength; level has enum values explained). The description does not need to add more, but the schema itself is comprehensive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool fetches real-time or archive voting results from BFS. It specifies the use case and distinguishes from the sibling tool democracy_bfs_list_vote_dates by referencing its output as input.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes a use_case tag indicating when to use (election results at various levels, especially on voting Sunday). It mentions the prerequisite of using the URL from democracy_bfs_list_vote_dates. It does not explicitly list alternatives or when not to use, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_bfs_list_vote_datesA
Read-onlyIdempotent

Listet alle verfügbaren eidgenössischen Abstimmungsdaten im BFS-Echtzeit-Webservice auf.

Einstieg in BFS-Echtzeit-/Archivdaten; liefert die Ressourcen-URLs für democracy_bfs_get_vote_results.

Die Daten werden am Abstimmungssonntag ab 12:00 Uhr laufend aktualisiert. Das Archiv enthält eidgenössische Abstimmungen seit 1981.

Returns: str: JSON mit verfügbaren Abstimmungsdaten und deren Ressource-URLs

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint, idempotentHint, and openWorldHint. The description adds valuable behavioral context: data updates on voting Sunday from 12:00 and the archive contains votes since 1981. This goes beyond what annotations offer, though it could mention any rate limits or data freshness guarantees.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: two sentences plus a use_case tag and a returns line. It front-loads the core purpose and uses structured tags for additional context. Every sentence adds value without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no input parameters, a rich set of annotations, and an existing output schema, the description is complete. It explains the tool's role in the workflow, data update timing, and archive coverage. The sibling list and annotations provide further context, leaving no critical gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters, so the input schema provides complete coverage. The description does not need to add parameter details, meeting the baseline score of 4 for zero-parameter tools.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists available federal voting dates from the BFS real-time web service and serves as an entry point for BFS data. It distinguishes itself from sibling tools by specifying it provides resource URLs for democracy_bfs_get_vote_results, and the sibling list includes other democracy tools that cover different data scopes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly identifies the tool as an entry point for BFS real-time/archive data and mentions it feeds into democracy_bfs_get_vote_results, giving clear context for when to use it. However, it does not explicitly differentiate from the sibling tool 'democracy_list_vote_dates', which appears to be a non-BFS variant. Without contrast, the agent may be uncertain which listing tool to choose.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_get_cantonal_resultsA
Read-onlyIdempotent

Gibt die Abstimmungsresultate aller 26 Kantone für eine eidgenössische Volksabstimmung zurück.

Kantonsvergleich und Ständemehr-Analyse zu einer Vorlage.

Inkl. Stimmberechtigte, abgegebene Stimmen, gültige Stimmen, Ja- und Nein-Stimmen, Ja-Prozent und ob der Kanton angenommen hat (für Ständemehr-Zählung).

Args: params (VoteDetailInput): Enthält: - vote_number (str): Abstimmungsnummer (anr)

Returns: str: JSON mit kantonalen Resultaten (26 Kantone), nationalem Total und Stimmenmehr/Ständemehr-Übersicht

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, destructiveHint, and idempotentHint. The description adds meaningful behavioral context by listing the returned fields (Stimmberechtigte, gültige Stimmen, etc.) and confirming national total inclusion, which goes beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured, with clear sections for use case, parameter description, and return value description. Every sentence serves a purpose, and the key information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has an output schema (though not shown) and annotations, the description covers the necessary behavioral details. It includes return value structure and complements the schema. Minor gap: no error handling guidance, but not critical.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides a description for vote_number. The tool description does not add new parameter semantics beyond reiterating the role of vote_number. Schema coverage appears high, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns cantonal results for a federal vote, specifying the verb (gibt zurück) and resource (Abstimmungsresultate aller 26 Kantone). It includes a use case but does not explicitly differentiate from siblings like democracy_bfs_get_vote_results.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions when to use (cantonal comparison and Ständemehr analysis) but lacks explicit guidance on when not to use or alternatives. This is adequate but not comprehensive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_get_party_positionsA
Read-onlyIdempotent

Gibt die Parteiparolen der grossen Schweizer Parteien zu einer Volksabstimmung zurück.

Analyse von Parteilinien und Kampagnen-Finanzierung zu einer Vorlage.

Dekodiert die numerischen Parolen-Codes aus Swissvotes in lesbare Labels: 1=Ja, 2=Nein, 3=Stimmfreigabe, 4=Nein zum Gegenentwurf, 5=Ja zum Gegenentwurf, 66=Keine Parole gefasst, 9=Unbekannt.

Args: params (VoteDetailInput): Enthält: - vote_number (str): Abstimmungsnummer (anr)

Returns: str: JSON mit Parteiparolen und Links zu Ja-/Nein-Komitees

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint. The description adds value by explaining the decoding of numeric codes into labels and the return format (JSON with links to committees). No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections, but slightly lengthy (three paragraphs). Every sentence adds value, and the use case and code decoding are useful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with good annotations and a single well-described parameter, the description adequately covers purpose, input, and output. It could mention potential errors or rate limits but is largely complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema itself provides a good description of the vote_number parameter (including example values). The tool description adds a brief restatement, but no substantial new information. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it returns party positions (Parolen) for Swiss popular votes, distinguishing it from sibling tools like democracy_get_vote_detail or democracy_bfs_get_vote_results. However, the use of German may reduce clarity for non-German-speaking agents, and the exact scope is implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a use case ('Analyse von Parteilinien und Kampagnen-Finanzierung') but does not explicitly mention when to avoid this tool or suggest alternatives. Usage is implied rather than guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_get_vote_detailA
Read-onlyIdempotent

Gibt vollständige Details zu einer eidgenössischen Volksabstimmung zurück.

Vertiefung zu einer konkreten Vorlage (Parlamentsempfehlungen, Resultat, Beteiligung).

Inkl. offiziellem Titel, Rechtsform, Parlamentsempfehlungen (NR, SR, Bundesrat), Abstimmungsresultat (national und kantonal), Beteiligung, Finanzierungsdaten und Link zur Swissvotes-Seite.

Args: params (VoteDetailInput): Enthält: - vote_number (str): Abstimmungsnummer (anr) aus democracy_search_votes

Returns: str: JSON mit vollständigen Vote-Details oder Fehlermeldung

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint and idempotentHint, reducing burden. The description adds context about the returned JSON and error handling, and lists included fields, aligning with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a use-case block, list of included items, and Args/Returns sections. It is informative but could be slightly more concise by avoiding redundancy with schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and the presence of an output schema, the description covers input, use case, and output sufficiently. It mentions error messages and links to additional resources.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The only parameter (params) is described with details about its field (vote_number) and source in the description. The schema also provides a description, so the main description adds clarity about the input's origin.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it returns full details of a federal popular vote, listing specific elements. It distinguishes itself from siblings through the emphasis on 'complete details', but does not explicitly name differences.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes a use-case hint ('Vertiefung zu einer konkreten Vorlage') implying when to use, but lacks explicit when-not-to-use or alternatives. It references democracy_search_votes for input, providing context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_list_vote_datesA
Read-onlyIdempotent

Listet alle eidgenössischen Abstimmungsdaten auf, an denen Vorlagen zur Abstimmung kamen.

Orientierung/Navigation vor einer Detailabfrage.

Gibt für jedes Datum die Anzahl Vorlagen zurück. Nützlich zur Orientierung vor einer Detailabfrage.

Args: params (ListDatesInput): Optionaler Zeitraumfilter (year_from, year_to)

Returns: str: JSON mit Liste von Abstimmungsdaten und Anzahl Vorlagen pro Datum

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, destructiveHint=false, idempotentHint=true, covering safety. The description adds that it returns JSON with dates and proposal counts, but no additional behavioral traits like auth needs or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is concise and front-loaded with purpose. Some redundancy (e.g., 'Nützlich zur Orientierung...' appears twice), but overall efficient with mixed German and technical formatting.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given tool complexity (listing with filtering) and existence of output schema, description adequately explains return format (JSON with dates and counts). Lacks differentiation from sibling list tools but covers essentials.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so description must compensate. It mentions 'Optionaler Zeitraumfilter (year_from, year_to)' for two of three parameters but omits 'limit'. Partial coverage limits clarity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Listet alle eidgenössischen Abstimmungsdaten auf' (lists all federal voting dates), specifying verb, resource, and scope. It distinguishes from siblings like democracy_get_vote_detail and democracy_bfs_list_vote_dates by focusing on date listing with proposal counts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes a <use_case> tag indicating 'Orientierung/Navigation vor einer Detailabfrage' (orientation/navigation before a detail query), providing context for when to use. However, it does not explicitly exclude usage or mention alternatives like democracy_bfs_list_vote_dates.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_polis_get_votation_detailA
Read-onlyIdempotent

Gibt detaillierte Polis-Daten zu einer Volksabstimmung zurück.

Gemeindescharfe Detailanalyse einer historischen Abstimmung.

Optional mit Gemeinde-Resultaten – ideal für Fragen wie «Wie hat die Stadt Zürich bei der AHV-Reform abgestimmt?». Benötigt SRGSSR_CONSUMER_KEY und SRGSSR_CONSUMER_SECRET.

Args: params (PolisVotationDetailInput): Enthält: - votation_id (str): Polis-ID aus democracy_polis_list_votations - lang (str): Ausgabesprache - include_municipalities (bool): Gemeinderesultate einschliessen

Returns: str: JSON mit Polis-Abstimmungsdetails, kantonalen und optionalen Gemeindedaten

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it as read-only, idempotent, open-world. The description adds that it requires authentication (SRGSSR keys) and returns JSON with cantonal/optional municipal data, providing context beyond annotations. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with four sentences plus a structured use case tag and args list. Every sentence adds value: purpose, use case, auth, parameter overview. No fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description does not need to detail return values. It covers input, auth, and use case adequately. Minor omission: no mention of rate limits or pagination, but not critical given the straightforward single-item retrieval.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description lists the three parameters from the input schema, but the schema itself already has detailed descriptions for each (e.g., votation_id source, lang enum, municipality inclusion effect). The description adds the auth requirement but does not significantly enrich the semantic meaning of the parameters beyond the schema; baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns detailed Polis data for a popular vote, with optional municipal results. It specifies the resource (votation detail) and verb (get), and distinguishes from siblings like democracy_polis_list_votations (listing) and democracy_bfs_get_vote_results (BFS data).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a concrete use case (analyzing municipal results like Zurich's AHV vote) and prerequisites (votation_id from list_votations, SRGSSR keys). It does not explicitly state when not to use or list alternatives, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_polis_list_electionsA
Read-onlyIdempotent

Ruft historische Wahlen (National-/Ständerat, Regierungsrat) aus Polis ab.

Wahlanalysen (Kandidierende, Parteistimmen) seit 1900.

Polis enthält Wahlresultate seit 1900, inkl. Kandidatinnen- und Parteistimmen. Benötigt SRGSSR_CONSUMER_KEY und SRGSSR_CONSUMER_SECRET.

Args: params (PolisElectionInput): Enthält: - year_from/year_to (int): Zeitraumfilter - lang (str): Ausgabesprache - limit (int): Max. Resultate

Returns: str: JSON mit Wahlliste oder Hinweis zur Registrierung

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true, which cover safety. The description adds that authentication is required and returns JSON with election list or registration hint. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with a title, use case tag, authentication note, and separate Args/Returns sections. It is not overly long, but the German language and special characters may slightly reduce readability for English agents.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema (context signal), the description adequately covers purpose, parameters, authentication, and return type. It lacks explicit examples or exclusions, but for a list-like tool it is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description compensates by listing parameters (year_from, year_to, lang, limit) and their basic purpose. However, it does not provide detailed guidance such as format or example values beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it retrieves historical elections (National-/Ständerat, Regierungsrat) from Polis for analysis since 1900. The use case tag explicitly mentions 'Wahlanalysen', making the purpose distinct from sibling tools that deal with votations or popular votes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: it requires API keys (SRGSSR_CONSUMER_KEY and SECRET). It also gives a use case indicator. However, it does not explicitly contrast with sibling tools (e.g., democracy_polis_list_votations) to guide when to choose this tool over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_polis_list_votationsA
Read-onlyIdempotent

Ruft historische Volksabstimmungen aus dem SRGSSR Polis-System ab (seit 1900).

Historische Analysen mit Gemeinde-Granularität.

Polis enthält Resultate auf Gemeinde-Ebene, was für historische Analysen besonders wertvoll ist. Benötigt SRGSSR_CONSUMER_KEY und SRGSSR_CONSUMER_SECRET.

Args: params (PolisListInput): Enthält: - year_from/year_to (int): Zeitraumfilter - lang (str): Sprache ('de', 'fr', 'it', 'rm', 'en') - limit/offset (int): Pagination

Returns: str: JSON mit Polis-Abstimmungsliste oder Hinweis zur Registrierung

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent behavior. The description adds context about municipality granularity and authentication needs, but does not elaborate on rate limits or other constraints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with a use case tag, authentication note, and parameter summary. It is slightly verbose but well-organized and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, the description covers authentication, parameter usage, output format, and the value of municipality-level data. No obvious gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description lists the parameters (year_from/year_to, lang, limit, offset) but adds little meaning beyond the input schema, which already has clear descriptions. With high schema coverage, baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves historical popular votes from the SRGSSR Polis system since 1900, with municipality-level granularity, distinguishing it from sibling tools like detail or election queries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description highlights a specific use case (historical analysis at municipality level) and mentions authentication requirements, but does not explicitly state when not to use this tool or compare to alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

democracy_search_votesA
Read-onlyIdempotent

Durchsucht alle eidgenössischen Volksabstimmungen seit 1848 (Swissvotes-Datenbank).

Politische/journalistische Recherche: Vorlagen nach Thema, Zeitraum oder Ergebnis finden.

Filtert nach Stichwort, Zeitraum, Rechtsform, Ergebnis und Politikbereich. Gibt Titel, Datum, Rechtsform, Ja-Anteil, Beteiligung und Bundesratsempfehlung zurück.

Args: params (VoteSearchInput): Suchparameter mit optionalen Feldern: - keyword (str): Freitextsuche im Titel (DE/EN) - year_from/year_to (int): Zeitraumfilter - legal_form (str): 'initiative', 'obligatorisch', 'fakultativ' - result (str): 'angenommen' oder 'abgelehnt' - policy_domain (str): Politikbereich-Stichwort - limit (int): Max. Resultate (Standard: 20) - offset (int): Pagination-Offset

Returns: str: JSON mit 'total', 'count', 'offset', 'has_more', 'votes' (Liste von Vote-Objekten mit vote_number, date, title_de, legal_form, accepted, yes_percent, turnout_percent, federal_council_position)

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only, idempotent, non-destructive; description adds return field context and default limit, no contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections (description, use case, filters, returns, args), concise and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all relevant aspects: filters, pagination, return fields (output schema present), no gaps given complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has full descriptions for parameters; description briefly repeats them without adding significant new meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool searches all federal popular votes since 1848, with use case and filter options, distinguishing it from siblings like democracy_get_vote_detail.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides a use case tag and lists filter criteria, but lacks explicit when-not-to-use or alternative sibling guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 4 tool updatesv0.2.0
    • Changeddemocracy_bfs_get_vote_results1 field changed
      • addedInput schema / $defs / BfsVoteResultInput / properties / level / enum
        Added value: +[
        +  "national",
        +  "cantonal",
        +  "municipality"
        +]
    • Changeddemocracy_polis_get_votation_detail1 field changed
      • addedInput schema / $defs / PolisVotationDetailInput / properties / lang / enum
        Added value: +[
        +  "de",
        +  "fr",
        +  "it",
        +  "rm",
        +  "en"
        +]
    • Changeddemocracy_polis_list_elections1 field changed
      • addedInput schema / $defs / PolisElectionInput / properties / lang / enum
        Added value: +[
        +  "de",
        +  "fr",
        +  "it",
        +  "rm",
        +  "en"
        +]
    • Changeddemocracy_polis_list_votations1 field changed
      • addedInput schema / $defs / PolisListInput / properties / lang / enum
        Added value: +[
        +  "de",
        +  "fr",
        +  "it",
        +  "rm",
        +  "en"
        +]
  2. 10 tool updatesv0.1.0
    • First observeddemocracy_bfs_get_vote_results
    • First observeddemocracy_bfs_list_vote_dates
    • First observeddemocracy_get_cantonal_results
    • First observeddemocracy_get_party_positions
    • First observeddemocracy_get_vote_detail
    • First observeddemocracy_list_vote_dates
    • First observeddemocracy_polis_get_votation_detail
    • First observeddemocracy_polis_list_elections
    • First observeddemocracy_polis_list_votations
    • First observeddemocracy_search_votes

TDQS

A4.1/5.0
Disambiguation4/5

Most tools have distinct purposes, but there is overlap between democracy_list_vote_dates and democracy_bfs_list_vote_dates, and between democracy_get_vote_detail and democracy_bfs_get_vote_results. Descriptions clarify the different data sources, but an agent could still be confused.

Naming Consistency5/5

All tools follow a consistent 'democracy_' prefix with snake_case verb_noun pattern. Source-specific tools (bfs, polis) maintain their own sub-pattern, while generic tools use clear verbs like get, list, search. No mixing of conventions.

Tool Count5/5

10 tools is well-scoped for a Swiss democracy data server. Each tool covers a specific aspect: listing dates, searching, details, cantonal results, party positions, BFS real-time, Polis votes and elections. No tool feels superfluous or missing.

Completeness4/5

The tool set covers the main aspects of Swiss democratic data: vote search, listing, details, cantonal results, party positions, and two separate historical sources (Swissvotes and Polis). A minor gap is the lack of detailed election results (e.g., candidate-level data), but core workflows are supported.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/malkreide/swiss-democracy-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server