Skip to main content
Glama
Austrian Parliament Open Data MCP Server

Austrian Parliament Open Data MCP Server

by austrolink

Austrian Parliament Open Data MCP Server

CI License: MIT

English | Deutsch

This Model Context Protocol (MCP) server gives AI assistants read-only access to data of the Austrian Parliament: plenary speeches, calls to order (Ordnungsrufe), stenographic protocols, agendas, votes, legislative processes, people, and other Open Data. No API key is necessary.

NOTE

This is an unofficial project. It is not affiliated with or endorsed by the Austrian Parliament (Parlamentsdirektion). Make sure that you check important facts in the official sources.

Contents

Related MCP server: mcp-nosdeputes-fr

Installation

Requirements

  • Node.js 22 or later

  • npm

  • Git, if you install from GitHub

Install from source

git clone https://github.com/austrolink/austrian-parliament-open-data-mcp.git
cd austrian-parliament-open-data-mcp
npm ci

npm ci also builds the server into dist/. The entry point is dist/index.js.

Start directly from GitHub

You can start the server directly from GitHub with npx. The first start downloads and builds the server, so it takes longer:

npx -y github:austrolink/austrian-parliament-open-data-mcp

Client configuration

The server uses the MCP stdio transport. In the examples, replace /absolute/path/to/austrian-parliament-open-data-mcp with the path of your clone. To use npx instead, set command to npx and args to ["-y", "github:austrolink/austrian-parliament-open-data-mcp"].

Visual Studio Code

Add the server to .vscode/mcp.json in a workspace or to your user mcp.json:

{
  "servers": {
    "austrian-parliament-open-data-mcp": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/austrian-parliament-open-data-mcp/dist/index.js"]
    }
  }
}

GitHub Copilot CLI

Add the server to ~/.copilot/mcp-config.json:

{
  "mcpServers": {
    "austrian-parliament-open-data-mcp": {
      "type": "local",
      "command": "node",
      "args": ["/absolute/path/to/austrian-parliament-open-data-mcp/dist/index.js"],
      "tools": ["*"]
    }
  }
}

Claude Desktop

Add the server to claude_desktop_config.json:

{
  "mcpServers": {
    "austrian-parliament-open-data-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/austrian-parliament-open-data-mcp/dist/index.js"]
    }
  }
}

Restart the client after you change the configuration.

Example questions

Ask a normal question in your MCP client. For example:

Find parliamentary initiatives about climate protection in the XXVIII legislative period.

Find events about European policy between 2025-01-01 and 2025-06-30.

Find Katayun Pracher-Hilander's speeches in the last six months.

Show the top five speakers in each National Council club in the last year.

Find Christoph Matznetter's plenary and committee activity between 2025-10-01 and 2026-03-31.

Find references to Christoph Steiner, including possible nicknames, between 2025-07-01 and 2026-06-30.

Count uses of "Remigration" by National Council members in the last year.

How many calls to order did Lukas Hammer receive as a member of the National Council?

Which calls to order in the last year were connected with "Remigration"? Group them by club and member, and name the presiding officer.

Find Yannick Shetty's transcript mentions of Rosenkranz between 2026-01-01 and 2026-06-30 from 21:40 to 21:55, including five minutes of context.

Get the National Council agenda for 2026-10-14.

Show all statements on the climate law whose review period ended yesterday.

How many seats does each club have in the Federal Council, by state? Which state holds the presidency?

Who spoke most often in the Federal Council in the last three months?

Which written inquiries to the Ministry of Justice are overdue? How fast does each ministry answer?

How often did the FPÖ and the Greens vote alike in the last year? Which motions were postponed in committees?

What happens in Parliament next week? What did the agriculture committee decide on 2026-10-01?

Who is Walter Rosenkranz, and which committees does he chair?

How long did the Strafvollzugsnovelle 2026 take from the draft to the Federal Law Gazette?

Which citizens' initiatives have the most supports? Which popular initiative had the most entries?

Who applauded whom in the current hour on 2026-10-14, and who made the most interjections?

When was the word "Klimakrise" first used in a plenary debate? Which current hours did the FPÖ request this year?

Who was questioned in the COFAG investigative committee, and where does Benko appear in the protocols?

Which analyses of laws has the Budget Office published this year? Which Court of Audit reports wait for the committee?

Who was President of the National Council in 1995? Who were the finance ministers since 2000? Which sitting of the current period was the longest? Who are the education spokespersons of the clubs?

Which members of Parliament have a paid seat on a supervisory board? Who reports the highest income category?

Get the vote results for /gegenstand/XXVIII/I/638.

Show the legislative process for /gegenstand/XXVIII/I/625.

The assistant selects a category such as applications, events, or protocols and passes the corresponding documented filters to the server. The numeric API identifiers remain internal.

Tools

  • search_parliament_website: Search the parlament.gv.at website like its search box: records, consultations and statements, plenary transcripts, press releases, news, and expert information. Filter by category, document type, topic, date range, chamber, legislative period, exact phrase, or titles only. Each result gives the title, date, category, link, and a short text excerpt. Use this tool to find a record or page by words, for example a draft law and its number.

  • get_parliament_overview: Get an overview of a period of up to 31 days, by default today and the next six days: plenary sessions, committee meetings with agenda links, enquêtes and events, review periods that end, new government bills and ministerial drafts, and press releases (Parlamentskorrespondenz). The response contains a Markdown overview by day in displayMarkdown.

  • get_parliament_committee: Get a committee by name or code: officers, planned meetings, the decisions of recent meetings or of the meeting on a date with the parties in favor and against, press releases about the committee, and pending items.

  • search_parliament_expert_information: List the publications of the Budget Office (Budgetdienst), the Research Service, the legal monitoring (Rechtsmonitoring) of drafts and bills, and the library and archive; or the reports of the Court of Audit (Rechnungshof) with their status in Parliament. Filter by words, category, topic, and date.

  • search_parliament_consultations: List review procedures (Begutachtungsverfahren) on ministerial drafts with number, title, ministry, topics, receipt date, end of the review period, number of statements, and link. Filter by title words, open or closed status, topic, ministry code, and the end date of the review period.

  • get_parliament_consultation_statements: List all statements (Stellungnahmen) on a ministerial draft or another record with statements. The response gives the counts of public, non-public, and late statements, and a Markdown table with number, date, sender, and link in displayMarkdown. When statements have online supports, a second table shows the five statements with the most supports.

  • search_parliament_participation: List citizens' initiatives (Bürgerinitiativen) and petitions with their online supports, statements, participations in the last 30 days, sponsor, and treatment status. Or list popular initiatives (Volksbegehren) with the valid entries and the turnout. Sort by supports, date, or trend.

  • search_parliament_open_data: Search a named Parliament Open Data category. The server maps categories to official API filters internally. Users do not need to find or provide filter IDs.

  • search_parliament_protocols: Search stenographic protocols of the National Council, the Federal Council, or the Federal Assembly (Bundesversammlung) by date range and optional legislative period.

  • search_parliament_speeches: Find a person's plenary speeches and other named contributions over a date range of up to ten years. Results separate speeches from other contributions and include transcript or video links when available. The response compares the results with the person's official speech list. Speeches that the list contains but no session record contains are returned in speechesOnlyInOfficialList. Each speech shows whether its official reference title contains the AI-language-model assistance marker. The response compares marked speeches with the total speech count and reports any unmarked or omitted speeches. Set include_related_activity to true to also get committee memberships, committee meeting dates and agenda links, and associated formal records.

  • rank_parliament_speakers: Rank National Council or Federal Council speakers by the number of recorded speech entries, grouped by parliamentary club. The tool reads session detail records only, includes members explicitly marked as having no club, reports unclassified entries, and returns the requested number of top speakers for each category, including ties at the cutoff. It uses the affiliation recorded for each speech, so changes over time are reflected. With metric: speaking_time, the tool ranks by the approximate speaking time from the official video timeline.

  • search_parliament_person_mentions: Find a person's surname in plenary speech transcripts from both chambers. Results include cited text, the speaker, date, session, agenda item, and transcript or video links. The tool returns 25 passages by default and gives the total number of matching passages. It also returns possible compound labels for review; it does not determine whether a phrase is an established nickname.

  • search_parliament_contributions: Search plenary sessions for speeches and other recorded contributions by text, speaker, and optional time of day. The tool can also search matching transcript passages and return nearby events with video links when available.

  • search_parliament_calls_to_order: List calls to order (Ordnungsrufe) for a date range of up to ten years. A Markdown table in displayTable gives one row for each member and session with the number of calls to order, the date, the presiding officer, and links to the session's stenographic protocol index and to the exact transcript passages. The response counts calls to order by club, recipient, and presiding officer. Set wording_query to find calls to order that are connected with an expression.

  • analyze_parliament_debate: Analyze the debates of a sitting: speakers, approximate speaking time, applause by club (who applauds whom), interjections (Zwischenrufe) by person and club, and laughter. Filter by words in the debate title.

  • search_parliament_special_debates: List the special debates of a period: current hours (Aktuelle Stunde) and EU hours with topic and requesting club, question times, urgent inquiries and motions, short debates, and statements.

  • get_parliament_term_history: Find the earliest Parliament documents that contain a word or phrase, and count the documents per decade.

  • count_parliament_speech_word_occurrences: Count a whole word in the speech transcripts of National Council or Federal Council members and report totals by member, with session, date, time, transcript link, and video link when available for each matching speech.

  • get_parliament_session_agenda: Get the agenda of a National Council, Federal Council, or Federal Assembly session, including special activities, agenda amendments, related records, and official agenda links.

  • get_parliament_vote_results: Get published vote outcomes and party positions for an official record.

  • get_parliament_legislative_process: Get the phases and dated steps for a bill or other parliamentary record.

  • get_parliament_law_status: Follow a law from the ministerial draft and its review period to the government bill or motion, the committee reports, the decisions of the National Council and the Federal Council, and the publication in the Federal Law Gazette (BGBl.). The response gives the time between the steps, the RIS link, and the EU law that the law implements. Accepts a record path, a citation such as 625 d.B., 121/ME, or 1007/A, or a gazette number such as BGBl. I Nr. 91/2026.

  • search_parliament_people: Search public parliamentary people by name or function.

  • get_parliament_person_profile: Get the profile of a current or former member of Parliament or of the government since 1918: biography, mandates and functions, current committees, plenary speeches, parliamentary activities, and the declared positions, activities, and income categories. If a name matches more than one person, the result lists the candidates.

  • search_parliament_inquiries: Search written inquiries (schriftliche Anfragen) of the National Council or Federal Council and their answers. Filter by asking member, addressed minister or ministry, party, status (open, overdue, answered, urgent), and title words. The response gives counts, the answer rate and average answer days for each addressee, and links to the inquiries and answers.

  • search_parliament_votes: Get the decisions of the National Council or Federal Council with the outcome and the parties in favor and against, in plenary and in committees. The response counts the positions of each party and shows how often each pair of parties voted alike. Federal Council decisions include objections (Einspruch). Other kinds list motions that a committee postponed (vertagt) and roll-call votes.

  • get_parliament_composition: Get the current composition of the National Council, the Federal Council, or the Federal Assembly: seats by club and state, women and men, and the presidium. For the Federal Council, the tool also gives the seats of each state by club and the state that holds the presidency. It can list the members of a club or state, and the area spokespersons (Bereichssprecher) of the clubs, for example for Bildung.

  • get_parliament_history: Get history and records: the presidents of the National Council and the Federal Council since 1920, the federal governments since 1918 with chancellors and parties, the holders of a ministry, the legislative periods with their sittings, and sitting records such as the longest sittings and the latest ends.

  • search_parliament_transparency: Search the declarations of all current members of both chambers under the Unvereinbarkeits- und Transparenz-Gesetz: leading positions in companies, other paid activities, leading honorary positions, and income categories. Filter by words, category, club, person, or minimum income category. The response counts the members of each club with paid positions and income.

  • get_parliament_investigative_committee: Get an investigative committee (Untersuchungsausschuss) by name words: subject, chair, sittings, the persons questioned (Auskunftspersonen) with the published protocols, reports, and press releases. Set quote to find a phrase in the hearing protocols of the committee. Without a name, the tool lists all investigative committees and shows the active one.

  • get_parliament_record: Fetch a detail page as JSON by its official relative URL path.

The server also sends short instructions to the client: start a search by words with search_parliament_website, start a question about one person with get_parliament_person_profile, and show the Markdown tables in displayMarkdown and displayTable directly in the chat instead of in a file.

Prompts and resources

The server provides prompts (slash commands) for frequent tasks. In Visual Studio Code, type /austrian-parliament-open-data-mcp. in the chat and select a prompt. In Claude Code, type /mcp__austrian-parliament-open-data-mcp__ and the prompt name. The prompts write the task in German, so the answer is in German. The client can complete person names.

Prompt

Arguments

Task

wochenbriefing

start

Sittings, committee meetings, review periods, and new bills of a week

gesetz-verfolgen

gesetz

A law from the ministerial draft to the Federal Law Gazette

personendossier

person

Functions, speeches, inquiries, calls to order, and declarations

abstimmungsanalyse

start, ende, kammer

Party agreement, disputed decisions, and postponed motions

ordnungsrufe

start, ende, person

Calls to order by club, person, and presiding officer

stellungnahmen

entwurf

All statements on a ministerial draft as a table

Resources are reference data that you can add to a chat. In Visual Studio Code, select Add Context > MCP Resources, or run MCP: Browse Resources. The client can complete the names of glossaries, glossary terms, and chambers.

Resource

Content

parliament://document-types

Codes for the document_types filter of search_parliament_website

parliament://glossary/{name}

The terms of one of the seven glossaries of the Parliament, with links

parliament://glossary/{name}/{term}

The explanation of one term from a glossary

parliament://committees/{chamber}

The committees of national-council or federal-council, with codes

parliament://legislative-periods

The legislative periods of the National Council with their first sittings

When a name matches more than one person, the server asks which person you mean, if the client supports forms (MCP elicitation). Otherwise the tool returns the candidates.

How the searches work

Dates and ranges

All tools treat start_date and end_date as inclusive. The Parliament filter API treats the second date of a range as exclusive and a single date as "from this date onward". The server converts each inclusive range before it sends the request. Raw filters in search_parliament_open_data use the API rules.

Protocol searches, person-mention searches, and word counts accept date ranges of up to 366 days. Protocol searches for the Federal Assembly accept any period, because it met only 19 times since 1945. Speech, contribution, and call-to-order searches accept date ranges of up to ten years. Speech and contribution searches load up to 500 sessions. Other tools that use session records remain limited to 100 sessions. Historical searches use the protocol index. If a search includes today or yesterday, the server also checks the current legislative period's plenary-session index so it can find current sessions before the protocol index updates.

search_parliament_website uses the search of the parlament.gv.at website. One request finds records, consultations, statements, transcript passages, press releases, and other pages by words. The search also finds other forms of a word. For example, "Remigration" also finds "Remigrations". Use match: "phrase" for an exact phrase and title_only: true to search only titles. document_type takes one of 255 codes of the website, for example AB (answer to a written inquiry), AUB (committee report), BRH (Rechnungshof report), KOMMUSA (communiqué of an investigative committee, for example a hearing protocol), or MEG (ministerial draft). It also accepts words of the German type name if they identify one type. topic takes one of the 20 topics of the website, for example "Klima, Umwelt und Energie". This search interface is not part of the documented Open Data offer. If the website changes the interface, the tool can fail until the server is updated.

People

For person-name lookups, use search_parliament_people or the people dataset, not parliamentarians. In search_parliament_people, full names use the Parliament's server-side name filter, and partial names and function searches use the complete people directory. The search returns at most 50 records. The other tools resolve names with the cached people directory. When a name matches more than one person, a match of whole words wins: "Bures" finds Doris Bures, not Karl Buresch. Otherwise the server asks which person you mean, if the client supports forms, or the tools name the candidates. The form closes when the tool call ends. search_parliament_contributions does not ask, because it filters by the words of the name. The parliamentarians dataset has no name filter and needs a documented filter to avoid an oversized response.

get_parliament_person_profile reads the person page and three lists of the page: speeches (filter list 251), activities (filter list 25), and committee memberships (filter list 250). Activities are the records that the person page lists, for example motions and inquiries that the person submitted and answers that the person gave as a minister. The tool shows the current committees with one row for each committee. If one of the three lists fails, the profile contains the other parts and lists the failure in warnings.

Members of the National Council and the Federal Council declare leading positions in companies, other activities with income, and leading honorary positions (§ 6 Unvereinbarkeits- und Transparenz-Gesetz). By 30 June of the next year, they also report the income category of a year: the average monthly gross income from the leading positions and paid activities. Since 2021, the categories are 1 (1 to 1,150 euros), 2 (up to 4,000 euros), 3 (up to 8,000 euros), 4 (up to 12,000 euros), and 5 (more than 12,000 euros). A category is a range, not an amount. search_parliament_transparency reads the full lists of both chambers and uses the latest year that most members have reported. A position with an asterisk in the official list brings no income; the tool marks it "ohne Einkommen".

Speeches and contributions

Speech searches, and contribution searches with a speaker that matches one person, select the sessions to load:

  • If the range has 80 sessions or fewer and the client-side request burst has room for the sessions that are not in the cache, the server loads all of them.

  • Otherwise, the server loads only the sessions in which the person spoke or has an official record. Examples of official records are calls to order, procedural statements, and oral questions. The person's official speech list and formal-record list identify these sessions.

The response field sessionSelection shows the strategy and the number of sessions in the range and loaded. If the person's lists are not available, the server loads all sessions in the range.

Person activity searches include both plenary chambers by default. With include_related_activity, they also include committee membership, committee meeting dates, published agendas, and formal records associated with the person by the official person filter. Committee membership and meeting records do not prove attendance or an individual spoken contribution. Formal record associations do not prove authorship or speech.

Contribution searches can use start_time and end_time to narrow results to a time of day. Set search_transcripts to search the linked transcript passages for the query; this requires a speaker or time range and checks at most 400 passages. Set context_minutes to include nearby recorded contributions. Procedural contributions include the speaker and official video link when the session data provides them.

Transcript search is supplementary: unavailable transcript pages set transcriptSearchStatus: "partial" and are listed in transcriptSearchFailures. A search above the passage limit reports transcriptSearchStatus: "skipped_limit". Neither condition removes matching structured session records from the results.

Overview and committees

get_parliament_overview reads the date list of the website (filter list 600) and leaves out guided tours and visits to sittings unless you ask for them. It adds the review periods that end in the period, new government bills and ministerial drafts, the press releases of the period, and the weekly preview "Die Parlamentswoche". If one of these sources fails, the tool returns the other parts and lists the failure in warnings.

Committee meetings are not public, so the press releases (Parlamentskorrespondenz) often are the only public report of a meeting. get_parliament_committee reads the committee page: the committee decisions that settled an item, the meeting dates, and the reports to the plenary. The committee decision on a report is a step in the record of the report, so the tool reads these records for the meetings that it shows. Pending items include motions that the committee postponed.

History and records

get_parliament_history reads the list of the presidents of the National Council since 1920 (WFW_003), the list of the presidents of the Federal Council (filter list 10401), and the government members since 1918 (filter list 1717). A government ends when the next government starts. When all its members left office before, as in March 1938, the government ends on the last day of its members. The party data of the government list is mostly complete from the mid-1990s and partial or missing before. The list has no head of the State Chancellery of 1918–1920 and 1945. A government name such as "Kurz I" selects one government; a name such as "Kurz" lists the governments and the roles of the person. A query such as "Finanzminister" lists the ministers of the ministry without the state secretaries. The legislative periods come from the sittings in the protocol index (filter list 211).

For sitting records, the tool reads the sitting records of a legislative period (by default the current period) or of a date range of up to 366 days (by default the year before the end date). The time line of a record has the opening, the closing, the interruptions, and the continuations of a sitting from the XXVII legislative period (October 2019). The duration is the time in session without interruptions; some sittings, for example budget sittings, continue on the next days. A first query of a whole period reads up to about 300 records and can take half a minute.

The area spokespersons come from the list that the clubs report (filter list 403).

Investigative committees

get_parliament_investigative_committee finds the investigative committees in the committee list (filter list 2008) and reads the committee page. The persons questioned come from the list of communiqués on the page: each published hearing protocol is a communiqué that names the person. The tool shows the publication date of the protocol; the Parliament data has no separate field for the date of the hearing. Hearings without a published protocol do not appear. The quote search uses the website search for the document type KOMMUSA from the start of the committee until 90 days after its end. It keeps only the documents of the committee: the record number in the document path identifies the committee. When the hearing protocol of a record has a hit, the tool does not show the communiqué of the same record again. For older committees, the hearing protocol is part of the communiqué.

Expert information

search_parliament_expert_information reads the list of expert publications (filter list 616) with the server-side filters for the type and the date, and the list of legal monitorings (filter list 614). The reports of the Court of Audit come from the record list (filter list 101, document type BRH); for the returned reports, the tool reads the records for the status of the committee treatment. To search the text of these publications, use search_parliament_website with the category expert_information.

Votes and decisions

search_parliament_votes reads the decisions (resolutions) in the record of each sitting. They contain the plenary decisions of the sitting and the committee decisions on its agenda items, each with the parties in favor and against. The tool keeps only the third reading of a law when a second reading has the same result. A decision without votes against counts as unanimous. An accepted report that rejects a motion (ablehnender Ausschussbericht) means that the motion failed. The party agreement shows, for each pair of parties, the share of decisions in which both voted the same way. Postponed motions come from the website search for record pages with the word "vertagt" and from the motion list (filter list 101), which gives the proposing party. Roll-call votes come from the protocol passages that mention them.

Written inquiries

search_parliament_inquiries reads the inquiry list of the Parliament (filter list 101) in one request. Each entry shows whether the inquiry was answered and by which answer, or until when the answer is due. Ministers must answer within two months, so an open inquiry after this date counts as overdue. Urgent inquiries (Dringliche Anfragen) are answered orally in the sitting and never count as overdue. The server finds the addressee with the list of all members of federal governments since 1918 (filter list 1717) and the date of the inquiry. The addressee filter selects the roles that contain the words, for example "Inneres" for the Minister of the Interior. It finds the inquiries to the holder of the role on the date of each inquiry, not the other inquiries to the same person. Inquiries of type JPR go to the President of the National Council or to a committee chair. The answer days come from the dates of the answers.

Consultations and statements

search_parliament_consultations reads the Parliament's list of ministerial drafts in review (filter list 143). The end of the review period is a step in the record of each draft, so the tool reads the records of the matching drafts. get_parliament_consultation_statements reads all statements on a record in one request (filter list 142). Each public statement has a link; non-public statements have none. Statements with a date after the end of the review period count as late. The tool returns the complete list as a Markdown table in displayMarkdown, so that the assistant can show it directly in the chat.

The same filter list 143 contains the citizens' initiatives and petitions with their online supports, the number of statements, and the participations in the last 30 days ("Trend"). Supports are available from the XXIV legislative period. search_parliament_participation reads the records of the returned items for the sponsor and the status. If a record fails, the item stays in the result without these details, and failedRecords gives the number of failures.

Popular initiatives come from the record list (filter list 101). The Parliament data has no field for the number of entries. The official text of each popular initiative contains the result of the Federal Electoral Board, so the tool reads the row for all of Austria: eligible voters, valid entries, and turnout. The tool accepts a row only if the turnout agrees with the two numbers. Popular initiatives before about 2003 have only a PDF text, so their entries are missing. For a ranking by entries, the tool reads the texts of all matching popular initiatives.

Calls to order

Use search_parliament_calls_to_order for questions about calls to order. It reads the Parliament's call-to-order records, so a search over several years needs few requests. Set recipient or presiding_officer to filter the results. The displayTable field contains every returned call to order as a Markdown table, with one row for each member and session. Rows are sorted by date and session number in ascending order. Each row shows the number of calls to order in that session, the date, the presiding officer, the linked protocol, and the exact transcript passages. Duplicate links are listed once, and an unreachable link is marked "(nicht erreichbar)". The assistant can show the table directly in the chat. The fields byClub, byRecipient, and byPresidingOfficer count all matching calls to order. If resultsTruncated is true, the table only covers the returned calls. The result does not include links to individual call-to-order records.

Set wording_query to read the presiding officer's call-to-order passage and the linked preceding passage. The response then contains items with the excerpts, and the field wording.matchedIn shows where the expression occurs. Read each excerpt before you attribute a call to order to an expression. A presiding officer can mention the expression without it being the reason, and one statement can cover several calls to order. Calls to order with unreadable passages are listed in callsToOrderWithUnreadableWording. They are not evidence that the expression was absent.

Debates, speaking time, and reactions

The media library page of a sitting (/aktuelles/mediathek/...) has a timeline with the start time of every turn, including the turns of the presiding officer and the votes. The tools use the time from the start of a turn to the next turn as the speaking time. This is an approximation that includes interruptions; the Parliament publishes no official duration for each speech. The timeline is complete for the sittings of the current legislative period and partial or missing for older sittings. For a ranking by speaking time, a sitting counts only if its timeline has at least 80 % of the speech entries of the sitting record. The response lists the sittings that the ranking leaves out.

analyze_parliament_debate reads the transcript of each speech and counts the notes in brackets: applause ("Beifall bei der FPÖ"), interjections ("Zwischenruf des Abg. …", "Abg. … [NEOS]: …"), shouts of a club ("Rufe bei der SPÖ"), and laughter ("Heiterkeit"). Current transcripts give the club of a member in square brackets. A note can name several clubs; each named club counts once. Turns of the presiding officer and procedural turns (for example points of order, calls to order, announcements, and the reports of a rapporteur) do not count as speeches. The title filter first looks for a debate with the exact title, then for the words as whole words, and then for parts of words. Without a title filter, the tool reads at most 100 transcripts and gives the number of transcripts that it did not read.

search_parliament_special_debates reads the special activities of each sitting record. The topic and the requesting club come from the description of the Parliament; when the description does not name a club, the field is empty.

get_parliament_term_history uses the website search. The website search has no sort by date, so the tool halves the period from 1918 until the earliest documents are in a period of at most 45 days. The search finds word forms and the text of scanned documents, which can contain recognition errors. An early hit does not prove who first used a term.

Transcripts and word counts

Person mention searches look for the member's surname, including compound forms. Treat returned text as evidence to assess, not proof that a phrase is a nickname or that a speaker intended it as one. The available committee data does not provide reliable individual speech transcripts, so nickname and name-mention searches cover plenary speech transcripts only.

Word counts use case-insensitive whole-word matches in the official HTML transcript passages. For full-protocol documents, the server isolates the speech section linked by the transcript reference before it counts words. It does not attribute transcript-marked interjections by other members to the main speaker.

Word counts and person-mention searches first use the website search to find the passages that contain the word or the surname. The website search also finds other forms of the word and parts of hyphenated compounds, so it finds a superset of the passages with exact matches. The server then reads only these passages and matches the text exactly. It reads all passages of the sittings of the last three days, because the search index can lag behind new transcripts. If the website search fails, finds more than 3,000 passages, or cannot search the term reliably, the server reads every passage in the range. The field transcriptSelection shows the method. A comparison with the full scan gave identical results for a one-year word count (54 instead of 2,907 requests) and for two person-mention searches.

Speech, contribution, and call-to-order responses check the returned transcript links for HTTP reachability. Call-to-order responses also check session protocol indexes. The field protocolLinkSummary gives the number of checked, reachable, and unreachable links. The field unreachableProtocolLinks lists each failed link with its HTTP status or request error. An item with an unreachable transcript link also has a protocolLinkCheck field. In the call-to-order table, an unreachable link is marked "(nicht erreichbar)". Missing protocol links are listed in linkIssues.

The server does not play or analyze audio or video. A video URL identifies an official recording but does not show that the recording was reviewed. Transcript text can support claims about recorded wording; it cannot by itself verify pronunciation, vocal delivery, gestures, or audience reactions. Speech-search responses include evidenceBasis, transcriptTextReviewed, and audioVideoReviewed fields to show what source content the tool inspected. The speech search also reports speechEvidenceAudit and marks each speech whose official reference title says Rede von KI-basiertem Sprachmodell unterstützt. This label records AI-model assistance; it does not prove that the voice in the recording was synthetic. A missing label does not prove that no AI assistance was used.

Laws and the Federal Law Gazette

get_parliament_law_status reads the record of the bill or motion. For a ministerial draft, it follows the link to the government bill; for a committee report, it follows the link to the main record. The National Council decision is the vote in third reading. The tool counts the statements on the draft with the statement list.

The Parliament records do not contain the Federal Law Gazette number. For this number, the tool uses the Open Government Data interface of the RIS (Rechtsinformationssystem des Bundes). Each gazette entry in the RIS names the legislative period, the government bill or motion, and the committee report. After the National Council decision, the tool searches the gazettes of the next 240 days and keeps the entry that names the record. With a gazette number, the tool reads the entry and then the record that it names. The RIS has the authentic gazette from 2004. Some gazettes have no parliamentary record, for example a decision of the Constitutional Court. Budget laws have no Federal Council decision.

Votes, processes, and other datasets

For vote results or legislative history, first find a record with search_parliament_open_data, then pass its official relative path to the matching detail tool. The vote tool reports only results and party positions that the Parliament publishes. It does not infer individual vote counts.

The server limits response sizes and search result counts. A text query in search_parliament_open_data only filters rows returned by the API; it does not reduce the API response. Use documented filters for large datasets. If an API response exceeds its size limit, narrow the search and try again.

Caching and request limits

The Parliament website limits filter-list and record requests from one client. After a burst of approximately 120 requests, it answers approximately 15 of these requests per second. More concurrent requests do not make a search faster. The website does not delay transcript documents. Thus the server keeps the number of limited requests low and stays below the limit:

  • It caches successful responses in memory and on disk. Searches that repeat or overlap earlier searches use the cache, also after a restart.

  • Transcript searches group speech passages by source document and read each document once.

  • The server reads expired transcript documents again with their ETag. If the document did not change, the server receives no new content.

  • Transcript link checks use the cache. A transcript document that the server read recently counts as reachable.

  • A client-side rate limit allows a burst of 100 filter-list and record requests and then 14 of these requests per second. Transcript documents and link checks are not part of this limit.

  • Each request identifies the server with the user agent austrian-parliament-open-data-mcp/<version> and the project URL.

The cache lifetime depends on the date of the data:

Data

Cache lifetime

Today or yesterday, on a plenary day

1 minute

Today or yesterday, other days

5 minutes

Up to 14 days old

30 minutes

Up to 90 days old

6 hours

Up to one year old

1 day

Older than one year

7 days

Lists without a date, on a plenary day

1 minute

Lists without a date, other days

10 minutes

People, person pages, and committees

12 hours

Federal Law Gazette searches (RIS)

1 day; 30 minutes without a result

Failed transcript link checks

1 minute, memory only

A plenary day is a day with a National Council or Federal Council sitting that the server found in the official session lists. The day after a sitting also counts as a plenary day. The server does not cache failed requests.

The disk cache is in ~/.cache/austrian-parliament-open-data-mcp, or in $XDG_CACHE_HOME/austrian-parliament-open-data-mcp when XDG_CACHE_HOME is set. The server removes files older than eight days. When the cache is larger than its limit, it removes the oldest files. Use these environment variables to change the behavior:

Variable

Effect

PARLIAMENT_MCP_CACHE_DIR

Sets the cache directory.

PARLIAMENT_MCP_DISK_CACHE

off disables the disk cache. The memory cache stays.

PARLIAMENT_MCP_CACHE_MAX_MB

Sets the size limit of the disk cache. The default is 512 MB.

PARLIAMENT_MCP_REQUESTS_PER_SECOND

Sets the client-side rate for filter-list and record requests. The default is 14. 0 disables it.

Long searches send MCP progress notifications when the client supplies a progress token. If the client cancels a tool call, the server stops its open requests. Tool responses use compact JSON to keep them small.

Data sources, license, and terms of use

The data comes from the Austrian Parliament (Parlamentsdirektion). The Parliament publishes its Open Data under the Creative Commons Attribution 4.0 International (CC BY 4.0) license. When you reuse data that you get through this server, name the source, for example "Source: Parlament Österreich, CC BY 4.0", and follow the license and terms of use.

The server reads these sources on www.parlament.gv.at:

Source

Use

Open Data filter API (/Filter/api/filter/data/{id})

Datasets such as protocols, proceedings, people, and committees

JSON detail pages (?json=TRUE)

Session, person, committee, and record details

Stenographic protocol documents (/dokument/...)

Transcript text and link checks

Plenary-session list of the website (listeId=11070)

Current sessions before the protocol index lists them

Speech list of a person page (filter list 251)

A person's speeches for session selection and reconciliation

Participation (filter lists 143, 142)

Drafts in review, statements, initiatives, and petitions

Popular initiatives (filter list 101, official texts)

Popular initiatives and the result of the Electoral Board

Member lists of the website (WFW_002, WFW_005)

Current members of the National Council and the Federal Council

Presidium list (filter list 402)

Presidents and vice presidents of both chambers

Government members (filter list 1717)

Ministers and state secretaries since 1918, with their terms

Dates (filter list 600) and committees (list 2008)

Sittings, committee meetings, events, and committee pages

Media library pages (/aktuelles/mediathek/...)

Speaker timeline of a sitting with the start of each turn

Expert publications (filter lists 616, 614)

Budget Office, Research Service, and legal monitoring

Presidents (WFW_003, filter list 10401)

Presidents of both chambers since 1920

Area spokespersons (filter list 403)

Spokespersons that the clubs report for each area

Person lists (filter lists 25, 250)

Activities and committee memberships of a person

Declarations (/person/unvtrans/...)

Positions, activities, and income categories of all members

Website search (/Filter/api/filterform/vts/data)

Full-text search of website pages and transcript passages

For the Federal Law Gazette, the server also reads the Open Government Data interface of the RIS (data.bka.gv.at/ris/api/v2.6, application BgblAuth). The Federal Chancellery publishes the RIS data under CC BY 4.0. Name the source, for example "Source: RIS, Bundeskanzleramt, CC BY 4.0".

The Parliament marks the datasets of its Open Data offer as such. Data that is not marked as Open Data is subject to the general terms of use of the Parliament website. The license of this project covers only the code, not the data.

Development

npm ci              # install dependencies and build
npm run dev         # run the server from the TypeScript sources
npm run check       # lint, Markdown lint, format check, type check, and tests
npm run build       # compile to dist/
npm run format      # format all files

The code has this structure:

Directory

Content

src/api/

HTTP access, cache, rate limit, and request context

src/domain/

Parsing and search logic for sessions, speeches, transcripts, and records

src/presentation/

Markdown tables that the assistant shows in the chat

src/shared/

Constants, date handling, link checks, and general helpers

src/tools/

One file for each MCP tool, and index.ts to register all tools

tests/

Unit tests and tool tests with a mocked Parliament API

The tests do not send requests to the Parliament website. Use Conventional Commits for commit messages.

Security

To report a vulnerability, read SECURITY.md.

License

The code is available under the MIT License. The data that the server reads is subject to the license and terms of the Austrian Parliament. Refer to Data sources, license, and terms of use.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Enables AI assistants to search, explore, and query any CKAN open data portal through natural language, making public datasets accessible without requiring knowledge of the portal's API.
    20
    1,846 npm
    60
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables querying the French National Assembly data, including deputies, interventions, questions, and votes, through natural language.
    364 npm
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI assistants to query official Polish Sejm data and the ELI legal acts database for deputies, clubs, committees, votes, interpellations, bills, proceedings, transcripts, and legal acts, with source links.
    29
    73 npm
    2
    Apache 2.0