switzerland-parliament-mcp-server

v0.1.1 pre-1.0

Search Swiss parliamentary business, votes, debates, members, and declared interests via MCP. STDIO or Streamable HTTP.

switzerland-parliament.caseyjhand.com/mcp
claude mcp add --transport http switzerland-parliament-mcp-server https://switzerland-parliament.caseyjhand.com/mcp
codex mcp add switzerland-parliament-mcp-server --url https://switzerland-parliament.caseyjhand.com/mcp
{
  "mcpServers": {
    "switzerland-parliament-mcp-server": {
      "url": "https://switzerland-parliament.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http switzerland-parliament-mcp-server https://switzerland-parliament.caseyjhand.com/mcp
{
  "mcpServers": {
    "switzerland-parliament-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://switzerland-parliament.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "switzerland-parliament-mcp-server": {
      "type": "http",
      "url": "https://switzerland-parliament.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://switzerland-parliament.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

7

chparl_search_business

open-world

Search Swiss parliamentary business by title substring, published submitter label, type, current status, submission session, inclusive submission dates, or committee role. Use chparl_list_reference to resolve codes and chparl_get_business to read a returned businessId. Follow nextCursor with unchanged filters; newest canonical business IDs appear first. Committee searches page role candidates and may return short pages without a distinct business total. Metadata labels remain in de, fr, or it without translation fallback.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "chparl_search_business",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "language": {
      "description": "Metadata language: de (default), fr, or it.",
      "default": "de",
      "type": "string",
      "enum": [
        "de",
        "fr",
        "it"
      ]
    },
    "query": {
      "description": "One title substring, preserving punctuation and diacritics.",
      "type": "string"
    },
    "author": {
      "description": "Substring of the published submitter label, not every co-signatory.",
      "type": "string"
    },
    "typeId": {
      "description": "Business type code from chparl_list_reference topic business_types.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "statusId": {
      "description": "Current status code from chparl_list_reference topic statuses.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "sessionId": {
      "description": "Submission session ID from chparl_list_reference topic sessions.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "committeeId": {
      "description": "Committee number from chparl_list_reference topic committees; matches any published committee role.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "submittedFrom": {
      "description": "Inclusive submission-date lower bound, YYYY-MM-DD.",
      "type": "string",
      "format": "date",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
    },
    "submittedTo": {
      "description": "Inclusive submission-date upper bound, YYYY-MM-DD.",
      "type": "string",
      "format": "date",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
    },
    "limit": {
      "default": 20,
      "description": "Page request, default 20; clamped to 100. Committee pages count candidate roles, and byte fitting may return fewer businesses.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "cursor": {
      "description": "Opaque nextCursor from a previous call with identical filters; omit to start.",
      "type": "string"
    }
  },
  "required": [
    "language",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

chparl_get_business

open-world

Read a Swiss parliamentary business by canonical eight-digit businessId or exact published short number. Choose overview for metadata and available text sizes; texts for original published text, automatically outlined when several fields exceed the disclosure budget; or status_history, bills, related_business, preconsultations, or subjects for independently paged relationships. textFields selects complete original fields only in texts, even when large. Paging applies only to relationships. Use subjects to narrow chparl_search_transcripts; source text and HTML remain unchanged.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "chparl_get_business",
    "arguments": {
      "businessId": "<businessId>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "businessId": {
      "type": "string",
      "pattern": "^(?:[1-9]\\d{7}|\\d{2}\\.\\d{3,4})$",
      "description": "Canonical eight-digit businessId from chparl_search_business, or an exact published short number such as 99.1234."
    },
    "language": {
      "description": "Metadata and business-text variant: de (default), fr, or it.",
      "default": "de",
      "type": "string",
      "enum": [
        "de",
        "fr",
        "it"
      ]
    },
    "section": {
      "default": "overview",
      "description": "Readable section, default overview.",
      "type": "string",
      "enum": [
        "overview",
        "texts",
        "status_history",
        "bills",
        "related_business",
        "preconsultations",
        "subjects"
      ]
    },
    "textFields": {
      "description": "Texts only: named original fields; empty array means unset.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "description",
          "initialSituation",
          "proceedings",
          "draftText",
          "submittedText",
          "reasonText",
          "documentationText",
          "motionText",
          "federalCouncilResponseText",
          "federalCouncilProposalText"
        ],
        "description": "Original field to return complete."
      }
    },
    "limit": {
      "description": "Relationships only: requested page size, default 20, clamped to 100.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "description": "Relationships only: source row offset, default zero; continue with returned nextOffset.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "businessId",
    "language",
    "section"
  ],
  "additionalProperties": false
}
view source ↗

chparl_get_votes

open-world

Find Nationalrat roll calls with mode votes and businessId, then select a returned voteId with mode members for a paged roll call or mode groups for complete decision counts by parliamentary group. Member roll calls start in the 2003 winter session and exclude Ständerat member votes; an empty result does not prove no vote occurred. Member counts cover only the delivered page; groups mode reads all published member rows before reporting totals. DecisionText remains unchanged; documented code meanings include 1 yes, 2 no, 3 abstention, 6 excused under Art. 57 para. 4, and 7 president does not vote. Unknown codes and missing decisions are retained. Follow nextOffset with the same mode and filters.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "chparl_get_votes",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "votes",
      "description": "Workflow: votes (default), members, or complete groups.",
      "type": "string",
      "enum": [
        "votes",
        "members",
        "groups"
      ]
    },
    "businessId": {
      "description": "Votes only: canonical eight-digit businessId from chparl_search_business, or a published short number such as 99.1234.",
      "type": "string",
      "pattern": "^(?:[1-9]\\d{7}|\\d{2}\\.\\d{3,4})$"
    },
    "voteId": {
      "description": "Members or groups only: positive Int32 Vote.ID discovered through votes mode.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "personNumber": {
      "description": "Members only: exact PersonNumber from chparl_search_members, distinct from Person.ID or current group affiliation.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "language": {
      "description": "Metadata language: de (default), fr, or it; decision text remains as published.",
      "default": "de",
      "type": "string",
      "enum": [
        "de",
        "fr",
        "it"
      ]
    },
    "limit": {
      "description": "Paged modes only: votes default 10/max 50, members default 50/max 100; higher requests are clamped with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "description": "Paged modes only: starting row offset, default zero; continue using returned nextOffset.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "mode",
    "language"
  ],
  "additionalProperties": false
}
view source ↗

chparl_search_transcripts

open-world

Find Amtliches Bulletin passages by business, debate subject, speaker, session, council, or inclusive meeting dates. Supply at least a business, subject, speaker, session, or date bound. A text substring query additionally requires sessionId or a closed date range of at most 31 calendar days. Searches return metadata by default; includeText returns whole original passages, and an exact transcriptId defaults to full text. Metadata language never translates the speaker text; missing LanguageOfText remains unknown. Business searches cover every associated subject up to 20; larger debates require selecting subjectId through chparl_get_business section subjects. Follow nextOffset with unchanged filters.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "chparl_search_transcripts",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "language": {
      "description": "Metadata language: de (default), fr, or it; original passage text stays in its published language.",
      "default": "de",
      "type": "string",
      "enum": [
        "de",
        "fr",
        "it"
      ]
    },
    "businessId": {
      "description": "Canonical eight-digit businessId from chparl_search_business or published short number; incompatible with subjectId and transcriptId.",
      "type": "string",
      "pattern": "^(?:[1-9]\\d{7}|\\d{2}\\.\\d{3,4})$"
    },
    "subjectId": {
      "description": "Positive Int64 debate IdSubject string; incompatible with businessId and transcriptId.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "transcriptId": {
      "description": "Exact positive Int64 transcriptId from a previous chparl_search_transcripts result; only language and includeText may accompany it.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "personNumber": {
      "description": "Exact speaker PersonNumber from chparl_search_members, distinct from Person.ID.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "sessionId": {
      "description": "Exact positive decimal session identifier from chparl_list_reference topic sessions.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "council": {
      "description": "N or S; exact German, French, and Italian council names are also accepted.",
      "type": "string",
      "enum": [
        "N",
        "S"
      ]
    },
    "dateFrom": {
      "description": "Inclusive meeting-day lower bound, YYYY-MM-DD.",
      "type": "string",
      "format": "date",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
    },
    "dateTo": {
      "description": "Inclusive meeting-day upper bound, YYYY-MM-DD.",
      "type": "string",
      "format": "date",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
    },
    "query": {
      "description": "One original-text substring; requires sessionId or both dates spanning at most 31 inclusive calendar days.",
      "type": "string"
    },
    "includeText": {
      "description": "Return whole original text and references; defaults true for transcriptId and false for searches. Explicit false always wins.",
      "type": "boolean"
    },
    "limit": {
      "description": "Search page request: metadata default 20/max 100, full text default 3/max 10; clamped with notice. Incompatible with transcriptId.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "description": "Search starting row offset, default zero; use returned nextOffset. Incompatible with transcriptId.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "language"
  ],
  "additionalProperties": false
}
view source ↗

chparl_search_members

open-world

Find current or former Swiss Parliament affiliation records by name, council, canton, party, or parliamentary group. membership defaults to current; former selects inactive records and all omits the activity filter. query matches a substring of a published first, last, or official name. Use each record’s personNumber with chparl_get_member for identity, full council terms, committees, and declared interests. Follow nextOffset with the same filters.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "chparl_search_members",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "query": {
      "description": "Optional name substring, trimmed without changing internal punctuation or diacritics.",
      "type": "string"
    },
    "membership": {
      "default": "current",
      "description": "current (default), former, or all MemberCouncil records.",
      "type": "string",
      "enum": [
        "current",
        "former",
        "all"
      ]
    },
    "council": {
      "description": "N or S; exact German, French, and Italian council names are accepted. Resolve codes with chparl_list_reference topic councils.",
      "type": "string",
      "enum": [
        "N",
        "S"
      ]
    },
    "cantonId": {
      "description": "Optional Canton identifier from chparl_list_reference topic cantons.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "partyId": {
      "description": "Optional Party identifier from chparl_list_reference topic parties.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "groupId": {
      "description": "Optional ParlGroupNumber from chparl_list_reference topic groups.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "language": {
      "description": "Metadata language: de (default), fr, or it; uppercase is accepted.",
      "default": "de",
      "type": "string",
      "enum": [
        "de",
        "fr",
        "it"
      ]
    },
    "limit": {
      "default": 20,
      "description": "Requested page size, default 20, effective maximum 100 with notice. Whole records may be fitted to the response byte budget.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "default": 0,
      "description": "Starting MemberCouncil record offset; continue with returned nextOffset.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "membership",
    "language",
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

chparl_get_member

open-world

Read a Swiss Parliament member by PersonNumber, which need not equal Person.ID. overview returns identity and every base MemberCouncil affiliation without pagination. Select council_terms for historical council terms, committees for published MemberCommittee rows, or interests for declared interests; those sections accept limit and offset. Missing paid status means unknown, and empty interests do not establish absence of conflicts of interest. Metadata labels remain in the selected language.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "chparl_get_member",
    "arguments": {
      "personNumber": "<personNumber>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "personNumber": {
      "description": "Required positive Int32 PersonNumber as a decimal string; discover with chparl_search_members.",
      "type": "string",
      "pattern": "^[1-9]\\d*$"
    },
    "language": {
      "description": "Metadata language: de (default), fr, or it; uppercase is accepted.",
      "default": "de",
      "type": "string",
      "enum": [
        "de",
        "fr",
        "it"
      ]
    },
    "section": {
      "default": "overview",
      "description": "overview (default), council_terms, committees, or interests.",
      "type": "string",
      "enum": [
        "overview",
        "council_terms",
        "committees",
        "interests"
      ]
    },
    "limit": {
      "description": "Relationship sections only: default 20, effective maximum 100 with notice. Omit for overview.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "description": "Relationship sections only: default zero; continue with nextOffset. Omit for overview.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "personNumber",
    "language",
    "section"
  ],
  "additionalProperties": false
}
view source ↗

chparl_list_reference

open-world

List Swiss Parliament reference entries and source coverage. Choose identifiers, coverage, or languages for server explanations; statuses for the official legacy/current status snapshot; or business_types, councils, cantons, parties, groups, committees, or sessions for live dictionaries. Date filters apply only to sessions. Follow nextOffset with the same topic, language, and dates; labels remain in the requested metadata language and missing labels stay unknown.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "chparl_list_reference",
    "arguments": {
      "topic": "<topic>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "topic": {
      "type": "string",
      "enum": [
        "identifiers",
        "coverage",
        "languages",
        "business_types",
        "statuses",
        "councils",
        "cantons",
        "parties",
        "groups",
        "committees",
        "sessions"
      ],
      "description": "Reference dictionary or explanatory topic to list."
    },
    "language": {
      "description": "Metadata label language: de (default), fr, or it.",
      "default": "de",
      "type": "string",
      "enum": [
        "de",
        "fr",
        "it"
      ]
    },
    "dateFrom": {
      "description": "Sessions only: inclusive StartDate lower bound, YYYY-MM-DD.",
      "type": "string",
      "format": "date",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
    },
    "dateTo": {
      "description": "Sessions only: inclusive EndDate upper bound, YYYY-MM-DD.",
      "type": "string",
      "format": "date",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
    },
    "limit": {
      "default": 50,
      "description": "Requested page size, default 50; values above 100 are clamped with a notice. Whole-item byte fitting may return fewer entries.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "default": 0,
      "description": "Starting row offset, default zero. Use the returned nextOffset to continue.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "topic",
    "language",
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗