Skip to main content
Glama
voundbrand
by voundbrand

mv-wahl-mcp

MCP server for searching and retrieving the Wahlprogramme (election platforms) of all 19 parties admitted to the Landtagswahl Mecklenburg-Vorpommern 2026.

This is retrieval only — not a Wahl-O-Mat clone and not a voting recommender. Do not use it to compute "closeness" scores from user positions.

Built for Martin Müller / Remington S.: let a KI browse full party programmes (primary) plus the official bpb Wahl-O-Mat MV 2026 theses & answers (secondary corpus).

Quick start

git clone https://github.com/voundbrand/mv-wahl-mcp.git
cd mv-wahl-mcp
./run.sh

That's it. The script creates a virtual environment if needed, installs dependencies, and starts the MCP server. The pre-built search index is included — no rebuild required.

Requirements: Python 3.11+

Related MCP server: mcp-bundestag-de

Add to Cursor or Claude Desktop

Run ./run.sh --print-config to get a ready-to-paste MCP configuration:

./run.sh --print-config

Copy the output into your MCP config file:

  • Cursor: ~/.cursor/mcp.json or .cursor/mcp.json in your project

  • Claude Desktop: claude_desktop_config.json

If you already have other MCP servers configured, merge the mv-wahl entry into your existing mcpServers object.

Features

Tool

Purpose

list_parties

All 19 parties + indexing status

search_programmes

FTS5 keyword search (query, optional party, corpus)

get_party_programme

Fetch sequential chunks for one party

coverage_status

Coverage table (source → indexed)

Corpora:

  • programme — full / website-captured Wahlprogramme (primary)

  • wahlomat — bpb Wahl-O-Mat MV 2026 dataset (theses + party answers)

Test search without MCP

./run.sh &  # or skip if you just want to test the search module
cd mv-wahl-mcp
source .venv/bin/activate
python -c "
from mv_wahl_mcp.search import search_programmes
import json
print(json.dumps(search_programmes('Wohnungsbau', limit=5), ensure_ascii=False, indent=2))
"

Data layout

data/
  parties.json          # metadata + source URLs for all 19
  programmes/           # PDF sources
  programmes_text/      # pdftotext extracts
  wahlomat/             # bpb Datensatz zip + xlsx
  index.db              # SQLite + FTS5 (pre-built, ready to use)

Wahl-O-Mat dataset

Downloaded from the bpb download page:

bpb licence restricts creating Wahl-O-Mat-like recommenders from the dataset; this project only indexes text for search/retrieval (journalistic/research-style analysis).

Programme sources

Prefer official party / Landesverband PDFs where available. Many smaller parties are mirrored via the schwerin.news Aug 2026 aggregation of all admitted lists:

See data/parties.json and the coverage_status tool for per-party notes. Short / website-captured texts (e.g. Die PARTEI, WLD, Team Freiheit, Handwerker 10-Punkte) are documented honestly.

Re-extract / re-index (optional)

Only needed if you modify the source PDFs or Wahl-O-Mat data:

# Needs poppler-utils (pdftotext)
for f in data/programmes/*.pdf; do
  base=$(basename "$f" .pdf)
  pdftotext -layout "$f" "data/programmes_text/${base}.txt"
done
python scripts/build_index.py

Licence / ethics

  • Party programmes remain copyright of the respective parties.

  • Wahl-O-Mat dataset © Bundeszentrale für politische Bildung — see data/wahlomat/Hinweis.txt.

  • This tool must not be turned into a proximity/voting recommender.

Coverage (build-time snapshot)

All 19/19 admitted Landeslisten are indexed. Volume varies:

Party

Chars (approx)

Notes

SPD, AfD, CDU, Die Linke, GRÜNE, FDP, BSW, Volt

large full programmes

Official / Landesverband PDFs

Tierschutzpartei, FREIE WÄHLER, Bündnis C, PdF, KPD

medium

Official or aggregator PDFs

PIRATEN, ÖDP

shorter full programmes

Official / aggregator

Die PARTEI, Team Freiheit, WLD

website captures

No long PDF published

Handwerker Partei Deutschland

short 10-point PDF

Intentional short programme

Secondary corpus: 722 Wahl-O-Mat position rows (38 theses × 19 parties) from the official bpb dataset.

Available Tools

4 tools
coverage_statusA

Return coverage table: which of the 19 parties are indexed and source notes.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior2/5

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

With no annotations provided, the description must convey behavioral traits. It only states 'Return', implying a read operation, but does not explicitly confirm it is non-destructive, nor does it mention any side effects, permissions, or limitations. The behavior is essentially a simple retrieval, but this is not disclosed beyond the verb.

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 a single, direct sentence that front-loads the action and specifies the output content. There is no unnecessary wording or repetition, making it highly efficient.

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 and no parameters, the description provides the essential context: it returns a coverage table of indexed parties with source notes. It mentions the specific count of 19 parties, which is helpful. The description is sufficient for an agent to know what to expect, though it could optionally clarify the read-only nature, which is covered by behavioral transparency.

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 tool has zero parameters, so the input schema is fully covered by default. The description correctly avoids adding parameter details since there are none, earning the baseline score for parameterless 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 specifies a clear action ('Return coverage table') and identifies the specific content (which of the 19 parties are indexed and source notes). This distinguishes it from siblings like list_parties (listing) and search_programmes (searching) by focusing on coverage status.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives. It merely states what it does without any contextual triggers, exclusions, or references to sibling tools.

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

get_party_programmeA

Fetch sequential text chunks from one party's programme (or Wahl-O-Mat answers).

Args: party: Party id or short name (e.g. "CDU", "Volt", "BSW"). offset: Chunk offset (0-based). limit: Number of chunks to return (1–50). corpus: "programme" (default) or "wahlomat".

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
partyYes
corpusNoprogramme
offsetNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

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

With no annotations, the description carries the behavioral burden. It discloses the sequential chunking behavior and the alternative corpus, which is helpful. However, it does not describe edge cases like end-of-document behavior, chunk ordering guarantees, or whether the operation is purely read-only, though 'Fetch' implies a safe read.

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 short and purposeful: a one-sentence summary followed by a compact Args block. Every line adds necessary parameter semantics, with no filler or repetition of schema titles.

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?

The tool is simple and an output schema exists, so return values need no explanation. The description covers core behavior and all parameters, though it omits minor context such as how to discover valid party IDs via list_parties. This is a minor gap given the provided examples.

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?

Schema description coverage is 0%, so the description must compensate, and it does thoroughly. It explains each parameter beyond the schema: party with concrete examples, offset as 0-based chunk offset, limit as a 1–50 count, and corpus with its two possible values and default.

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 states a specific verb ('Fetch'), a resource ('sequential text chunks from one party's programme'), and an optional alternative corpus ('Wahl-O-Mat answers'). It clearly distinguishes from sibling tools like search_programmes by emphasizing sequential chunk retrieval versus searching, though it does not explicitly name alternatives.

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?

Usage is implied by the description: use this tool when you need to read a party's programme or Wahl-O-Mat answers as sequential chunks. However, it provides no explicit when-to-use or when-not-to-use guidance, and does not mention search_programmes or list_parties as alternatives for different needs.

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

list_partiesA

List all 19 parties with indexing status, source notes, and chunk counts.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

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?

With no annotations, the description carries the behavioral burden. It accurately portrays a read-only list operation, states the fixed scope (all 19 parties), and describes the returned content. It does not mention auth or rate limits, but for a simple listing tool the behavioral profile is sufficiently clear.

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?

A single sentence that is front-loaded with the core action and scope, followed by the specific output attributes. Every word earns its place with no filler or repetition.

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 parameterless list tool with an output schema, the description covers the essential use case and return content, which is sufficient. It does not mention ordering, but given the fixed 'all 19 parties' scope and available output schema, nothing critical is missing.

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 tool has zero parameters, so there is nothing for the description to explain beyond what the schema already shows. This meets the baseline for parameterless 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 uses a specific verb ('List') with a clear resource ('all 19 parties') and enumerates the output fields (indexing status, source notes, chunk counts). This clearly distinguishes it from siblings like search_programmes and get_party_programme, which target searching or single-party retrieval.

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 implies when to use the tool—when an agent needs an overview of all parties—but it does not explicitly state alternatives or when not to use it. No exclusions or comparisons to sibling tools are given, so usage guidance is inferred rather than explicit.

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

search_programmesA

Keyword/FTS search across Wahlprogramme (and optionally Wahl-O-Mat answers).

Args: query: Search terms in German or English (e.g. "Wohnungsbau", "Energiewende"). party: Optional party filter (id or short name, e.g. "SPD", "GRÜNE", "Die Linke"). corpus: Optional "programme" (full platforms) or "wahlomat" (theses + answers). limit: Max hits (1–50, default 10).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
partyNo
queryYes
corpusNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

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

With no annotations present, the description carries the full burden. It conveys important behavior constraints like language support, optional corpora, and a 1–50 hit limit, which is useful. It does not explicitly state that this is read-only/has no side effects, nor how null party/corpus defaults behave, though the output schema helps with return shape.

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 compact and well-structured: a one-line purpose statement followed by a labeled Args block. Every line contributes useful parameter or behavior information, with no filler or redundancy.

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 search tool with four parameters and an output schema, this description is nearly complete: all parameters are explained with types, examples, and constraints. The only gaps are the lack of explicit sibling-tool routing and a precise statement of default corpus behavior, which are minor given the clear operation and output schema.

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?

Schema description coverage is 0%, and the description fully compensates: it explains query semantics with language examples, party as id or short name with examples, corpus as 'programme' vs 'wahlomat', and limit range/default. This adds genuine meaning beyond the bare property titles.

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 starts with a specific action and resource: 'Keyword/FTS search across Wahlprogramme (and optionally Wahl-O-Mat answers).' This makes the tool's scope clear and distinguishes it from sibling tools like list_parties, coverage_status, and get_party_programme, which are not search operations.

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 Args block provides operational guidance, such as party filters, corpus selection, and limit range, so an agent knows how to shape calls. However, it never explicitly says when to prefer this tool over get_party_programme or when not to use it, leaving cross-tool routing implied rather than stated.

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.

  1. 4 tool updatesv0.1.0
    • First observedcoverage_status
    • First observedget_party_programme
    • First observedlist_parties
    • First observedsearch_programmes

TDQS

A3.9/5.0

Scored across 4 tools

Disambiguation3/5

The tools list_parties and coverage_status both report on which of the 19 parties are indexed, with only minor differences (chunk counts vs. a coverage table). This overlap could cause misselection, while search_programmes and get_party_programme are clearly distinct.

Naming Consistency4/5

Tool names are consistently lowercase with underscores and mostly follow a verb_noun pattern (list_parties, search_programmes, get_party_programme). The exception is coverage_status, which uses a noun phrase, but it remains readable and predictable.

Tool Count5/5

With exactly 4 tools, the server is well-scoped for its purpose of listing, checking coverage, searching, and retrieving election programme content. Each tool has a clear role and the count is appropriate.

Completeness5/5

The server covers the core read-only workflows: listing parties, verifying indexing status, performing keyword search, and fetching chunked content. No obvious gaps exist for the stated domain of accessing Wahlprogramme and Wahl-O-Mat data.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Provides unified access to German federal and state legislation, court decisions, and European Union legal databases for comprehensive legal research. It enables users to search and retrieve full-text laws, parliamentary documents, and judicial rulings directly through the Model Context Protocol.
    20
    122 npm
    GPL 3.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables searching and retrieving documents, activities, and plenary protocols from the German Bundestag's DIP system via MCP tools.
    3 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides programmatic access to official German Bundestag parliamentary data, enabling LLMs to answer questions about legislation, voting records, and members.
    1
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Provides live, source-linked transparency data on German MPs, including roll-call voting, side jobs, committee memberships, and election programs, via the Abgeordnetenwatch API. No API key required.
    -