# Riksdag Regering MCP

> Riksdag-Regering MCP server with 32 specialized tools for Swedish political data (Parliament, Government, MPs, votes, documents)

- Skill: `hack23/riksdag-regering-mcp` (Agent Skill)
- Install (CLI): `npx skillmds@latest add hack23/riksdag-regering-mcp`
- Raw SKILL.md: https://api.skillmd.com/api/skills/hack23/riksdag-regering-mcp/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: Apache-2.0
- Author: Hack23 (https://skillmd.com/u/hack23)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/hack23/riksdag-regering-mcp

---


# Riksdag-Regering MCP Server


## 🔴 AI FIRST Quality Principle

> **Apply the AI FIRST principle: never accept first-pass quality. Minimum 2 iterations. Read all output, improve every section. No shortcuts.**

## 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
7. **Quantitative Context Handoff**: Pair parliamentary evidence with SCB/Riksbank helper outputs when domestic economic transmission matters; keep IMF as cross-country macro canon and SCB/Riksbank as Swedish ground truth.

## 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
- **Economic Transmission Analysis**: Combine Riksdag measures with `scripts/scb-fetch.ts` KPI/AKU/HEK/fuel presets and `scripts/riksbank-fetch.ts` policy-rate/minutes context for Swedish-specific impact estimates.

## Calling MCP Tools in Agentic Workflows

In gh-aw agentic workflows, MCP tools are called **directly by name** without any prefix. The MCP gateway routes to the correct server automatically:

```javascript
// Direct tool calls in agentic workflows (no prefix needed):
get_sync_status({})                                       // Health check — ALWAYS call first
get_propositioner({ rm: "2025/26", limit: 20 })           // Government propositions
get_betankanden({ rm: "2025/26", limit: 20 })             // Committee reports
search_dokument({ doktyp: "prop", rm: "2025/26" })        // Search documents
search_voteringar({ rm: "2025/26", parti: "S" })          // Search votes
get_calendar_events({ from: "2026-04-01", tom: "2026-04-30" }) // Calendar events
```

> **⚠️ Tool names use underscores** (e.g., `get_sync_status`, NOT `get-sync-status`).
> The gateway at `http://host.docker.internal:$MCP_GATEWAY_PORT/mcp/riksdag-regering` (port `8080` for gh-aw v0.69+, port `80` for legacy gh-aw <0.69 — resolved dynamically by `mcp-setup.sh`) handles routing.
> See [`.github/prompts/02-mcp-access.md`](../../prompts/02-mcp-access.md) for MCP server access, direct tool invocation, and tool-naming conventions (and the [`.github/prompts/README.md`](../../prompts/README.md) for the full module catalogue).

## Examples (TypeScript)

### Good Pattern: MP Voting Discipline Analysis
```javascript
// 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
```javascript
// 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
```javascript
// 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
```javascript
// 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
```javascript
// ❌ 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
```javascript
// ❌ 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**

```javascript
// === 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

```javascript
// === 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

```javascript
// ❌ 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
```javascript
// 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
```javascript
// 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**
```javascript
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**
```javascript
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**
```javascript
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)
```json
{
  "mcpServers": {
    "riksdag-regering": {
      "type": "http",
      "url": "https://riksdag-regering-ai.onrender.com/mcp",
      "tools": ["*"]
    }
  }
}
```

### Local Installation (Development)
```bash
# 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

- [riksdag-regering-mcp npm package](https://www.npmjs.com/package/riksdag-regering-mcp)
- [Swedish Riksdag Open Data](http://data.riksdagen.se/)
- [Swedish Government Publications](https://www.regeringen.se/)
- [G0V.se - Government Document Archive](https://g0v.se/)
- [Hack23 ISMS - GDPR Compliance](https://github.com/Hack23/ISMS-PUBLIC)

---

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


---

## 🔗 Integration with agentic workflows & analysis artifacts

This skill is consumed by the 11 agentic news workflows in `.github/workflows/news-*.md`. The authoritative contract lives in [`.github/prompts/README.md`](../../prompts/README.md); this skill supplies domain expertise on top of that contract.

- **Analysis product** → [`ai-driven-analysis-guide.md`](../../../analysis/methodologies/ai-driven-analysis-guide.md) + every template in [`analysis/templates/`](../../../analysis/templates/).
- **Required before any article**: 9 core artifacts (14 for Tier-C) in `analysis/daily/$ARTICLE_DATE/$SUBFOLDER/`; [`05-analysis-gate.md`](../../prompts/05-analysis-gate.md) is the single blocking gate.
- **gh-aw v0.69.3** docs: [abridged](https://github.github.com/gh-aw/llms-small.txt) · [complete](https://github.github.com/gh-aw/llms-full.txt) · [blog series](https://github.github.com/gh-aw/_llms-txt/agentic-workflows.txt).

