Bundestag MCP Server

Bundestag MCP Server

A production-ready MCP server that provides access to the German Bundestag's parliamentary documentation system (DIP API).

Category
访问服务器

README

Bundestag MCP Server

CI License: MIT Node.js

A production-ready Model Context Protocol (MCP) server that provides access to the German Bundestag's parliamentary documentation system (DIP API).

Public Instance

A public instance is available at:

https://bundestagapi.moritz-waechter.de/mcp

You can use this directly in your MCP client configuration without running your own server.

Table of Contents

Features

Core Capabilities

  • Search Drucksachen - Find bills, motions, inquiries, and other printed documents
  • Search Plenarprotokolle - Find plenary session transcripts
  • Search Vorgaenge - Track legislative proceedings through parliament
  • Search Personen - Find MPs and their information
  • Search Aktivitaeten - Find parliamentary activities (speeches, questions)
  • Full Text Retrieval - Get complete document texts
  • Semantic Search - AI-powered search using Qdrant + Mistral embeddings
  • Speech Search - Find specific statements in debates with hybrid vector/keyword search
  • Document Section Search - Search within document sections (articles, questions, etc.)
  • NLP Analysis - Extract speeches, analyze tone, classify topics, and compare parties

Production-Ready

  • Graceful Shutdown - Clean session termination on SIGTERM/SIGINT
  • Retry with Backoff - Automatic retries with exponential backoff and jitter
  • Rate Limiting - Token bucket rate limiter to protect upstream API
  • Circuit Breaker - Fast-fail pattern to prevent cascading failures
  • Response Caching - Three-layer caching (API, entity, metadata)

Observability

  • Prometheus Metrics - /metrics/prometheus endpoint for monitoring
  • Deep Health Checks - /health/deep verifies DIP API connectivity
  • Structured Logging - JSON logs with categories and levels

MCP Protocol

  • 33 Tools - Search, retrieval, semantic search, speech search, and NLP analysis
  • 8 Prompts - Guided workflows for common research tasks
  • 12 Resources - Static and dynamic resource templates
  • Dual Mode - Supports stateful (Claude, Cursor) and stateless (ChatGPT) clients

Quick Start

Prerequisites

  • Node.js 18+
  • DIP API Key (a public test key is provided)

Installation

git clone https://github.com/Movm/bundestag-mcp.git
cd bundestag-mcp
npm install

Configuration

Create a .env file (or copy .env.example):

# Public test key valid until 05/2026
DIP_API_KEY=OSOegLs.PR2lwJ1dwCeje9vTj7FPOt3hvpYKtwKkhw

# Optional
PORT=3000
PUBLIC_URL=
LOG_LEVEL=INFO

Note: For production, request your own API key from: parlamentsdokumentation@bundestag.de

Run

# Production
npm start

# Development (auto-reload)
npm run dev

The server will start at http://localhost:3000.

MCP Tools

Document Tools

Tool Description
bundestag_search_drucksachen Search printed documents (Gesetzentwürfe, Anträge, Anfragen)
bundestag_get_drucksache Get specific document by ID (optionally with full text)
bundestag_search_drucksachen_text Full-text search within document content

Protocol Tools

Tool Description
bundestag_search_plenarprotokolle Search plenary session transcripts
bundestag_get_plenarprotokoll Get specific protocol by ID (optionally with full text)
bundestag_search_plenarprotokolle_text Full-text search within transcript content

Proceeding Tools

Tool Description
bundestag_search_vorgaenge Search parliamentary proceedings
bundestag_get_vorgang Get specific proceeding by ID
bundestag_search_vorgangspositionen Search proceeding positions/steps (track bill progress)

Person & Activity Tools

Tool Description
bundestag_search_personen Search MPs and other persons
bundestag_get_person Get person details by ID
bundestag_search_aktivitaeten Search parliamentary activities
bundestag_get_aktivitaet Get specific activity by ID

Semantic Search Tools

Tool Description
bundestag_semantic_search AI-powered semantic search across all documents
bundestag_semantic_search_status Show semantic search system status
bundestag_trigger_indexing Manually trigger document indexing

Speech Search Tools

Tool Description
bundestag_search_speeches Semantic/hybrid search through parliamentary speeches
bundestag_trigger_protocol_indexing Trigger protocol chunking and indexing
bundestag_reindex_protocols Force full re-indexing of all protocols
bundestag_protocol_search_status Show protocol search system status

Document Section Search Tools

Tool Description
bundestag_search_document_sections Semantic search through document sections
bundestag_trigger_document_indexing Trigger document chunk indexing
bundestag_document_search_status Show document chunk search status

NLP Analysis Tools

These tools use a Python FastAPI service with spaCy's German language model for natural language processing.

Tool Description
bundestag_extract_speeches Parse protocol text into individual speeches with speaker, party, and type
bundestag_analyze_text Analyze German text for word frequencies (nouns, adjectives, verbs)
bundestag_analyze_tone Communication style analysis (aggression, collaboration, solution-focus)
bundestag_classify_topics Classify text by political topics (migration, climate, economy, etc.)
bundestag_analysis_health Check if the NLP analysis service is available
bundestag_speaker_profile Generate comprehensive profile for a speaker based on their speeches
bundestag_compare_parties Compare political parties based on their parliamentary speeches

Utility Tools

Tool Description
bundestag_estimate_size Check document/protocol size BEFORE fetching to manage context window
bundestag_cache_stats Show cache statistics
get_client_config Generate MCP client configurations

Common Parameters

Parameter Description
query Full-text search in title
wahlperiode Electoral period (e.g., 20 for current 2021-2025)
datum_start / datum_end Date range filter (YYYY-MM-DD)
limit Results per page (1-100, default 10)
cursor Pagination cursor from previous response
includeFullText Fetch full document text
useCache Whether to use cached results (default: true)

MCP Prompts

Guided workflows for common parliamentary research tasks:

Prompt Description
search-legislation Guided search for bills and legislation with semantic search and fallback strategies
track-proceeding Track a parliamentary proceeding with legislative glossary and timeline
mp-activity-report Comprehensive MP report with rhetorical analysis via bundestag_speaker_profile
analyze-debate Analyze plenary debate with party comparison via bundestag_compare_parties
compare-factions Compare party rhetoric on a topic using cross-party analysis
find-statements Find specific quotes/statements from politicians with fallback strategies
topic-trends Analyze how topic discussion evolved over time (across Wahlperioden/years)
speaker-deep-dive Comprehensive rhetorical and policy analysis of a politician

MCP Resources

Static Resources

URI Description
bundestag://system-prompt AI usage instructions with tool selection guide and context management
bundestag://info Server capabilities and tool listing
bundestag://wahlperioden Electoral periods (Wahlperioden)
bundestag://drucksachetypen Document types (Gesetzentwurf, Antrag, etc.)
bundestag://factions Parliamentary factions with official names, aliases, colors, and positions

Resource Templates

URI Pattern Description
bundestag://drucksache/{id} Fetch document by ID
bundestag://drucksache/{id}/text Fetch document full text
bundestag://plenarprotokoll/{id} Fetch protocol by ID
bundestag://plenarprotokoll/{id}/text Fetch protocol full text
bundestag://vorgang/{id} Fetch proceeding by ID
bundestag://person/{id} Fetch person by ID
bundestag://aktivitaet/{id} Fetch activity by ID

Client Configuration

Tip: Use the public instance https://bundestagapi.moritz-waechter.de/mcp or run your own with http://localhost:3000/mcp

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "bundestag": {
      "url": "https://bundestagapi.moritz-waechter.de/mcp"
    }
  }
}

Cursor

Add to .cursor/mcp.json:

{
  "mcpServers": {
    "bundestag": {
      "url": "https://bundestagapi.moritz-waechter.de/mcp"
    }
  }
}

VS Code (GitHub Copilot)

Add to settings:

{
  "mcp.servers": {
    "bundestag": {
      "type": "http",
      "url": "https://bundestagapi.moritz-waechter.de/mcp"
    }
  }
}

ChatGPT

The server is fully compatible with ChatGPT as a connector. Use the public instance or deploy your own.

  1. Enable developer mode in ChatGPT:

    • Go to Settings → Apps & Connectors → Advanced settings
    • Enable developer mode
  2. Add the connector:

    • Go to Settings → Connectors → Create
    • Use URL: https://bundestagapi.moritz-waechter.de/mcp
    • Name it "Bundestag" and provide a description
  3. Use in chat:

    • Click the + button in a new chat
    • Select your connector from the More menu
    • Ask about German parliamentary documents!

API Endpoints

Endpoint Description
POST /mcp MCP protocol endpoint
GET /mcp SSE stream for sessions
DELETE /mcp Close session
GET /health Basic health check
GET /health/deep Deep health check (verifies DIP API)
GET /metrics JSON statistics
GET /metrics/prometheus Prometheus format metrics
GET /.well-known/mcp.json Auto-discovery
GET /config/:client Client-specific config
GET /info Server information

Docker

# Build
docker build -t bundestag-mcp .

# Run
docker run -p 3000:3000 \
  -e DIP_API_KEY=your-api-key \
  bundestag-mcp

Docker Compose

version: '3.8'
services:
  bundestag-mcp:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DIP_API_KEY=${DIP_API_KEY}
      - LOG_LEVEL=INFO
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

Development

Running Tests

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

Project Structure

src/
├── index.js              # Express server, MCP setup, endpoints
├── config.js             # Environment configuration
├── api/
│   └── bundestag.js      # DIP API client with retry logic
├── jobs/
│   └── indexer.js        # Background document/protocol indexer
├── services/
│   ├── analysisService.js    # HTTP client for Python NLP service
│   ├── embeddingService.js   # Mistral embeddings
│   ├── qdrantService.js      # Vector database operations
│   ├── protokollParser.js    # Protocol speech extraction
│   └── drucksacheParser.js   # Document section parsing
├── tools/
│   ├── search.js         # 15 search/entity tools (incl. estimate_size)
│   ├── analysis.js       # 7 NLP analysis tools
│   ├── semanticSearch.js # 10 semantic search tools
│   └── clientConfig.js   # Client configuration tool
├── prompts/
│   └── index.js          # MCP Prompts
├── resources/
│   ├── info.js           # Static resources
│   └── templates.js      # Resource templates
└── utils/
    ├── cache.js          # Three-layer caching
    ├── logger.js         # Structured logging
    ├── retry.js          # Exponential backoff
    ├── rateLimiter.js    # Token bucket rate limiter
    ├── circuitBreaker.js # Circuit breaker pattern
    ├── metrics.js        # Prometheus metrics
    └── textNormalization.js # German text handling

Architecture

Resilience Patterns

Request → Rate Limiter → Circuit Breaker → Retry Logic → DIP API
              ↓               ↓                ↓
         (throttle)      (fast-fail)      (backoff)
  • Rate Limiter: Token bucket algorithm prevents overwhelming the DIP API
  • Circuit Breaker: Opens after consecutive failures, fast-fails during outages
  • Retry Logic: Exponential backoff with jitter for transient failures

Caching Strategy

Layer TTL Max Entries Use Case
API Response 5 min 500 Search results
Entity 15 min 200 Individual documents
Metadata 24 hr 50 Wahlperioden, document types

Semantic Search

The server supports AI-powered semantic search using Qdrant vector database and Mistral embeddings. This enables finding conceptually related documents even when exact keywords don't match.

How It Works

  1. Document Indexing: Background indexer fetches documents from DIP API and generates embeddings using Mistral AI
  2. Vector Storage: Embeddings are stored in Qdrant with rich metadata for filtering
  3. Semantic Query: User queries are embedded and matched against document vectors using cosine similarity

Three Search Collections

Collection Description
bundestag-docs Document-level search (Drucksachen, Vorgaenge, Aktivitaeten, Personen)
bundestag-protocol-chunks Speech-level search from Plenarprotokolle
bundestag-document-chunks Section-level search from Drucksachen (articles, questions, etc.)

Features

  • Multilingual: Search in English, finds German documents (e.g., "renewable energy" → "Erneuerbare Energien")
  • Hybrid Search: Combines vector similarity with keyword boosting for improved precision
  • Rich Filtering: Filter by document type, entity type, Wahlperiode, Sachgebiet, initiative, faction, date range
  • Speech Search: Find specific statements by speaker, party, speech type, or government officials
  • Document Section Search: Find specific paragraphs, questions, or articles within documents
  • Incremental Indexing: Uses f.aktualisiert.start for efficient updates after initial indexing

Configuration

Add to your .env file:

# Semantic Search (Qdrant + Mistral)
QDRANT_ENABLED=true
QDRANT_URL=http://qdrant:6333
QDRANT_API_KEY=your-qdrant-api-key      # Optional: API key for Qdrant authentication
MISTRAL_API_KEY=your-mistral-api-key

# Background Indexer
INDEXER_ENABLED=true
INDEXER_INTERVAL_MINUTES=15
INDEXER_WAHLPERIODEN=19,20

Tip: Generate a secure API key with openssl rand -hex 32

Docker Compose with Qdrant

services:
  bundestag-mcp:
    build: .
    environment:
      - QDRANT_ENABLED=true
      - QDRANT_URL=http://qdrant:6333
      - QDRANT_API_KEY=${QDRANT_API_KEY}
      - MISTRAL_API_KEY=${MISTRAL_API_KEY}
      - INDEXER_ENABLED=true
    depends_on:
      - qdrant

  qdrant:
    image: qdrant/qdrant:latest
    ports:
      - "6333:6333"
    volumes:
      - qdrant_data:/qdrant/storage
    environment:
      - QDRANT__SERVICE__API_KEY=${QDRANT_API_KEY}

volumes:
  qdrant_data:

Semantic Search Parameters

Parameter Description
query Natural language search query
limit Max results (1-50)
docTypes Filter: drucksache, vorgang, aktivitaet, person
entityTypes Filter: Gesetzentwurf, Kleine Anfrage, Rede, etc.
wahlperiode Electoral period (19, 20)
sachgebiet Subject area
initiative Initiating faction (CDU/CSU, SPD, etc.)
fraktion Parliamentary group
dateFrom / dateTo Date range (YYYY-MM-DD)
scoreThreshold Minimum similarity (0-1, default 0.3)

Speech Search Parameters

Parameter Description
query Natural language search query
limit Max results (1-50)
speaker Filter by speaker name (e.g., "Friedrich Merz")
speakerParty Filter by party (e.g., "CDU/CSU", "SPD")
speakerState Filter by state for Bundesrat (e.g., "Bayern")
top Filter by agenda item (e.g., "TOP 1")
wahlperiode Electoral period
herausgeber Publisher: BT (Bundestag) or BR (Bundesrat)
speechType Type: rede, befragung, fragestunde_antwort, kurzbeitrag
isGovernment Filter for government officials (ministers, state secretaries)
category Category: rede (formal speeches) or wortbeitrag (contributions)
searchMode semantic (pure vector) or hybrid (vector + keyword boosting)
keywordBoost Boost factor for keyword matches in hybrid mode (0-2, default 0.5)
requiredKeywords Keywords that must appear in the text
excludeKeywords Keywords that must not appear in the text

Document Section Search Parameters

Parameter Description
query Natural language search query
limit Max results (1-50)
drucksachetyp Filter: Gesetzentwurf, Kleine Anfrage, Antrag, etc.
chunkType Section type: problem, loesung, artikel, question, etc.
wahlperiode Electoral period
urheber Author/initiator (e.g., "Bundesregierung", "CDU/CSU")
dateFrom / dateTo Date range (YYYY-MM-DD)
scoreThreshold Minimum similarity (0-1, default 0.3)

NLP Analysis Service

The server includes optional NLP analysis capabilities powered by a Python FastAPI service using spaCy's German language model.

Features

  • Speech Extraction: Parse Plenarprotokolle into individual speeches with speaker, party, and type
  • Word Analysis: Extract and lemmatize nouns, adjectives, and verbs with frequency counts
  • Tone Analysis: 12 communication style metrics including aggression, collaboration, and solution-focus
  • Topic Classification: Detect focus on 13 policy areas (migration, climate, economy, etc.)
  • Speaker Profiles: Generate comprehensive profiles with statistics, vocabulary, and communication style
  • Party Comparison: Compare parties based on their speeches with tone rankings and topic focus

Tone Metrics

Metric Description
affirmative Positive vs critical adjective ratio (0-100)
aggression Aggressive language intensity (0-100)
labeling "Othering" language usage (0-100)
solution_focus Solution vs problem-oriented verbs (0-100)
collaboration Collaborative vs confrontational (0-100)
demand_intensity Demanding language (fordern, müssen) (0-100)
authority Obligation vs possibility modals (0-100)
future_orientation Forward vs backward-looking (0-100)

Topic Categories

Migration, Climate (Klima), Economy (Wirtschaft), Social Policy (Soziales), Security (Sicherheit), Health (Gesundheit), Europe (Europa), Digital, Education (Bildung), Finance (Finanzen), Justice (Justiz), Labor (Arbeit), Mobility (Mobilität)

Configuration

The analysis service runs as a separate Python container. Add to your .env:

ANALYSIS_SERVICE_URL=http://analysis:8000

Docker Compose with Analysis

services:
  bundestag-mcp:
    build: .
    environment:
      - ANALYSIS_SERVICE_URL=http://analysis:8000
    depends_on:
      - analysis

  analysis:
    image: ghcr.io/movm/bundestag-analysis:latest
    expose:
      - "8000"

Note: The analysis service requires ~1GB RAM for the spaCy model and takes ~30s to start.

DIP API

This server uses the official Bundestag DIP API:

  • Documentation: https://dip.bundestag.de/
  • API Docs: https://dip.bundestag.api.bund.dev/
  • GitHub: https://github.com/bundesAPI/dip-bundestag-api

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Run tests (npm test)
  4. Commit your changes (git commit -m 'feat: Add amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选