skills/hack23/riksdagsmonitor/riksdag-regering-mcp

riksdag-regering-mcp

SKILL.md

Riksdag-Regering MCP Server

Purpose

Provide comprehensive access to Swedish political data through the riksdag-regering-mcp Model Context Protocol (MCP) server. Enables intelligence operatives and political analysts to query, analyze, and visualize data from the Swedish Riksdag (Parliament) and Regeringen (Government).

Core Principles

  1. Authoritative Data Source: Official Swedish government data (data.riksdagen.se, regeringen.se)
  2. Comprehensive Coverage: 50+ years of historical data (1971-2024)
  3. Structured API: 32 specialized tools for different data types
  4. Real-Time Access: Latest parliamentary and government activities
  5. GDPR Compliance: Public interest basis (Article 6(1)(e)), no personal data beyond official capacity
  6. Multi-Source Integration: Riksdag documents + Government publications

Available Tools (32 Total)

🔍 Search & Discovery (6 tools)

  • search_ledamoter: Search for MPs (349 members) by name, party, constituency
  • search_dokument: Search parliamentary documents (motions, bills, reports)
  • search_dokument_fulltext: Full-text search across document content
  • search_anforanden: Search speeches and parliamentary debates
  • search_voteringar: Search voting records and roll calls
  • search_regering: Search government documents (propositions, SOU, Dir)

📊 Detailed Information (6 tools)

  • get_dokument: Get complete document with metadata and content
  • get_ledamot: Get MP profile with assignments, activities, bio
  • get_dokument_innehall: Get document content and summary
  • get_g0v_document_content: Get government document in Markdown
  • get_discussion: Get specific discussion thread
  • get_discussion_comments: Get comments from a discussion

📝 Parliamentary Documents (6 tools)

  • get_motioner: Latest motions (proposals from MPs)
  • get_propositioner: Latest government propositions
  • get_betankanden: Latest committee reports
  • get_fragor: Latest written questions
  • get_interpellationer: Latest interpellations (formal questions)
  • get_utskott: List parliamentary committees (15 committees)

🏛️ Government Documents (4 tools)

  • get_regering_document: Get government document by ID
  • summarize_regering_document: AI-powered government document summary
  • get_g0v_document_types: List available government document types
  • get_g0v_category_codes: List government policy area codes

📈 Analytics & Aggregation (5 tools)

  • get_voting_group: Get votes grouped by party/constituency
  • list_reports: List available statistical reports
  • fetch_report: Get statistical report (MP stats, committee data)
  • analyze_g0v_by_department: Analyze government documents by department
  • get_g0v_latest_update: Check latest government data update

🔄 Advanced Queries (5 tools)

  • fetch_paginated_documents: Batch fetch with pagination
  • fetch_paginated_anforanden: Batch fetch speeches
  • batch_fetch_documents: Multi-year document batches
  • get_calendar_events: Parliamentary calendar (debates, committees)
  • enhanced_government_search: Combined Riksdag + Government search

Data Coverage

Swedish Riksdag (Parliament)

  • 349 MPs: Current members across 8 parties
  • 15 Committees: AU, FiU, JuU, KU, SkU, SfU, UU, UtU, etc.
  • Documents: 50+ years (1971-2024)
    • Motions (mot): MP proposals
    • Propositions (prop): Government bills
    • Reports (bet): Committee reports
    • Questions (fr): Written questions
    • Interpellations (ip): Formal questions
  • Votes: Complete voting records with party/MP breakdown
  • Speeches: Parliamentary debates (anföranden)

Swedish Government (Regeringen)

  • Document Types: Propositions, SOU (state investigations), Dir (committee directives), DS (department series), Remisser (referrals)
  • Departments: All 10 ministries
  • Historical Data: Government documents from 1990s+
  • G0V Integration: Markdown-formatted documents via g0v.se

8 Parliamentary Parties

  • S - Socialdemokraterna (Social Democrats)
  • M - Moderaterna (Moderates)
  • SD - Sverigedemokraterna (Sweden Democrats)
  • MP - Miljöpartiet (Green Party)
  • C - Centerpartiet (Centre Party)
  • V - Vänsterpartiet (Left Party)
  • KD - Kristdemokraterna (Christian Democrats)
  • L - Liberalerna (Liberals)

When to Use

  • Political Intelligence: Analyze voting patterns, coalition behavior
  • Legislative Monitoring: Track bills, motions, committee work
  • MP Analysis: Profile MPs, track activities, voting discipline
  • Coalition Analysis: Assess government stability, party cooperation
  • Policy Research: Trace policy development through documents
  • Voting Analysis: Party cohesion, rebels, cross-party voting
  • Government Oversight: Track government proposals, investigations
  • Electoral Research: Historical trends, party evolution
  • Transparency Dashboards: Real-time political metrics
  • Risk Assessment: Identify democratic accountability gaps

Examples

Good Pattern: MP Voting Discipline Analysis

// Get all votes from current riksmöte
const votes = await riksdag_regering_mcp.search_voteringar({
  rm: "2024/25",
  limit: 200
});

// Analyze party cohesion
const partyDiscipline = {};
for (const party of ['S', 'M', 'SD', 'C', 'V', 'KD', 'L', 'MP']) {
  const partyVotes = await riksdag_regering_mcp.get_voting_group({
    rm: "2024/25",
    groupBy: "parti",
    limit: 200
  });
  
  // Calculate cohesion metric
  partyDiscipline[party] = calculateCohesion(partyVotes);
}

Good Pattern: Committee Productivity Analysis

// Get reports from all committees
const committees = ['AU', 'FiU', 'JuU', 'KU', 'SkU', 'SfU', 'UU'];
const productivity = {};

for (const committee of committees) {
  const reports = await riksdag_regering_mcp.get_betankanden({
    organ: committee,
    rm: "2024/25",
    limit: 100
  });
  
  productivity[committee] = {
    count: reports.length,
    avgProcessingTime: calculateAvgTime(reports)
  };
}

Good Pattern: Government Document Analysis

// Search government propositions on specific topic
const props = await riksdag_regering_mcp.search_regering({
  type: "propositioner",
  title: "migration",
  dateFrom: "2024-01-01",
  limit: 50
});

// Get full content for analysis
for (const prop of props) {
  const content = await riksdag_regering_mcp.get_g0v_document_content({
    regeringenUrl: prop.url
  });
  
  // Analyze policy positions
  analyzePolicy(content);
}

Good Pattern: Multi-Language Political Dashboard

// Get latest parliamentary activity
const motions = await riksdag_regering_mcp.get_motioner({ limit: 10 });
const props = await riksdag_regering_mcp.get_propositioner({ limit: 10 });
const questions = await riksdag_regering_mcp.get_fragor({ limit: 10 });

// Create bilingual dashboard (Swedish/English)
const dashboard = {
  sv: formatDashboardSV({ motions, props, questions }),
  en: formatDashboardEN({ motions, props, questions })
};

Anti-Pattern: Over-Fetching Without Filtering

// ❌ BAD: Fetching too much data
const allDocs = await riksdag_regering_mcp.search_dokument({
  limit: 200 // Default, could be thousands
});

// ✅ GOOD: Targeted query with filters
const recentDocs = await riksdag_regering_mcp.search_dokument({
  rm: "2024/25",
  doktyp: "mot",
  organ: "FiU",
  limit: 50
});

Anti-Pattern: Ignoring Pagination

// ❌ BAD: Only getting first page
const votes = await riksdag_regering_mcp.search_voteringar({ limit: 20 });

// ✅ GOOD: Handling pagination
const allVotes = await riksdag_regering_mcp.fetch_paginated_documents({
  doktyp: "votering",
  rm: "2024/25",
  fetchAll: true,
  maxPages: 10
});

🔥 MCP Query Best Practices

⚡ CRITICAL: Always Check Data Freshness First

RULE #1: Call get_sync_status() before any data queries

// === DATA FRESHNESS CHECK ===
// ALWAYS call this FIRST - validates freshness and warms up server
const syncStatus = get_sync_status({});
console.log("Last data sync:", syncStatus.last_updated);

// Calculate hours since last sync
const lastSync = new Date(syncStatus.last_updated);
const hoursSinceSync = (Date.now() - lastSync.getTime()) / 3600000;

// Warn if data is stale (>48 hours)
if (hoursSinceSync > 48) {
  console.warn(`⚠️ DATA MAY BE STALE: ${hoursSinceSync.toFixed(1)} hours since last sync`);
  // Include disclaimer in analysis/articles
}

Why this matters:

  1. Data Quality: Ensures analysis uses recent data, not stale information
  2. Server Warmup: Warms up MCP server (avoids 30-60s cold start on first query)
  3. User Transparency: Readers/stakeholders know when data was last updated
  4. Quality Control: Prevents publishing analysis with outdated information

📅 Date Parameter Support Matrix

Only 3 of 32 tools support explicit date parameters:

Tool Date Parameters Example
get_calendar_events from, tom { from: "2026-02-17", tom: "2026-02-23" }
search_regering from_date, to_date { from_date: "2026-02-01", to_date: "2026-02-17" }
analyze_g0v_by_department dateFrom, dateTo { dateFrom: "2026-02-01", dateTo: "2026-02-17" }

All other 29 tools require post-query date filtering by:

  • datum - votes, speeches (voting/speech date)
  • publicerad - committee reports, propositions (publication date)
  • inlämnad - motions, questions, interpellations (submission date)

✅ Good Pattern: Explicit Date Filtering

// === STEP 1: Check data freshness ===
const syncStatus = get_sync_status({});

// === STEP 2: Query with explicit dates (where supported) ===
const govDocs = search_regering({
  from_date: "2026-02-01",
  to_date: "2026-02-17",
  limit: 50
});

// === STEP 3: Filter by date for tools without date params ===
const betankanden = get_betankanden({ rm: "2025/26", limit: 100 });

// Filter results by publication date
const fromDate = new Date("2026-02-01");
const recentBetankanden = betankanden.filter(bet => 
  new Date(bet.publicerad) >= fromDate
);

console.log(`Found ${recentBetankanden.length} committee reports from ${fromDate.toISOString().split('T')[0]}`);

❌ Anti-Pattern: Implicit "Latest" Reliance

// ❌ BAD: Relies on implicit sorting without date awareness
const votes = search_voteringar({ rm: "2025/26", limit: 50 });
// Problem: No idea when votes occurred, might be months old

// ✅ GOOD: Explicit date filtering
const votes = search_voteringar({ rm: "2025/26", limit: 50 });
const recentVotes = votes.filter(v => 
  new Date(v.datum) >= new Date("2026-02-01")
);
console.log(`Found ${recentVotes.length} votes since 2026-02-01`);

🔗 Cross-Referencing Strategy

Combine multiple tools for richer analysis:

Pattern 1: Committee Report Deep Dive

// 1. Get recent committee reports
const betankanden = get_betankanden({ rm: "2025/26", limit: 20 });
const recentBet = betankanden.filter(b => 
  new Date(b.publicerad) >= new Date("2026-02-01")
);

// 2. Get full details for each report
const reportDetails = recentBet.map(bet => 
  get_dokument({ dok_id: bet.dok_id })
);

// 3. Find related votes
const votes = search_voteringar({ rm: "2025/26", limit: 100 });
const relatedVotes = votes.filter(v => 
  recentBet.some(bet => v.bet === bet.beteckning)
);

// 4. Get committee members' speeches
const speeches = search_anforanden({ rm: "2025/26", limit: 100 });
const committeeSpeeches = speeches.filter(a =>
  recentBet.some(bet => a.dokument_hangar_samman === bet.dok_id)
);

// Now you have: reports + details + votes + speeches

Pattern 2: Party Behavior Analysis

// 1. Get voting patterns by party
const voteGroups = get_voting_group({ rm: "2025/26", groupBy: "parti" });

// 2. Get recent votes
const votes = search_voteringar({ rm: "2025/26", limit: 200 });
const recentVotes = votes.filter(v => 
  new Date(v.datum) >= new Date("2026-02-01")
);

// 3. Get party motions
const motions = get_motioner({ rm: "2025/26", limit: 100 });
const partyMotions = motions.filter(m => 
  new Date(m.inlämnad) >= new Date("2026-02-01")
);

// 4. Calculate party cohesion
const partyDiscipline = calculateCohesion(voteGroups, recentVotes);

🐛 Troubleshooting Guide

Issue Cause Solution
Tool not found Wrong tool name Use exact names: get_calendar_events, search_voteringar
Empty results No data in timeframe Check get_sync_status(), widen date range, verify rm parameter
Stale data Last sync >48h ago Note in analysis with disclaimer, use available data
Timeout Cold start (30-60s) Wait - MCP framework retries automatically
Too broad results No date filtering Add date params OR filter by datum/publicerad/inlämnad
Swedish-only results Riksdag API returns Swedish Must translate to target languages
Missing documents Wrong riksmöte (rm) Verify rm parameter (e.g., "2025/26")

🚀 Performance Tips

  1. Batch Queries After Warmup: Call get_sync_status() first, then batch data queries
  2. Use Pagination Wisely: Use fetch_paginated_documents for large datasets
  3. Filter Early: Apply date filters as early as possible
  4. Cache Results: MCP server data updates daily, cache results when appropriate
  5. Parallel Queries: Independent queries can run in parallel after server warmup

📊 Query Pattern Templates

Template 1: Daily News Monitoring

const syncStatus = get_sync_status({});
const today = new Date().toISOString().split('T')[0];
const yesterday = new Date(Date.now() - 86400000).toISOString().split('T')[0];

// Government activity
const govDocs = search_regering({ 
  from_date: yesterday, 
  to_date: today, 
  limit: 50 
});

// Parliamentary calendar
const events = get_calendar_events({ 
  from: today, 
  tom: today, 
  limit: 50 
});

// Recent votes (filter by date)
const votes = search_voteringar({ rm: "2025/26", limit: 50 });
const todayVotes = votes.filter(v => v.datum === today);

Template 2: Weekly Analysis

const syncStatus = get_sync_status({});
const today = new Date();
const weekAgo = new Date(Date.now() - 7 * 86400000);

// Committee reports (filter by publicerad)
const reports = get_betankanden({ rm: "2025/26", limit: 100 });
const weeklyReports = reports.filter(r => 
  new Date(r.publicerad) >= weekAgo
);

// Propositions (filter by publicerad)
const props = get_propositioner({ rm: "2025/26", limit: 50 });
const weeklyProps = props.filter(p => 
  new Date(p.publicerad) >= weekAgo
);

// Questions (filter by inlämnad)
const questions = get_fragor({ rm: "2025/26", limit: 100 });
const weeklyQuestions = questions.filter(q => 
  new Date(q.inlämnad) >= weekAgo
);

Template 3: MP Activity Analysis

const syncStatus = get_sync_status({});

// Get MP profile
const mp = get_ledamot({ intressent_id: "XXXXXXXX" });

// Get MP's motions
const allMotions = get_motioner({ rm: "2025/26", limit: 200 });
const mpMotions = allMotions.filter(m => 
  m.intressent_id === mp.intressent_id
);

// Get MP's speeches
const speeches = search_anforanden({ 
  rm: "2025/26", 
  talare: mp.tilltalsnamn + " " + mp.efternamn,
  limit: 100
});

// Get MP's voting record
const votes = search_voteringar({ rm: "2025/26", limit: 200 });
// Requires cross-referencing with ledamöter data

MCP Server Configuration

HTTP Endpoint (Production)

{
  "mcpServers": {
    "riksdag-regering": {
      "type": "http",
      "url": "https://riksdag-regering-ai.onrender.com/mcp",
      "tools": ["*"]
    }
  }
}

Local Installation (Development)

# Install globally
npm install -g riksdag-regering-mcp

# Run locally
riksdag-regering-mcp
# Listens on http://localhost:3000/mcp

Data Quality Considerations

Completeness

  • Historical Data: Complete from 1971 for most document types
  • Real-Time Updates: Government data updated daily
  • Missing Data: Some older documents may lack full text

Accuracy

  • Official Source: Direct from Swedish government APIs
  • Validation: Schema validation for all responses
  • Versioning: API versioned for stability

Timeliness

  • Parliamentary Data: Updated within hours of publication
  • Government Data: Updated daily from regeringen.se
  • Latency: HTTP endpoint may have cold start delays (~30s)

GDPR Compliance

Legal Basis

  • Article 6(1)(e): Processing necessary for task carried out in public interest
  • Article 9(2)(g): Processing necessary for substantial public interest
  • Offentlighetsprincipen: Swedish Public Access to Information and Secrecy Act

Data Minimization

  • ✅ Only official capacity data (no private lives)
  • ✅ No personal contact information
  • ✅ No tracking or cookies
  • ✅ No data retention beyond cache

Transparency

  • ✅ Clear data sources documented
  • ✅ Open-source MCP server
  • ✅ Public API documentation
  • ✅ GDPR compliance statement

Remember

  • Use HTTP endpoint for production (no local installation needed)
  • Filter queries with riksmöte (rm), organ, party parameters
  • Handle pagination for large datasets (use fetchAll carefully)
  • Verify data quality - some older documents may be incomplete
  • Respect rate limits - HTTP endpoint may throttle heavy usage
  • Cache responses - avoid redundant API calls
  • GDPR compliance - only official capacity data, no personal information
  • Multi-language support - Display data in all 14 supported languages
  • Document IDs follow pattern: H901FiU1 (Riksmöte + Type + Committee + Number)

References


Version: 1.0
Last Updated: 2026-02-06
Maintained by: Hack23 AB

Weekly Installs
16
GitHub Stars
2
First Seen
11 days ago
Installed on
opencode16
claude-code16
github-copilot16
codex16
amp16
cline16