io.github.cyanheads/sweden-parliament-mcp-server
Search Swedish parliamentary documents, speeches, votes, members, and statutes.
What can you do with io.github.cyanheads/sweden-parliament-mcp-server?
- Keyless access to official document, speech, vote, and member endpoints, plus dated official reference tables
- Document text as canonical Markdown or SFS source text, with separately selectable original HTML
- Shared upstream concurrency, bounded public-response caching, and one 55-second deadline across queueing, retries, and text hydration
- Historical coverage varies by record type; speeches and votes start in 1993/94, with gaps in older vote data
- Source attribution, retrieval time, effective filters, and source warnings on both
content[]andstructuredContent - Complete continuation calls for rows, sections, and text, with revision checks on local continuations; a changing remote document search is not a frozen snapshot
- Explicit misses, unavailable text, unknown counts, and source service classifications; candidate saturation fails as
candidate_limit_reachedinstead of returning an incomplete traversal
Install
Add this to your client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: .cursor/mcp.json; VS Code and others use the same "mcpServers" shape).
claude mcp add --transport http sweden-parliament-mcp-server 'https://sweden-parliament.caseyjhand.com/mcp'
{
"mcpServers": {
"sweden-parliament-mcp-server": {
"type": "http",
"url": "https://sweden-parliament.caseyjhand.com/mcp"
}
}
}
@cyanheads/sweden-parliament-mcp-serverclaude mcp add sweden-parliament-mcp-server -e 'MCP_LOG_LEVEL=info' -- npx -y @cyanheads/sweden-parliament-mcp-server@0.1.2
{
"mcpServers": {
"sweden-parliament-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/sweden-parliament-mcp-server@0.1.2"
],
"env": {
"MCP_LOG_LEVEL": "info"
}
}
}
}
Environment variables
MCP_LOG_LEVELSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
@cyanheads/sweden-parliament-mcp-serverclaude mcp add sweden-parliament-mcp-server -e 'MCP_TRANSPORT_TYPE=<MCP_TRANSPORT_TYPE>' -e 'MCP_HTTP_HOST=127.0.0.1' -e 'MCP_HTTP_PORT=3010' -e 'MCP_HTTP_ENDPOINT_PATH=/mcp' -e 'MCP_AUTH_MODE=none' -e 'MCP_LOG_LEVEL=info' -- npx -y @cyanheads/sweden-parliament-mcp-server@0.1.2
{
"mcpServers": {
"sweden-parliament-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/sweden-parliament-mcp-server@0.1.2"
],
"env": {
"MCP_TRANSPORT_TYPE": "<MCP_TRANSPORT_TYPE>",
"MCP_HTTP_HOST": "127.0.0.1",
"MCP_HTTP_PORT": "3010",
"MCP_HTTP_ENDPOINT_PATH": "/mcp",
"MCP_AUTH_MODE": "none",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Environment variables
MCP_TRANSPORT_TYPESelects the HTTP transport.MCP_HTTP_HOSTThe hostname for the HTTP server.MCP_HTTP_PORTThe port to run the HTTP server on.MCP_HTTP_ENDPOINT_PATHThe endpoint path for the MCP server.MCP_AUTH_MODEAuthentication mode to use: 'none', 'jwt', or 'oauth'.MCP_LOG_LEVELSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
Documentation
From the project's README on GitHub, refreshed weekly. Links open on GitHub.
Contents
@cyanheads/sweden-parliament-mcp-server
Search Swedish parliamentary documents, speeches, votes, members, and statutes via MCP. STDIO or Streamable HTTP.
7 Tools • 0 Resources • 0 Prompts
Overview
Swedish parliamentary records from Riksdagen Open Data. Find proposals and committee reports, follow published decisions and main votes, read speeches, explore member assignments, and retrieve consolidated SFS statutes. Runs as a stdio process or a local Streamable HTTP server; no API key required.
Source: The Swedish Parliament. This independent service is not operated or endorsed by Sveriges riksdag. Swedish titles, labels, decisions, and text retain their source wording; English labels appear only where the source supplies them.
Tools
| Tool | Description |
|---|---|
riksdag_list_reference | Browse official document types, committees, parties, constituencies, sessions, and identifier and coverage guidance |
riksdag_search_documents | Search parliamentary documents and consolidated SFS statutes by words, type, session, committee, party, or dates |
riksdag_get_document | Read publication metadata, decisions, reservations, activities, links, and paginated text |
riksdag_search_speeches | Find speeches within a session by debate heading, member, or party; retrieve full text through get mode |
riksdag_get_votes | Read report decisions with party main-vote totals or one member's session main votes |
riksdag_search_members | Find register entries by name, party, constituency, and source service classification |
riksdag_get_member | Read an exact member IID and its published assignment history |
Capability reference
riksdag_list_reference tool
topic:document_types,committees,parties,constituencies,speech_types,sessions,identifiers, orcoverage- Dated offline snapshot with Swedish labels, available source English labels, source links, and
referenceVerifiedAt; document subtypes remain separate from parent codes, and the session catalog can lag current sessions offsetpagination;limitdefaults to 20 and is clamped to 100, withtotalCountand completenextCallarguments
riksdag_search_documents tool
- Optional
query,documentType,session,committee,party,dateFrom, anddateTo; dates useYYYY-MM-DD, and codes or exact reference labels are accepted - Remote
pagestarts at 1;pageSizedefaults to 10 and is clamped to 50. Every fetched row is returned, with source ordering, availabletotalCount, andnextCall - Use
documentType: "sfs"for consolidated statutes; narrow slow full-text searches withsessionordocumentType
riksdag_get_document tool
- Required
documentIdfrom search, or an unambiguous SFS identifier such as1974:152; missing records returnfound: false - Omit
sectionsfor metadata, the complete outline, and the first text page; selectmetadata,decisions,reservations,activities,properties,attachments,references,text, orsource_html - Text and HTML use Unicode code-point offsets (
textOffset/htmlOffset); lengths default to 1,000 and explicittextLength/htmlLengthvalues are honored. Array sections usesectionOffset/sectionLimit(default 20, maximum applied 100) - Follow
nextTextCall,nextHtmlCall, or eachsectionPages[].nextCall, retainingrevision; changed records fail withrevision_changed. Attachments are links, not downloaded files - SFS
versionKind: "consolidated"describes published consolidated text, which may include future-effective provisions; it is not an as-enacted or point-in-time legal version
riksdag_search_speeches tool
mode: "search"(default) requiressession; optionalmemberId,party, andspeechType: "all" | "speech"narrow the selection, withspeechexcluding repliesheadingContainsmatches all tokens against headings and subheadings, ignoring case and diacritics; it never searches speech body text- Local
offsetpagination;limitdefaults to 5 and is clamped to 20.textCountdefaults to 1, is clamped to 5, and accepts 0 for metadata only mode: "get"requires a retrievalspeechIdcopied from search, notsourceSpeechId; get mode rejects search filters.textOffsetand optionaltextLengthread the whole published body throughnextTextCall; the default text page is 1,000 code pointstextStateisincluded,not_requested,unavailable, orfailed; transient hydration failures include recovery details. Retainrevisionon search or text continuations
riksdag_get_votes tool
- Required
modeandsession;mode: "report"takesreport(designation or session:designation) or a reportdocumentId, whilemode: "member"requiresmemberIdand permitsparty - Report mode returns authoritative decisions and complete party groups. Select one
point, or usepointOffset/pointLimit(default 5, maximum applied 10); member mode usesoffset/limit(default 20, maximum applied 500) - Published main votes only, not every ballot round.
rollCallStateisavailable,acclamation,not_published, orunknown; acclamation requires explicit decision evidence, never merely empty vote rows - Missing aggregate counts remain unknown; additional source vote labels stay in
otherVotes. FollownextCallwithrevisionfor remaining whole points or member rows
riksdag_search_members tool
- Optional
nameContainsmatches all tokens ignoring case and diacritics;partyandconstituencyaccept codes or exact reference labels sitting: "all" | "serving" | "not_serving"defaults toall; this filters source service classification, not verified sitting or elected membership. Historical entries and ministers can appear, and unknown classifications remain inall- Local
offsetpagination;limitdefaults to 20 and is clamped to 100. ReturnscandidateCount, exact filteredtotalCount,revision, andnextCall - Keep leading zeros in
memberId. Some European Parliament entries have no IID and returndetailAvailable: false; theirsourceRecordIdis a different identifier and cannot be used withriksdag_get_member
riksdag_get_member tool
- Required numeric-string
memberIdfrom search, including leading zeros; missing entries returnfound: falsewith guidance - Published register metadata and assignments in source order;
assignmentOffset/assignmentLimitdefault to 0 / 20, with a maximum applied limit of 100 assignmentTotal,nextCall, andrevisionallow complete traversal. Assignment dates retain source precision and do not establish historical sitting status; contact details and photographs are excluded
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Riksdag-specific:
- Keyless access to official document, speech, vote, and member endpoints, plus dated official reference tables
- Document text as canonical Markdown or SFS source text, with separately selectable original HTML
- Shared upstream concurrency, bounded public-response caching, and one 55-second deadline across queueing, retries, and text hydration
- Historical coverage varies by record type; speeches and votes start in 1993/94, with gaps in older vote data
Agent-friendly output:
- Source attribution, retrieval time, effective filters, and source warnings on both
content[]andstructuredContent - Complete continuation calls for rows, sections, and text, with revision checks on local continuations; a changing remote document search is not a frozen snapshot
- Explicit misses, unavailable text, unknown counts, and source service classifications; candidate saturation fails as
candidate_limit_reachedinstead of returning an incomplete traversal
Getting started
Add the following to your MCP client configuration file.
{
"mcpServers": {
"sweden-parliament-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/sweden-parliament-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"sweden-parliament-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/sweden-parliament-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"sweden-parliament-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/sweden-parliament-mcp-server:latest"]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- Riksdagen Open Data requires no API key or account.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/sweden-parliament-mcp-server.git
- Navigate into the directory:
cd sweden-parliament-mcp-server
- Install dependencies:
bun install
- Configure environment:
cp .env.example .env
# edit .env for optional transport, authentication, or logging overrides
Configuration
| Variable | Description | Default |
|---|---|---|
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto. | stateless |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.). | info |
LOGS_DIR | Directory for log files (Node.js only). | <app-root>/logs |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for every server setting and the common framework overrides.
Running the server
Local development
- Build and run the production version:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdio - Run checks and tests:
bun run devcheck # Lints, formats, type-checks, and more bun run test # Runs the test suite
Project structure
| Directory | Purpose |
|---|---|
src/index.ts | Registers seven tools, initializes the service, and selects stateless HTTP sessions. |
src/mcp-server/tools/definitions | Seven read-only tool definitions; no resources or prompts. |
src/services/riksdag | Riksdagen endpoint parsing, reference tables, transport, cache, text conversion, and continuation. |
tests/ | Unit and integration tests, mirroring the src/ structure. |
See docs/tree.md for the full file tree.
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor logging,ctx.statefor storage - Register new tools and resources in the
createApp()arrays insrc/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
Apache-2.0 — see LICENSE for details.
Frequently asked questions
What is io.github.cyanheads/sweden-parliament-mcp-server?
Search Swedish parliamentary documents, speeches, votes, members, and statutes.
How do I install io.github.cyanheads/sweden-parliament-mcp-server?
It runs as a remote server. In Claude Code: claude mcp add --transport http sweden-parliament-mcp-server 'https://sweden-parliament.caseyjhand.com/mcp'. For other clients, paste the JSON configuration from this page into their MCP settings.
Does io.github.cyanheads/sweden-parliament-mcp-server need an API key?
Its registry entry lists no required key or secret. Some features may still need an account with the service it connects to.
Is io.github.cyanheads/sweden-parliament-mcp-server open source?
Yes. Its code is on GitHub under the Apache-2.0 license.
Who maintains io.github.cyanheads/sweden-parliament-mcp-server?
It is published by cyanheads. AI.tn lists it but does not maintain or endorse it.
From the official MCP Registry. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.