It covers not just the federal parliament but cantonal and municipal ones too. And while I was at it, I added an MCP server so any AI assistant can query parliamentary data directly.
Almost a year ago, I wrote about building a Swiss Parliament Bot with LangGraph. The bot answered questions about the federal parliament by constructing OData queries against the totally unofficial parlament.ch API. It worked, but the OData API had its quirks, was sometimes slow and totally unofficially used. I didn't work on it any further since then.
The migration was smooth. The LangGraph workflow itself didn't need to change at all. It's still the same boring four-step loop: generate API URLs, fetch data, evaluate whether the data is sufficient, and generate a response. If the evaluator says the data isn't enough, it loops back and tries different URLs. That architecture proved its worth here, because swapping out the underlying API was essentially a prompt and data-handling change, not a structural one. And that was the goal of this quick adjustment, not coming up with something totally new. Just use that new, more supported API.
What did change significantly was the prompt. The original prompt listed all OData entities with their fields and taught the LLM how to construct OData filter expressions. The new prompt does the same for OpenParlData's REST endpoints, with parameters like search, search_mode=partial, sort_by=-begin_date, and expand=memberships. The LLM had no trouble adapting. REST with query parameters is arguably more natural for it than OData's somewhat unusual syntax.
The biggest functional upgrade is the scope. The old bot only knew about the Nationalrat and Ständerat. Now it can answer questions about any parliament in the system. Ask "Welche Vorstösse gibt es zum Thema Künstliche Intelligenz?" and it searches across all parliaments. Ask about the "Finanzkommission des Nationalrats" and it narrows to body_key=CHE. Ask about the "Zürcher Kantonsrat" and it filters with body_key=ZH.
The bot is still a prototype and far from perfect. Not all cantonal parliaments have the same data coverage. Some queries work beautifully, others return empty results because the data simply isn't there yet. But the foundation is there, and as more parliaments feed data into OpenParlData, the bot will automatically benefit.
An MCP Server on Top
With the API migration done, I had a clean REST-based data layer sitting there. That made me think: why limit access to the chatbot? The Model Context Protocol (MCP) has been getting a lot of attention as a way for AI assistants to call external tools directly. And a well-structured REST API is pretty much the ideal thing to wrap in MCP tools.
So I built an MCP server that exposes the OpenParlData endpoints as tools that any MCP-compatible client can call ā Claude Desktop, Cursor, or anything else that speaks the protocol. Each API endpoint becomes a tool: persons, affairs, votings, memberships, and so on. The AI assistant can search for parliament members, look up voting records, or drill into affair details, all without going through the chatbot UI.
Of course the right place for that MCP would be directly at OpenParlData. I didn't see anything about that yet. Time will tell.
You can try the chatbot at swissparliamentbot.gpt.liip.ch, or connect your MCP client to https://swissparliamentbot.gpt.liip.ch/mcp.