eu-parliament-mcp-server

v0.1.1 pre-1.0

Track European Parliament procedures, MEPs, votes, documents, speeches, and questions via MCP. STDIO or Streamable HTTP.

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

Tools

9

euparl_list_reference

open-world

List parliamentary codes, identifier formats, committees, political groups, and coverage limitations. Choose topic to discover accepted filter values before calling another euparl tool. Committees and political groups are live bodies; organization identifiers are not inferred filter codes. Continue with page.next_offset; these lists do not require snapshots.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_list_reference",
    "arguments": {
      "topic": "<topic>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "topic": {
      "type": "string",
      "enum": [
        "committees",
        "political_groups",
        "procedure_types",
        "document_types",
        "question_types",
        "activity_types",
        "mep_filters",
        "identifiers",
        "coverage"
      ],
      "description": "Reference topic to list."
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    }
  },
  "required": [
    "topic",
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

euparl_list_procedures

open-world

List procedure references by procedure type. Titles, stages, and participants require euparl_get_procedure with a returned procedure_id. Use euparl_list_reference topic procedure_types for supported process_type codes. No keyword, year, committee, or stage filter is available; continue with page.next_offset.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_list_procedures",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "process_type": {
      "description": "Optional procedure-type code from euparl_list_reference topic procedure_types; case-insensitive and whitespace-trimmed.",
      "type": "string"
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    }
  },
  "required": [
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

euparl_get_procedure

open-world

Read a procedure title, stage, events, participants, or linked parliamentary documents. Default section overview returns scalar fields and collection counts; events, participants, and documents page one selected collection. Continue with page.next_offset and the returned snapshot; restart at offset 0 without snapshot if the collection changes. Historical participation groups remain historical. Missing detail succeeds with found false; discover references with euparl_list_procedures. Linked documents can be read with euparl_search_documents mode get; files are linked, not parsed.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_get_procedure",
    "arguments": {
      "procedure_id": "<procedure_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "procedure_id": {
      "type": "string",
      "minLength": 1,
      "pattern": "^(?:https:\\/\\/data\\.europarl\\.europa\\.eu\\/eli\\/dl\\/proc\\/|eli\\/dl\\/proc\\/)?\\d{4}[-/]\\d{4}[A-Z]?(?:\\([A-Z]+\\))?$",
      "description": "Procedure YYYY-NNNN or YYYY/NNNN, optional letter suffix and (TYPE), known eli/dl/proc/ prefix or exact public procedure URI."
    },
    "section": {
      "default": "overview",
      "description": "Default overview returns scalars and counts; choose a collection for complete paged items.",
      "type": "string",
      "enum": [
        "overview",
        "events",
        "participants",
        "documents"
      ]
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    },
    "snapshot": {
      "description": "Previous collection snapshot; required for local offset above 0, optional at offset 0.",
      "type": "string"
    }
  },
  "required": [
    "procedure_id",
    "section",
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

euparl_search_documents

open-world

Search adopted texts, committee documents, or plenary documents, then retrieve metadata and source-file links with mode get and document_id. Get accepts IDs from procedures, speeches, votes, questions and answers without a source family; parent_document_ids lead from subdivisions to parent files. Only adopted_texts supports text, title, sitting dates and related_process_id. Committee supports term but no year; plenary supports year but no term. Use euparl_list_reference topic document_types for family-specific work_type codes. Detail returns links, not extracted full text; continue search with page.next_offset.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_search_documents",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "search",
      "description": "Default search discovers records; get requires document_id and rejects source and all search filters.",
      "type": "string",
      "enum": [
        "search",
        "get"
      ]
    },
    "source": {
      "description": "Search-only family; omitted search defaults to adopted_texts. Omit entirely in get mode.",
      "type": "string",
      "enum": [
        "adopted_texts",
        "committee",
        "plenary"
      ]
    },
    "document_id": {
      "description": "Get-only canonical work ID, eli/dl/doc/ prefix or exact public URI; no family restriction.",
      "type": "string"
    },
    "text": {
      "description": "Adopted-texts-only keyword search in the requested language.",
      "type": "string"
    },
    "title": {
      "description": "Adopted-texts-only title search in the requested language.",
      "type": "string"
    },
    "year": {
      "description": "Four-digit document year; adopted_texts and plenary search only.",
      "type": "integer",
      "minimum": 1000,
      "maximum": 9999
    },
    "term": {
      "description": "Parliamentary term 0–10; adopted_texts and committee search only.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10
    },
    "work_type": {
      "description": "Search-only family-specific code from euparl_list_reference topic document_types; case-insensitive and whitespace-trimmed.",
      "type": "string"
    },
    "sitting_date": {
      "description": "Adopted-texts-only sitting date YYYY-MM-DD; start of range when sitting_date_end is supplied.",
      "type": "string"
    },
    "sitting_date_end": {
      "description": "Adopted-texts-only inclusive range end YYYY-MM-DD; requires sitting_date and must not precede it.",
      "type": "string"
    },
    "related_process_id": {
      "description": "Adopted-texts-only procedure reference YYYY-NNNN, YYYY/NNNN(TYPE), known prefix or public URI.",
      "type": "string"
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    }
  },
  "required": [
    "mode",
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

euparl_search_speeches

open-world

Search speech activities in the tenth parliamentary term or retrieve one with mode get and speech_id. Text and title search return activity metadata, not transcripts. Follow document_ids with euparl_search_documents mode get and any returned parent_document_ids to source files. Use euparl_list_reference topic activity_types for activity_type codes; older-term search is unavailable. Get rejects search filters and nondefault paging; continue search with page.next_offset.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_search_speeches",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "search",
      "description": "Default search discovers speech activities; get requires speech_id and rejects search filters.",
      "type": "string",
      "enum": [
        "search",
        "get"
      ]
    },
    "speech_id": {
      "description": "Get-only canonical activity ID, eli/dl/event/ prefix or exact public URI.",
      "type": "string"
    },
    "text": {
      "description": "Search-only keywords in the selected language; matching does not guarantee transcript output.",
      "type": "string"
    },
    "title": {
      "description": "Search-only published activity title keywords in the selected language.",
      "type": "string"
    },
    "person_id": {
      "description": "Search-only numeric MEP identifier, person/ prefix or exact public person URI.",
      "type": "string"
    },
    "activity_type": {
      "description": "Search-only code from euparl_list_reference topic activity_types; case-insensitive and whitespace-trimmed.",
      "type": "string"
    },
    "sitting_date": {
      "description": "Search-only sitting date YYYY-MM-DD; start date when a range end is supplied.",
      "type": "string"
    },
    "sitting_date_end": {
      "description": "Search-only inclusive end date YYYY-MM-DD; requires sitting_date and cannot precede it.",
      "type": "string"
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    }
  },
  "required": [
    "mode",
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

euparl_search_meps

open-world

Find MEPs by name, country, political group, gender, or parliamentary term. Omitted term selects members in office today; explicit term selects that published term roster. Name matching requires every normalized token after case, diacritic, and punctuation normalization over the complete roster before paging. Country and group describe roster context, never voting-date affiliation. Continue with page.next_offset and snapshot; restart at offset 0 without snapshot after snapshot_changed. Read identity and membership history with euparl_get_mep. Empty matches succeed with guidance.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_search_meps",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name_contains": {
      "description": "All-token name filter over the complete selected roster; case, diacritics, and punctuation are normalized, without fuzzy scoring.",
      "type": "string"
    },
    "term": {
      "description": "Parliamentary term 0–10; omitted selects members in office today.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10
    },
    "country": {
      "description": "Supported ISO alpha-2 country code, case-insensitive; UK is historical. See euparl_list_reference topic mep_filters.",
      "type": "string"
    },
    "political_group": {
      "description": "Supported political group code, case-insensitive; accepts S&D, Verts/ALE, The Left, Renew, and PfE aliases. See euparl_list_reference topic mep_filters.",
      "type": "string"
    },
    "gender": {
      "description": "Supported gender code FEMALE, MALE, NAP, NKN, or NST, case-insensitive.",
      "type": "string"
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    },
    "snapshot": {
      "description": "Returned roster snapshot; required for offset above 0, optional at offset 0.",
      "type": "string"
    }
  },
  "required": [
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

euparl_get_mep

open-world

Read an MEP identity or membership history including published committee, delegation, and political-group records. Default section overview returns identity and membership_count; section memberships pages full membership records. Missing end dates do not establish current membership. Continue memberships with page.next_offset and snapshot; restart at offset 0 without snapshot after snapshot_changed. Missing detail succeeds with found false; discover IDs with euparl_search_meps.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_get_mep",
    "arguments": {
      "mep_id": "<mep_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mep_id": {
      "type": "string",
      "minLength": 1,
      "pattern": "^(?:https:\\/\\/data\\.europarl\\.europa\\.eu\\/person\\/|person\\/)?\\d+$",
      "description": "Decimal person ID, person/ prefix, or exact https://data.europarl.europa.eu/person/ URI."
    },
    "section": {
      "default": "overview",
      "description": "Default overview returns identity and membership count; memberships returns the selected history page.",
      "type": "string",
      "enum": [
        "overview",
        "memberships"
      ]
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    },
    "snapshot": {
      "description": "Returned membership snapshot; required for membership offset above 0, optional at offset 0.",
      "type": "string"
    }
  },
  "required": [
    "mep_id",
    "section",
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

euparl_get_plenary_votes

open-world

Discover sittings with mode sittings and year; default decisions pages compact summaries for sitting_id. Mode decision requires decision_id and returns one rich record with whole labels, reference text, commentary, and document references; it rejects nondefault paging and snapshot. Mode voters requires decision_id and one position, paging recorded and intended voters independently. Missing arrays succeed with available false; published empty arrays have available true. Optional resolve_names requires explicit roster_term and joins only published names from that complete term roster, never voting-date affiliations or current-roster substitutes. Some IDs may remain unresolved. Continue local decisions or voters with page.next_offset and snapshot; restart at offset 0 without snapshot after snapshot_changed. Missing sitting decisions succeed empty; absent selected decision fails decision_not_found.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_get_plenary_votes",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "decisions",
      "description": "Default decisions returns compact summaries; sittings discovers by year, decision returns one rich record, voters pages one position.",
      "type": "string",
      "enum": [
        "sittings",
        "decisions",
        "decision",
        "voters"
      ]
    },
    "year": {
      "description": "Four-digit year, required only for sittings and forbidden in other modes.",
      "type": "integer",
      "minimum": 1000,
      "maximum": 9999
    },
    "sitting_id": {
      "description": "Required outside sittings: real YYYY-MM-DD date, MTG-PL-YYYY-MM-DD, known event prefix, or exact public event URI.",
      "type": "string",
      "minLength": 1,
      "pattern": "^(?:https:\\/\\/data\\.europarl\\.europa\\.eu\\/eli\\/dl\\/event\\/|eli\\/dl\\/event\\/)?(?:MTG-PL-)?\\d{4}-\\d{2}-\\d{2}$"
    },
    "decision_id": {
      "description": "Required for decision and voters: exact returned canonical decision ID, known eli/dl/event/ prefix, or exact public event URI; forbidden for sittings and decisions.",
      "type": "string",
      "minLength": 1,
      "pattern": "^(?:https:\\/\\/data\\.europarl\\.europa\\.eu\\/eli\\/dl\\/event\\/|eli\\/dl\\/event\\/)?[A-Za-z0-9][A-Za-z0-9_-]*$"
    },
    "position": {
      "description": "Required only for voters: favor, against, abstention, intended_favor, intended_against, or intended_abstention.",
      "type": "string",
      "enum": [
        "favor",
        "against",
        "abstention",
        "intended_favor",
        "intended_against",
        "intended_abstention"
      ]
    },
    "resolve_names": {
      "default": false,
      "description": "Default false retains IDs only; true is voters-only and requires roster_term for complete names-only roster resolution.",
      "type": "boolean"
    },
    "roster_term": {
      "description": "Explicit parliamentary term 0–10 containing the sitting; required with resolve_names true, forbidden otherwise. No term is inferred from dates.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    },
    "snapshot": {
      "description": "Returned decisions or voter-position snapshot; required for local offset above 0, optional at offset 0; forbidden for sittings and decision.",
      "type": "string"
    }
  },
  "required": [
    "mode",
    "resolve_names",
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

euparl_list_questions

open-world

List parliamentary questions by year and work_type or retrieve metadata, source-file links and published answers with mode get and question_id. Human citations such as E-000001/2025 retain their full year; supplying term resolves directly, while omission searches the complete year catalogue and requires an unambiguous exact match. Canonical IDs bypass that scan. Use euparl_list_reference topic question_types for work_type codes. No keyword, author or addressee search is available. Empty answers means no answer relation was published in this response. Get rejects list filters and nondefault paging; continue lists with page.next_offset.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "euparl_list_questions",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "list",
      "description": "Default list discovers questions; get requires question_id and forbids year and work_type.",
      "type": "string",
      "enum": [
        "list",
        "get"
      ]
    },
    "year": {
      "description": "List-only four-digit question year.",
      "type": "integer",
      "minimum": 1000,
      "maximum": 9999
    },
    "work_type": {
      "description": "List-only question code from euparl_list_reference topic question_types; case-insensitive and whitespace-trimmed.",
      "type": "string"
    },
    "question_id": {
      "description": "Get-only canonical E-{term}-{year}-{six-digit-sequence}, known document prefix/public URI, or human E-NNNNNN/YYYY citation; corresponding P/O prefixes are accepted.",
      "type": "string"
    },
    "term": {
      "description": "Get-only term 0–10 to disambiguate a human citation; must agree with a canonical ID. Omit to scan the entire citation year without inferring term.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10
    },
    "offset": {
      "default": 0,
      "description": "Zero-based collection offset; default 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Whole items requested; default 20, effective maximum 100 with notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "language": {
      "description": "Supported EU ISO-639-1 language, case-insensitive; default en; source text is never translated.",
      "type": "string"
    }
  },
  "required": [
    "mode",
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗