Skip to main content
Glama
nanditha1997

DIP Bundestag Fraktion distribution

by nanditha1997

DIP Bundestag Fraktion distribution

Look up politicians and calculate Bundestag Fraktion distributions using the DIP API. Python computes the statistics; Groq writes the explanations. Includes a command-line client and a bonus chat agent, both using the same MCP server.

Setup

Requires Python 3.11+ and DIP/Groq API keys. From the project root in PowerShell:

python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
Copy-Item .env.example .env

Copy the example only when creating .env for the first time. Fill in your keys:

DIP_API_KEY=your-dip-key
LLM_API_KEY=your-groq-key
LLM_PROVIDER=groq
LLM_MODEL=openai/gpt-oss-120b

The MCP tools need only DIP_API_KEY. CLI distribution narration and bonus chat also need the Groq key. Existing environment variables override .env.

On macOS/Linux, activate with source .venv/bin/activate and copy the example with cp .env.example .env. Without PowerShell activation, use .\.venv\Scripts\python.exe instead of python below.

Related MCP server: DIP Parliamentary Analyser

Run

python -m src.cli distribution 20
python -m src.cli person "Friedrich Merz"
python -m bonus.chat_agent

The distribution CLI prints a table and a Groq summary. The person CLI prints the DIP record. Bonus chat accepts questions such as:

  • "What is the party distribution in the 20th legislative session?"

  • "Who is Friedrich Merz?"

Use /quit or /exit to leave chat. To ask one question and exit:

python -m bonus.chat_agent --question "Who is Friedrich Merz?"

Add --trace to show MCP tool names and arguments on stderr:

python -m src.cli distribution 20 --trace
python -m src.cli person "Friedrich Merz" --trace
python -m bonus.chat_agent --trace

Architecture

Both clients start the same FastMCP server as a subprocess and communicate over MCP stdio. The server fetches DIP records and runs the Python services. It returns structured data and makes no LLM calls.

CLI / bonus chat <-> MCP stdio <-> FastMCP server -> DIP API + Python services

CLI:   MCP statistics -> Groq narrator -> printed summary
Bonus: Groq selects tool -> MCP data -> Groq formulates answer

MCP tool

Input

Output

get_party_distribution

wahlperiode: int

{total, parties: [{party, count, percentage}]}

get_person_info

name: str

Person fields, or {found: false, message}

Clients never call the services directly. Bonus tool selection is driven by the LLM using discovered schemas. A typical bonus lookup needs two Groq calls: one to select the tool and one to formulate the answer.

Assumptions and limits

  • Distribution includes records with funktion == "MdB" or ", MdB," in titel. This heuristic counts matching DIP records, not seats on a specific date.

  • For distributions, Fraktion comes from the first nonempty matching person_roles entry for the requested period, then the top-level value, then fraktionslos/unbekannt. Person lookup uses the top-level snapshot. An unknown snapshot is not proof of nonmembership.

  • Fraktionen are parliamentary groups, not necessarily individual parties. CDU/CSU is never split. Listed Wahlperioden refer to associated documents, not continuous membership or tenure.

  • DIP pagination deduplicates IDs. The client adapts observed singleton arrays for funktion and fraktion; ambiguous arrays are rejected.

  • Python rounds percentages to two decimals, so they may not total exactly 100%. Numeric checks constrain LLM output but do not guarantee correct prose.

  • API errors are reported without automatic retries. Groq 429 errors indicate rate limits or quota restrictions. If CLI narration fails, the statistics stay printed and the command exits with an error.

Tests

python -m pytest -q
python -m pip check

The 58 tests cover DIP requests and pagination, member filtering, aggregation, person lookup, MCP responses and errors, narration, and the bonus tool-call flow. They use mocked HTTP/model responses and in-memory MCP sessions, so no API keys or internet access are needed. They do not verify live LLM quality or subprocess startup.

Bonus example: two tools in one question

Run python -m bonus.chat_agent --trace to see the selected tools. This sample shows both tools used to answer one question; the client executes them sequentially. The output below was captured from a run; live data and generated wording can vary.

> who is alice weidel and what is the party distribution in 20th legislation
MCP tool: get_person_info {"name": "Alice Weidel"}
MCP tool: get_party_distribution {"wahlperiode": 20}

Alice Weidel is recorded by the DIP as a member of the German Bundestag (MdB) belonging to the AfD Fraktion. Her DIP identifier is 2187.

In the 20th legislative period the DIP lists 697 matching Bundestag members. The leading Fraktion is the SPD with 191 members (27.4 %), followed by CDU/CSU with 173 members (24.82 %) and the BÜNDNIS 90/DIE GRÜNEN with 114 members (16.36 %).

Fraktion

Count

Percentage

SPD

191

27.4 %

CDU/CSU

173

24.82 %

BÜNDNIS 90/DIE GRÜNEN

114

16.36 %

FDP

92

13.2 %

AfD

86

12.34 %

DIE LINKE

27

3.87 %

fraktionslos

13

1.87 %

Die Linke (Gruppe)

1

0.14 %

These figures refer to matching DIP member records under the MdB heuristic and are not a point‑in‑time seat count.

Related MCP Connectors

Related MCP Servers

  • 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.
    5 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