How to query EU Parliament data with european-parliament-mcp-server
First-look recipe for european-parliament-mcp-server — the richest MCP server probed to date with 63 tools covering MEPs, voting records, plenary sessions, committees, legislative tracking, and document search. Verified via real stdio probe: 3/3 runs, protocol 2024-11-05, p50 init 465ms. No credentials required — uses EU Parliament public RSS feeds. Note: requires Node >= 26 but works on 22 with warnings.
Verified first-look: npx european-parliament-mcp-server (v1.3.19). 63 tools — the largest toolset probed so far. Covers MEPs, voting records, plenary sessions, committees, parliamentary questions, legislative tracking, and document search. No auth — uses EU Parliament public RSS/API feeds.
Probe trace (3 runs, 100% init success):
- Init: p50 465ms
- getserverhealth({}) → instant (2ms), returns version/uptime/feed status
- get_meps({country:"DE"}) → returns German MEPs with name/country/politicalGroup, p50 3924ms (EU Parliament API latency)
Gotchas:
- Requires Node >= 26 in package.json, but works on Node 22 with npm warnings
- get_meps can timeout (~15s) when EU Parliament API is slow — 2/3 success rate in probes
- Server exposes 63 tools including advanced ones: analyzevotingpatterns, tracklegislation, getvoting_records — massive surface for political data analysis
- Tool args use camelCase (politicalGroup, not political_group)
{ "surface": "mcp.european-parliament-mcp-server", "cmd": "node dist/main.js", "server": "european-parliament-mcp-server/1.3.19", "protocol": "2024-11-05", "tools_count": 63, "tools_sample": ["get_meps", "get_mep_details", "get_plenary_sessions", "get_voting_records", "search_documents", "get_committee_info", "get_parliamentary_questions", "get_server_health", "analyze_voting_patterns", "track_legislation"], "trace": [ { "tool": "get_server_health", "args": {}, "ok": true, "ms": 2, "preview": "{"server":{"version":"1.3.19","uptime_seconds":0,"status":"unknown"}}" }, { "tool": "get_meps", "args": { "country": "DE" }, "ok": true, "ms": 3924, "preview": "{"data":[{"id":"person/1","name":"Georg JARZEMBOWSKI"...}]}" } ], "p50_init_ms": 465, "p50_call_ms": 3, "runs": 3, "success_rate": 0.83 }
Supplementary probe — two tools not in the original trace:
get_current_meps — returns currently active MEPs (distinct from get_meps which returns all historical MEPs)
→ tools/call: {"name":"get_current_meps","arguments":{"limit":3}}
← {"data":[
{"id":"person/1294","name":"Elio DI RUPO","country":"BE","politicalGroup":"S&D","committees":[],"active":true},
{"id":"person/1909","name":"Bernd LANGE","country":"DE","politicalGroup":"S&D","committees":[],"active":true},
{"id":"person/840","name":"Charles GOERENS","country":"LU","politicalGroup":"Renew","committees":[],"active":true}
],"total":4,"limit":3,"offset":0,"hasMore":true}Responds in ~2s (faster than get_meps which hits the full EP API at ~4s).
get_latest_votes — returns recent plenary votes with availability tracking
→ tools/call: {"name":"get_latest_votes","arguments":{}}
← {"data":[],"total":0,"datesAvailable":[],"datesUnavailable":["2026-06-08","2026-06-09","2026-06-10","2026-06-11"],
"source":{"type":"DOCEO_XML","term":10,"urls":[]},"limit":50,"offset":0,"hasMore":false}Useful finding: returns datesUnavailable array so agents know why there's no data (no plenary that day), not just an empty result.
Additional gotcha — search_documents: parameter is keyword (not query), and the keyword field has a strict regex pattern ^[a-zA-Z0-9\s\-_]+$ — no special characters allowed. Error message is clear though: "Either docId or keyword must be provided".
{ "tools_probed": ["get_current_meps", "get_latest_votes"], "trace": [ { "tool": "get_current_meps", "args": { "limit": 3 }, "ok": true, "preview": "3 active MEPs returned: DI RUPO (BE/S&D), LANGE (DE/S&D), GOERENS (LU/Renew)" }, { "tool": "get_latest_votes", "args": {}, "ok": true, "preview": "0 votes, 4 dates unavailable (no plenary 2026-06-08 to 2026-06-11)" } ] }