Skip to main content
Glama
malkreide

parlament-mcp

by malkreide

🇩🇪 Deutsche Version

🏛️ parlament-mcp

CI PyPI version License: MIT Swiss Public Data MCP Portfolio

Part of the Swiss Public Data MCP Portfolio – connecting AI models to Swiss public data sources.

Note: This server covers the federal level (Curia Vista). This repo additionally hosts a self-contained subproject under openparldata-mcp/ — the subnational counterpart for the 26 cantons and ~70 municipal parliaments (OpenParlData.ch). The two are independent servers.

An MCP server that connects AI models to the Swiss Federal Parliament via the Curia Vista OData API (ws.parlament.ch). Access motions, interpellations, votes, members, sessions, and the verbatim debate transcripts of the Amtliches Bulletin – with no API key required (Phase 1 – No-Auth-First).


🎯 Anchor Demo Queries

Metadata layer:

"Welche Vorstösse zu KI in der Schule sind hängig?"parlament_search_business(keyword="KI", keyword2="Schule", status="Eingereicht")

Verbatim transcripts (Amtliches Bulletin):

"What did National Councillor Munz say in the 2024 spring session about the Volksschule? Give me the exact wording with a correct AB citation."parlament_search_transcripts(speaker_name="Munz", session_id=5202, keyword="Volksschule") → then parlament_get_transcript(transcript_id=…) for the full wording.

Returns short, citable excerpts (AB 2024 N, 2024-03-13, Munz Martina) with a stable source URL; the verbatim text is fetched on demand, never in bulk.

→ More use cases by audience →

Perfect for the KI-Fachgruppe Stadtverwaltung Zürich: find pending motions on AI in education, or quote what was actually said in the chamber – instantly.


Related MCP server: lobbywatch-mcp

🔧 Tools

Tool

Description

parlament_search_business

Search Vorstösse by keyword, type, status, council, date

parlament_get_business

Full details of a single business (texts, FC response)

parlament_search_members

Find councillors by canton (e.g. ZH), party, council

parlament_get_votes

Parliamentary votes with Ja/Nein meaning

parlament_get_sessions

List recent sessions with IDs for follow-up queries

parlament_search_transcripts

Search debate transcripts → citable excerpts with AB citation + source URL (speaker / session / business / date filters)

parlament_get_transcript

Fetch the verbatim full text of a single speech by ID (capped, paginated, is_excerpt flagged)


🏗️ Architecture

┌──────────────────────────────────┐
│     MCP Host (Claude Desktop /    │
│     Claude API / IDE)             │
└─────────────┬─────────────────────┘
              │ MCP Protocol (JSON-RPC 2.0)
              │ Transport: stdio (local) / SSE (cloud)
┌─────────────▼─────────────────────┐
│          parlament-mcp            │
│   FastMCP · Python · Pydantic v2  │
│                                   │
│  ┌── metadata layer (server.py) ──┐
│  │  search_business · get_business │
│  │  search_members · get_votes     │
│  │  get_sessions                   │
│  └─────────────────────────────────┘
│  ┌── transcript layer ────────────┐  ← separate module (transcripts.py)
│  │  search_transcripts (excerpts) │    · Language='DE' dedups editions
│  │  get_transcript (verbatim)     │    · Type=1 = real speeches only
│  └─────────────────────────────────┘    · retry + 45s read timeout
└─────────────┬─────────────────────┘
              │ HTTPS / OData v3
┌─────────────▼─────────────────────┐
│  ws.parlament.ch / odata.svc      │
│  Curia Vista – No Auth Required   │
│                                   │
│  Business · Vote · MemberCouncil  │   metadata path
│  Session ─< Meeting ─< Subject ─< Transcript   transcript path
└───────────────────────────────────┘

🚀 Installation

Claude Desktop (stdio)

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "parlament": {
      "command": "uvx",
      "args": ["parlament-mcp"]
    }
  }
}

Local development

git clone https://github.com/malkreide/parlament-mcp
cd parlament-mcp
pip install -e .
python -m parlament_mcp.server

Cloud / Railway (SSE)

MCP_TRANSPORT=sse MCP_HOST=0.0.0.0 PORT=8080 python -m parlament_mcp.server
# SSE endpoint: http://your-host:8080/sse

Network binding

By default the server binds to 127.0.0.1 (localhost only). Set MCP_HOST=0.0.0.0 only inside a container/cloud context (Docker, Railway, Render, Kubernetes). Never bind to 0.0.0.0 on a local dev machine – it exposes the server to your local network (NeighborJack risk); the server logs a warning if you do so outside a detected container.

Transport is selected via MCP_TRANSPORT (stdio default, or sse / streamable-http); --http is kept as an alias for streamable-http.

Authentication (optional)

The HTTP transport is open by default (public read-only data). To require a bearer token, serve via the CORS/auth app factory and set MCP_BEARER_TOKENS:

MCP_BEARER_TOKENS="alice:tok_abc,bob:tok_def" MCP_ALLOWED_ORIGINS="https://claude.ai" \
  uvicorn parlament_mcp.server:create_http_app --factory --host 0.0.0.0 --port 8080

Each request then needs Authorization: Bearer <token>; identity comes from the validated token, not a session header (see docs/security.md).

Docker

docker compose up --build          # binds 127.0.0.1:8080 only
# or build the hardened image directly (non-root, read-only FS):
docker build -t parlament-mcp .

Kubernetes manifests (hardened securityContext, resource limits, egress NetworkPolicy, Mcp-Session-Id sticky routing) live in deploy/k8s/; an HAProxy stick-table example is in deploy/haproxy.cfg.


🔗 Synergies

Partner Server

Combination

openparldata-mcp

Federal ↔ subnational — same question across cantons & municipalities

fedlex-mcp

Law text ↔ parliamentary debate that created it

zurich-opendata-mcp

City policy ↔ cantonal/federal motions

swiss-statistics-mcp

Data backing ↔ motions citing statistics

Power query example:

"Zeige mir alle Zürcher Motionen zu KI in der Bildung
 und verlinke die relevanten Bundesgesetze aus fedlex-mcp."

📊 Data Source

  • API: ws.parlament.ch/odata.svc

  • Authentication: None (Phase 1 – No-Auth-First)

  • Protocol: OData v3 / JSON

  • Coverage: All parliamentary businesses since 1978; votes since ~2000. Structured verbatim transcripts (Amtliches Bulletin) from 1999-12-06 onward (earlier years 1891–1999 exist only as archive scans — see Known Limitations).

  • Update cycle: Real-time (official government data)

Official proceedings of Swiss authorities are excluded from copyright under Art. 5 para. 1 lit. a URG (Swiss Copyright Act). The verbatim wording of parliamentary debates in the Amtliches Bulletin may therefore be reproduced and quoted freely — which is exactly what the transcript tools return: the wording itself, never a summary standing in for it.


📜 Data sources & licenses

Source

License

Attribution

Curia Vista (ws.parlament.ch)

CC BY 4.0

© Schweizer Parlament, CC BY 4.0

Every tool returns a typed structured response (FastMCP exposes the output schema) carrying source, license, provenance, match_type and count alongside typed results. Data is passed through unmodified.

🧭 Phase

This server is in Phase 1 — Read-only Wrapper (all tools readOnlyHint: true, no writes). The full phase model and transition criteria are in docs/roadmap.md.

🔖 MCP Protocol Version

This server speaks two protocol eras over the same endpoint. The client's first request on a connection decides which one applies; a later claim from the other era is refused.

Era

Revision

Who reaches it

initialize handshake

2024-11-052025-11-25

What today's clients speak. The server answers with the revision asked for, or with the 2025-11-25 ceiling when the request asks for something newer.

Per-request envelope

2026-07-28

A request carrying the 2026-07-28 _meta envelope opens a modern connection.

Both revisions are pinned in tests/test_protocol_version.py and asserted against the installed SDK, so a Dependabot bump of mcp cannot move either one silently. This server builds no ASGI app to send an initialize through, so the gate asserts the SDK constants rather than a measured response — the weaker form, named rather than left unsaid.

Note that the SDK's LATEST_PROTOCOL_VERSION is an alias for the modern era, not for the handshake era — pinning against it alone would leave the era that current clients actually negotiate free to drift.

Update policy. When the gate fails, do not edit the constant blindly: read the spec changelog between the two revisions, verify the server still behaves, then move the constant, this section, README.de.md and CHANGELOG.md together.

🧱 MCP primitives

Phase 1 uses Tools only — rationale and the Phase-2 Resources plan are in docs/adr/ADR-003-mcp-primitives.md.

🏷️ Tool annotations

All tools declare explicit annotations consistent with their behaviour:

Tool

readOnly

destructive

idempotent

openWorld

parlament_search_business

parlament_get_business

parlament_search_members

parlament_get_votes

parlament_get_sessions

parlament_search_transcripts

parlament_get_transcript

📈 Observability

Structured JSON logs go to stderr (stdout stays reserved for the stdio protocol). OpenTelemetry tracing wraps each tool call and auto-instruments outgoing HTTP; set OTEL_EXPORTER_OTLP_ENDPOINT (with the otel-export extra) to ship spans. See docs/security.md for the full security posture (Lethal-Trifecta assessment, egress allow-list, gateway hardening).


🛡️ Safety & Limits

Aspect

Details

Access

Read-only (readOnlyHint: true) — the server cannot modify or delete any data

Personal data

Parliamentary businesses are public record by law (BGÖ). No private data is accessed or stored.

Rate limits

Built-in per-query caps: max. 100 results (businesses/members), 50 (votes), 30 (transcript search), 10 (sessions). Transcript full text is capped per call and paginated — you never pull a whole session by accident.

Timeout

20 seconds per metadata call; 45 seconds for transcript reads (verbatim search is heavier)

Authentication

No API keys required — Curia Vista is publicly accessible

Data source

Official Swiss federal government data (Schweizerische Parlamentsdienste)

Terms of Service

Subject to ToS of ws.parlament.ch — Schweizerische Parlamentsdienste


Known Limitations

General

  • OData substringof() filter is case-sensitive for some fields.

  • Session names may be null in the API for very recent sessions – use session ID.

Transcripts (Amtliches Bulletin) — verified live 2026-07-19:

  • Temporal coverage: from 1999-12-06 only. The structured Transcript entity reaches back to Dec 1999. Debates from 1891–1999 exist only as scanned archive documents (Bundesarchiv / Amtsdruckschriften) and are not connected here (no OCR in scope). A query whose whole date window predates coverage returns an explanatory error, not an empty result.

  • No page number in the source. The API carries no page/column field, so the classic AB <year> N <page> form cannot be built. We emit a stable, verifiable substitute — AB <year> <N|S>, <date>, <speaker> — plus the authoritative source_url (SubjectId) and the transcript_id. This is a documented, honest trade-off, not an omission.

  • Language behaviour (important). Language is the edition, not the spoken language. The tools filter Language eq 'DE' purely to deduplicate the three byte-identical editions (DE/FR/IT) down to one copy. Every speech is returned in its original wording; a French or Italian speech is not hidden — its real language is reported in the language field (de/fr/it). The response states this via language_note.

  • Truncation is explicit, never silent. Search returns short excerpts (snippet, ~320 chars) with is_excerpt, total_length_chars and a hint to fetch the full text. parlament_get_transcript caps output at max_chars; when it truncates it sets is_excerpt=True and returns a next_offset to continue.

  • Verbatim only, never summarised. The wording is the product; the tools never substitute a summary for the actual text.

  • Latency: a free-text keyword combined with a speaker_name is the slowest path (~40 s). Add a session_id, business_number or date window to keep reads around 1–2 s.


🧪 Testing

pip install -e ".[dev]"

# Unit + mocked integration tests (no network), as run in CI:
PYTHONPATH=src pytest tests/ -m "not live"

# Include live tests against the real ws.parlament.ch API:
PYTHONPATH=src pytest tests/ -m live

HTTP is mocked with respx; network-dependent tests are marked @pytest.mark.live and excluded from CI via -m "not live". Tool definitions are pinned in tool-hashes.json (python -m parlament_mcp.tool_hashes --check).


Contributing

See CONTRIBUTING.md.


Security

See SECURITY.md for the security policy and posture (vulnerability reporting, Lethal-Trifecta assessment, accepted risks).


License

MIT © Hayal Oezkan — see LICENSE


Author

Hayal Oezkan · github.com/malkreide

Installation

Run via uv's uvx — no clone or manual install needed. Add to your MCP client config (mcpServers for Claude Desktop, Cursor and Windsurf; use a top-level servers key for VS Code in .vscode/mcp.json):

{
  "mcpServers": {
    "parlament-mcp": {
      "command": "uvx",
      "args": [
        "parlament-mcp"
      ]
    }
  }
}

Available Tools

7 tools
parlament_get_businessA
Read-onlyIdempotent

Vollständige Details eines parlamentarischen Vorstosses nach Curia Vista ID abrufen.

Nach einer Suche verwenden, um vollständige Informationen inkl. Ausgangslage, Vorstosstext und Antwort des Bundesrats zu erhalten.

Benötigt die numerische Geschäfts-ID (aus parlament_search_business). found=false bei unbekannter ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNo
urlNo
tagsNo
typeNo
foundNo
titleNo
sourceNo
statusNo
councilNo
licenseNo
departmentNo
descriptionNo
motion_textNo
proceedingsNo
status_dateNo
short_numberNo
submitted_byNo
submitted_textNo
submission_dateNo
initial_situationNo
federal_council_responseNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only, idempotent, non-destructive behavior. The description adds behavioral context beyond annotations by explaining the 'found=false' return value for invalid IDs and the need for a prior search. This adds useful transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise: a single-line purpose, followed by structured XML tags for use case and important notes. Every sentence adds value, and the information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the input (ID), usage context (post-search), and error behavior (found=false). Since an output schema exists, return values do not need explanation. The description is complete for this tool's purpose.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides descriptions for both parameters (business_id and language). The description reinforces the importance of the ID but does not add new semantics for the language parameter. With 0% schema description coverage in the context, the description partially compensates but misses the optional language parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'abrufen' (retrieve) and resource 'Details eines parlamentarischen Vorstosses', and the use case distinguishes it from the sibling tool 'parlament_search_business'. It is specific and action-oriented.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: use after a search to get full details, requires the numeric business ID from search, and notes that 'found=false' is returned for unknown IDs. This clearly tells when and how to use the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parlament_get_sessionsA
Read-onlyIdempotent

Aktuelle parlamentarische Sessionen mit Daten auflisten.

Session-IDs aus dieser Liste zum Filtern von Abstimmungen oder Transkripten verwenden.

Session-Namen können für sehr aktuelle Sessionen null sein – dann die Session-ID verwenden.

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNo
countNo
offsetNo
sourceNo
licenseNo
resultsNo
match_typeNo
provenanceNo
suggestionsNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint, idempotentHint, and nondestructive. The description adds important behavioral context: session names can be null for recent sessions. This goes beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, using a single sentence plus structured XML tags for use case and notes. However, it could be slightly more efficient by integrating the notes into the main text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema exists, the description explains the tool's purpose and a key behavioral note (null names). However, it omits parameter descriptions, which are essential for proper invocation. This is a moderate gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, yet the description does not explain the parameters (limit, offset). It only describes the output, leaving the agent to infer input semantics from the schema alone. This is a significant gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'auflisten' (list) and the resource 'parlamentarische Sessionen' (parliamentary sessions). The use case explicitly mentions using session IDs for filtering votes or transcripts, distinguishing this tool from siblings like get_votes or get_transcripts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear use case for when to use the tool (fetching session IDs for filtering). However, it does not explicitly state when not to use it or mention alternatives, though for a simple listing tool this is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parlament_get_transcriptA
Read-onlyIdempotent

Den vollen Wortlaut eines einzelnen Votums nach Transkript-ID abrufen.

Nach einer Suche mit parlament_search_transcripts den kompletten Wortlaut eines konkreten Votums holen – zitierfähig, mit stabiler URL.

Ausgabe ist gedeckelt (max_chars); bei Kürzung ist is_excerpt=True gesetzt und note/next_offset erklären, wie die Fortsetzung zu laden ist. Kein stilles Kürzen. Der Wortlaut wird nie durch eine Zusammenfassung ersetzt.

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
dateNo
noteNo
textNo
foundNo
groupNo
cantonNo
offsetNo
sourceNo
councilNo
licenseNo
speakerNo
citationNo
functionNo
languageNo
is_excerptNo
provenanceNo
session_idNo
source_urlNo
next_offsetNo
transcript_idNo
business_titleNo
business_numberNo
total_length_charsNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The <important_notes> section discloses non-obvious behavior: the output is capped by max_chars, truncation is signaled by is_excerpt=True, and note/next_offset explain how to load the continuation. It also promises no silent truncation and no summarization, going beyond the readOnly/idempotent annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a lead sentence, a <use_case> block, and an <important_notes> block. Every sentence adds functional value, and the formatting makes it easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-record retrieval tool with rich annotations and an output schema, the description covers what is fetched, when to use it, and the pagination/truncation contract. No return-value documentation is needed because the output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 0%, the description compensates by tying transcript_id to the lookup key and explaining that max_chars caps the response, with is_excerpt/next_offset for continuation. It does not describe the offset parameter directly, but the continuation note implies its role.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource statement: 'Den vollen Wortlaut eines einzelnen Votums nach Transkript-ID abrufen' (retrieve the full wording of a single speech by transcript ID), which clearly distinguishes this tool from the search-oriented siblings. It also names the exact follow-up use case after parlament_search_transcripts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The <use_case> section explicitly says to use this after a search with parlament_search_transcripts to get the complete, quotable wording of a specific Votum. It does not list alternative tools or explicit 'when not to use' exclusions, but the context is clear enough to guide tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parlament_get_votesB
Read-onlyIdempotent

Parlamentarische Abstimmungen (im Rat) mit Ja/Nein-Bedeutung abrufen.

Zeigt, wie der Rat über Themen wie KI-Regulierung, Bildungsfinanzierung oder Digitalisierungsprojekte abgestimmt hat.

meaning_yes/meaning_no erklären, was ein Ja/Nein im konkreten Geschäft bedeutet – wichtig zur korrekten Interpretation.

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNo
countNo
offsetNo
sourceNo
licenseNo
resultsNo
match_typeNo
provenanceNo
suggestionsNo

TDQS

B3.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnly, idempotent, and non-destructive nature. Description adds value by highlighting the importance of 'meaning_yes'/'meaning_no' for correct interpretation, which is not evident from annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is concise with two sentences plus structured use_case and important_notes. No redundancy, but could be more efficient by integrating note into main text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has an output schema, return values need not be explained. However, parameter semantics are missing and usage context is sparse. For a simple retrieval tool, it is incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, meaning parameters lack descriptions in the schema. The tool description does not explain any parameters (limit, offset, keyword, session_id), relying solely on the schema which is insufficient.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves parliamentary votes with yes/no meaning, using specific verb 'abrufen' and resource 'Abstimmungen'. Use case examples differentiate from siblings like get_sessions or get_business.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives like parlament_search_business or when not to use it. The use case provides context but lacks comparative direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parlament_search_businessA
Read-onlyIdempotent

Parlamentarische Vorstösse suchen (Motionen, Interpellationen, Postulate usw.).

Durchsucht Curia Vista Geschäftsdaten von ws.parlament.ch.

Politische Recherche zu Bildungs-, Datenschutz- oder Verwaltungsthemen; hängige Vorstösse zu KI in der Bildung, Digitalisierungsinitiativen oder beliebigen Politikthemen finden.

Titel-Suche via OData substringof() (gross-/klein-sensitiv). Maximal 100 Treffer pro Aufruf; mit offset paginieren.

keyword='KI', keyword2='Schule', status='Eingereicht'

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNo
countNo
offsetNo
sourceNo
licenseNo
resultsNo
match_typeNo
provenanceNo
suggestionsNo

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint, idempotentHint, and destructiveHint=false. The description adds critical behavioral details beyond annotations: case-sensitive OData substringof search, maximum 100 results per call, and pagination via offset. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with tags for use_case, important_notes, and example. It is concise (around 4 sentences plus tags) and front-loaded with the main purpose. Minor verbosity from tags but overall effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, the description adequately covers use cases, important technical notes (case sensitivity, pagination), and provides an example. It is complete enough for a search tool with well-documented parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already has detailed descriptions for each parameter (limit, offset, status, etc.), so the description adds minimal additional semantic value. It mentions OData substringof for title search but does not explain each parameter beyond the schema. Baseline 3 is appropriate given schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the purpose: searching parliamentary business (motions, interpellations, etc.) in German. It distinguishes itself from sibling tools like parlament_get_business (for single business) and other search/get tools for sessions, transcripts, votes, and members.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes a use_case tag with specific political research topics, providing clear context for when to use the tool. It does not explicitly state when not to use it, but the sibling tools are distinct enough to imply alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parlament_search_membersA
Read-onlyIdempotent

National- und Ständeräte suchen.

Alle Zürcher Ratsmitglieder ('ZH') oder Mitglieder einer bestimmten Partei finden. Synergie: mit parlament_search_business kombinieren, um Urheber von Vorstössen zu identifizieren.

active_only=True (Default) liefert nur amtierende Mitglieder. Kanton als 2-Buchstaben-Kürzel.

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNo
countNo
offsetNo
sourceNo
licenseNo
resultsNo
match_typeNo
provenanceNo
suggestionsNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, confirming safe read operation. The description adds behavioral detail beyond annotations by specifying the default active_only=True behavior and canton format, though it omits pagination details which are covered by the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with a single sentence, a use case tag, and important notes tag. No wasted words; all content is valuable and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the seven parameters and presence of an output schema, the description covers the main purpose, typical use cases, and key behavior. It lacks explanation of offset/limit but those are standard and schema-defined. Overall adequate for a search tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds moderate value over the schema: it reinforces canton format and active_only default, but the schema already provides adequate descriptions for all parameters (e.g., party, council, last_name). With 0% overall schema description coverage, the tool description compensates partially but not heavily.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool searches for members of National and Ständeräte, and distinguishes from siblings by mentioning synergy with parlament_search_business for identifying motion authors. The use case example reinforces the purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage scenarios (finding all Zurich members or members of a party) and notes important defaults and format requirements (active_only=True, canton as 2-letter code). It also guides users to combine with a sibling tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parlament_search_transcriptsA
Read-onlyIdempotent

Wörtliche Wortmeldungen aus den Ratsdebatten durchsuchen (Amtliches Bulletin).

Liefert kurze, zitierfähige Auszüge (kein Volltext) mit korrekter AB-Zitation und stabiler Quell-URL. Für den Wortlaut eines einzelnen Votums danach parlament_get_transcript(transcript_id=…) verwenden.

«Was hat Nationalrätin X in der Frühjahrssession 2024 zur Volksschule gesagt?» – Sprecher, Session, Rat, Geschäft oder Datumsfenster kombinieren. Synergie mit fedlex-mcp: vom Gesetzestext zur Debatte.

Nur echte Wortmeldungen (keine Abstimmungszeilen). Der Language-Filter dedupliziert die Editionen und blendet keine französisch-/italienischsprachigen Voten aus – die reale Sprache steht in language. Abdeckung ab 1999-12-06. Für beste Latenz session_id, business_number oder ein Datumsfenster mit einem freien keyword kombinieren.

speaker_name='Munz', session_id=5202, keyword='Volksschule'

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNo
countNo
offsetNo
sourceNo
editionNo
licenseNo
resultsNo
match_typeNo
provenanceNo
suggestionsNo
citation_noteNo
language_noteNo
coverage_sinceNo
full_text_hintNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark readOnlyHint=true and idempotentHint=true, but the description adds substantial behavioral detail beyond that: it returns only real spoken contributions (not voting lines), explains that the Language filter deduplicates editions but does not hide French/Italian votes, and states coverage starts at 1999-12-06. These are valuable context for the agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with distinct sections (main statement, return format, pointer to related tool, use_case, important_notes, example). Every sentence adds value: the limitation of excerpts, the language filter behavior, coverage start, and a concrete example. It is detailed but not bloated, and the front-loaded purpose sentence is immediately clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the essential aspects for a search tool: what it searches, what it returns (short quotable extracts with citation and stable URL), what it does not return (full text), which sibling to use next, scope limitations, and coverage date. It also addresses the Language filter nuance. Given the output schema exists and the input schema has detailed per-parameter descriptions, this is fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

While the description does not individually document each parameter, the input schema itself provides thorough descriptions for all nested properties (limit, offset, council, dates, keyword, session_id, speaker_name, business_number). The tool description adds practical usage meaning via the example (speaker_name='Munz', session_id=5202, keyword='Volksschule') and latency guidance for combining parameters, which goes beyond raw schema listings.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource: 'Wörtliche Wortmeldungen aus den Ratsdebatten durchsuchen (Amtliches Bulletin)' – clearly searching verbatim contributions in council debates. It further distinguishes itself from siblings by stating it returns 'kurze, zitierfähige Auszüge (kein Volltext)' and explicitly redirects to parlament_get_transcript for the full text of a single vote.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance: use this tool for search/snippets, then call parlament_get_transcript for the exact full wording. It also gives a concrete use case and performance tips (combine session_id, business_number, or a date window with a free keyword for best latency), plus notes about synergie with fedlex-mcp.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.3.4
    • Addedparlament_get_transcript
    • Removedparlament_get_transcripts
    • Addedparlament_search_transcripts
  2. 6 tool updatesv0.3.3
    • First observedparlament_get_business
    • First observedparlament_get_sessions
    • First observedparlament_get_transcripts
    • First observedparlament_get_votes
    • First observedparlament_search_business
    • First observedparlament_search_members

TDQS

A4.1/5.0

Scored across 7 tools

Disambiguation5/5

Each tool targets a distinct resource and action: search vs. get, and business/transcripts/members/votes/sessions are clearly separated. The two search tools return different entity types, and the two get tools are distinguished by ID and purpose.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern with 'search_' for queries and 'get_' for retrievals. No mixed conventions or vague verbs.

Tool Count5/5

Seven tools cover the core parliamentary data domain without bloat. Each tool has a clear, non-redundant role, and the count is within the ideal 3-15 range.

Completeness4/5

The set covers search and retrieval for proposals, transcripts, members, votes, and sessions, which are the main entities. Minor gaps include no direct get_member by ID and no committee data, but agents can work around these with search_members and get_votes.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    MCP server for Portuguese Parliament open data, enabling AI agents to access legislative initiatives, deputies, plenary votes, petitions, and parliamentary committees.
    12
    7 npm
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    An MCP server that connects AI models to the Lobbywatch.ch database, providing access to Swiss parliamentarians' conflicts of interest, lobby groups, access badges, and transparency scores.
    8
    25 PyPI
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    An MCP server providing AI-powered access to Open Data from the City of Zurich, enabling queries to 900+ datasets, real-time environmental and mobility data, geodata, parliamentary proceedings, and more.
    26
    8
    MIT