@cyanheads/eur-lex-mcp-server

v0.1.3 pre-1.0

Search EU legislation, CJEU case law, and treaties; traverse the CELLAR relationship graph; resolve EuroVoc concepts via MCP. STDIO or Streamable HTTP.

@cyanheads/eur-lex-mcp-server
claude mcp add --transport http eur-lex-mcp-server https://eur-lex.caseyjhand.com/mcp
codex mcp add eur-lex-mcp-server --url https://eur-lex.caseyjhand.com/mcp
{
  "mcpServers": {
    "eur-lex-mcp-server": {
      "url": "https://eur-lex.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http eur-lex-mcp-server https://eur-lex.caseyjhand.com/mcp
{
  "mcpServers": {
    "eur-lex-mcp-server": {
      "command": "bunx",
      "args": [
        "@cyanheads/eur-lex-mcp-server@latest"
      ]
    }
  }
}
{
  "mcpServers": {
    "eur-lex-mcp-server": {
      "type": "http",
      "url": "https://eur-lex.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://eur-lex.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

7

eurlex_lookup_celex

open-world

Resolve any EU legal citation — CELEX number, ELI URI, or Official Journal reference — to the canonical CELLAR work. Returns the work URI, confirmed CELEX number, document type, document date, and whether the work exists in the CELLAR corpus. Use this to validate identifiers before passing them to eurlex_get_document or eurlex_get_relations. CELEX format: {sector}{year}{type}{number} e.g. 32016R0679 (GDPR). ELI format: http://data.europa.eu/eli/{type}/{year}/{number}/oj. OJ format: OJ L 119 or L:2016:119.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "eurlex_lookup_celex",
    "arguments": {
      "identifier": "<identifier>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "identifier": {
      "type": "string",
      "minLength": 1,
      "description": "The EU legal citation to resolve: a CELEX number (e.g. 32016R0679), ELI URI, or Official Journal reference (e.g. OJ L 119)."
    },
    "identifier_type": {
      "default": "auto",
      "description": "Format of the identifier. Use \"auto\" to let the server detect the format automatically. Supply explicitly if auto-detection fails or if the identifier is ambiguous.",
      "type": "string",
      "enum": [
        "celex",
        "eli",
        "oj",
        "auto"
      ]
    }
  },
  "required": [
    "identifier",
    "identifier_type"
  ],
  "additionalProperties": false
}
view source ↗

eurlex_browse_subjects

open-world

Search the EuroVoc multilingual thesaurus to resolve a human-readable term or keyword into EuroVoc concept IDs. This tool is required before using the eurovoc_concept filter in eurlex_search_documents — agents cannot guess numeric EuroVoc concept IDs. Returns concept URI, preferred label in the requested language, concept code, and broader/narrower hierarchy hints. EuroVoc covers all EU policy domains: agriculture, environment, finance, health, trade, transport, and more. If no results are found in a non-English language, retry with language "en" and a broader English term.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "eurlex_browse_subjects",
    "arguments": {
      "keyword": "<keyword>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "keyword": {
      "type": "string",
      "minLength": 1,
      "description": "Search term to match against EuroVoc concept labels (e.g. \"privacy\", \"agriculture\", \"trade\")."
    },
    "language": {
      "default": "en",
      "description": "Language code for concept labels (e.g. \"en\", \"fr\", \"de\"). Defaults to English.",
      "type": "string",
      "pattern": "^[a-z]{2,3}$"
    },
    "limit": {
      "default": 20,
      "description": "Maximum number of EuroVoc concepts to return (1–50). Defaults to 20.",
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    }
  },
  "required": [
    "keyword",
    "language",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

eurlex_search_documents

open-world

Search EU legislation, treaties, and preparatory acts across the CELLAR corpus of 2.7M+ works. Filters by document type, date range, EuroVoc subject concept, author institution, and in-force status. Keyword search matches against English expression titles and CELEX strings — full-text body search is not available via this API. For multi-word searches, supply a single dominant keyword; use other filters to narrow results. Returns CELEX numbers, work URIs, human-readable document type labels, and dates — use these with eurlex_get_document to fetch full content. To filter by EuroVoc subject, first call eurlex_browse_subjects to obtain the concept URI. Case law (CJEU/GC judgments) is better searched via eurlex_get_cases which has court-specific parameters.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "eurlex_search_documents",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "keyword": {
      "description": "Keyword to match against document titles. Single dominant word recommended; multi-word phrase uses substring match.",
      "type": "string"
    },
    "document_type": {
      "description": "Document type filter: REG=Regulation, DIR=Directive, DEC=Decision, TREATY=Treaty, JUDG=Judgment, OPIN_AG=AG Opinion, PROP=Proposal, REC=Recommendation.",
      "type": "string",
      "enum": [
        "REG",
        "DIR",
        "DEC",
        "TREATY",
        "JUDG",
        "OPIN_AG",
        "PROP",
        "REC"
      ]
    },
    "date_from": {
      "description": "Start of date range in ISO 8601 format (YYYY-MM-DD). Matches document date.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "date_to": {
      "description": "End of date range in ISO 8601 format (YYYY-MM-DD). Matches document date.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "eurovoc_concept": {
      "description": "EuroVoc concept URI to filter by subject (e.g. http://eurovoc.europa.eu/2828). Obtain concept URIs from eurlex_browse_subjects first.",
      "type": "string",
      "pattern": "^http.*"
    },
    "author_institution": {
      "description": "Author institution name filter (e.g. \"European Parliament\", \"Council\"). Substring match.",
      "type": "string"
    },
    "in_force": {
      "description": "If true, restrict to acts currently in force. Omit to return all regardless of in-force status.",
      "type": "boolean"
    },
    "offset": {
      "default": 0,
      "description": "Pagination offset — number of results to skip. Defaults to 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Maximum number of results to return (1–100). Defaults to 20.",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    }
  },
  "required": [
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

eurlex_get_cases

open-world

Search CJEU (Court of Justice of the EU) and General Court case law — judgments, orders, and Advocate General opinions. Distinct from eurlex_search_documents because case law uses CELEX sector 6 and practitioners search it differently: by case number, court, party name, or AG opinion type. Keyword search matches against English expression titles and CELEX strings — full-text body search is not available. Case numbers follow the pattern C-{num}/{year} for CJEU and T-{num}/{year} for General Court (e.g. C-131/12). Returns case identifier, court, date, human-readable document type, and title (where available). Use eurlex_get_document with the CELEX number to fetch the full judgment text.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "eurlex_get_cases",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "case_number": {
      "description": "Case number in standard format: C-{num}/{year} for CJEU or T-{num}/{year} for General Court (e.g. C-131/12).",
      "type": "string"
    },
    "keyword": {
      "description": "Keyword to match against case titles and CELEX strings.",
      "type": "string"
    },
    "court": {
      "description": "Court filter: CJEU = Court of Justice of the EU, GC = General Court.",
      "type": "string",
      "enum": [
        "CJEU",
        "GC"
      ]
    },
    "case_type": {
      "description": "Case type filter: judgment, order (procedural decision), or ag_opinion (Advocate General opinion).",
      "type": "string",
      "enum": [
        "judgment",
        "order",
        "ag_opinion"
      ]
    },
    "date_from": {
      "description": "Start of date range in ISO 8601 format (YYYY-MM-DD).",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "date_to": {
      "description": "End of date range in ISO 8601 format (YYYY-MM-DD).",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "offset": {
      "default": 0,
      "description": "Pagination offset — number of results to skip. Defaults to 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Maximum number of results to return (1–100). Defaults to 20.",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    }
  },
  "required": [
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

eurlex_get_document

open-world

Fetch the notice (metadata) and full text of an EU act by CELEX number or ELI URI. Returns structured metadata — title, date, document type, author institution, legal basis, EuroVoc subjects — plus the HTML or Formex4 XML content in the requested language. Defaults to English (EN); not all works have content in all 24 official EU languages, especially older acts pre-2004 EU enlargement. If the requested language is unavailable, the server automatically falls back to English and notes the fallback. CELEX format: {sector}{year}{type}{number} e.g. 32016R0679 for GDPR. Use eurlex_lookup_celex to validate an identifier before calling this tool. HTML format returns the full act text suitable for reading; XML returns Formex4 for structured processing.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "eurlex_get_document",
    "arguments": {
      "celex_number": "<celex_number>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "celex_number": {
      "type": "string",
      "minLength": 1,
      "description": "CELEX number of the act to fetch (e.g. 32016R0679 for GDPR). Preferred over eli_uri."
    },
    "eli_uri": {
      "description": "ELI URI as alternative to celex_number (e.g. http://data.europa.eu/eli/reg/2016/679/oj). Used only if celex_number is absent or empty.",
      "type": "string"
    },
    "language": {
      "default": "EN",
      "description": "Language code for document content (ISO 639-1 uppercase, e.g. EN, FR, DE). Defaults to EN. Falls back to EN if the requested language is unavailable.",
      "type": "string",
      "pattern": "^[A-Za-z]{2,3}$"
    },
    "format": {
      "default": "html",
      "description": "Content format: \"html\" for readable HTML text (default), \"xml\" for Formex4 XML structured format.",
      "type": "string",
      "enum": [
        "html",
        "xml"
      ]
    }
  },
  "required": [
    "celex_number",
    "language",
    "format"
  ],
  "additionalProperties": false
}
view source ↗

eurlex_get_relations

open-world

Traverse the CELLAR CDM relationship graph for an EU work: what it amends, what amends it, its current consolidated version, its legal basis, and works that cite it. This is CELLAR's primary value over HTML scraping — the graph traversal that exposes the lifecycle and dependencies of an EU act. Returns one-hop direct relations only. For deeper traversal, use eurlex_query_sparql. The "consolidated_version" relation links to the current consolidated text (a separate CELEX-numbered work); fetch that work with eurlex_get_document. Requires a valid CELEX number or CELLAR work URI — use eurlex_lookup_celex to resolve identifiers first.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "eurlex_get_relations",
    "arguments": {
      "celex_number": "<celex_number>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "celex_number": {
      "type": "string",
      "minLength": 1,
      "description": "CELEX number of the work to traverse (e.g. 32016R0679). Preferred identifier."
    },
    "work_uri": {
      "description": "CELLAR work URI as alternative to celex_number. Used if celex_number resolves to no work.",
      "type": "string"
    },
    "relation_types": {
      "description": "Subset of relation types to return. Omit to return all types: cites (citation graph), amends (what this work amends), amended_by (what amends this work), legal_basis (treaty/treaty article this act is based on), consolidated_version (current consolidated text).",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "cites",
          "amends",
          "amended_by",
          "legal_basis",
          "consolidated_version"
        ]
      }
    }
  },
  "required": [
    "celex_number"
  ],
  "additionalProperties": false
}
view source ↗

eurlex_query_sparql

open-world

Execute a raw SPARQL SELECT query against the CELLAR Virtuoso endpoint. Use only when the curated tools (eurlex_search_documents, eurlex_get_relations, etc.) do not cover the needed traversal. The server caps all queries at 100 results — include an explicit LIMIT in your query to control the count; if omitted or above 100 it will be injected or capped automatically. The CDM ontology prefix is prepended automatically: cdm: = http://publications.europa.eu/ontology/cdm#. Also auto-includes skos: and xsd: prefixes. Requires familiarity with the CELLAR CDM ontology. Key predicates: cdm:resource_legal_id_celex (CELEX number), cdm:work_date_document (date), cdm:work_has_resource-type (document type), cdm:work_is_about_concept_eurovoc (EuroVoc subject), cdm:work_cites_work (citation). Virtuoso does not support bif:contains for multi-word phrases; use FILTER(CONTAINS(LCASE(?title), "keyword")).

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "eurlex_query_sparql",
    "arguments": {
      "sparql_query": "<sparql_query>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "sparql_query": {
      "type": "string",
      "minLength": 10,
      "description": "A SPARQL SELECT query to execute against CELLAR. The cdm:, skos:, and xsd: prefixes are auto-injected. LIMIT is injected at 100 if absent or capped to 100 if above that threshold."
    },
    "timeout_hint": {
      "description": "Optional client-side timeout hint in milliseconds (1000–55000). Defaults to server-configured SPARQL_QUERY_TIMEOUT_MS (55000). Virtuoso hard limit is 60 seconds.",
      "type": "integer",
      "minimum": 1000,
      "maximum": 55000
    }
  },
  "required": [
    "sparql_query"
  ],
  "additionalProperties": false
}
view source ↗

Resources

2

Metadata snapshot for a CELLAR work identified by CELEX number. Returns document type, date, title (where available), author institution, and in-force flag. Read-only, stable-URI injectable context for EU acts. Full content and relations are available via the eurlex_get_document and eurlex_get_relations tools.

uri eurlex://document/{celexNumber} mime application/json

Relationship summary for a CELLAR work: amendment chain, consolidations, legal basis, and cited-by information. Returns direct one-hop CDM relations for the work identified by CELEX number. For deeper traversal or additional relation types, use the eurlex_get_relations tool.

uri eurlex://document/{celexNumber}/relations mime application/json

Prompts

1

Frames a comparative legal analysis across EU and US law for a given policy domain. Structures the inquiry to use eurlex_search_documents and eurlex_get_document for the EU side, and courtlistener_search_opinions for the US counterpart. Useful for policy analysts, legal researchers, and practitioners needing a cross-jurisdictional overview.

  • domainrequired — Policy domain for the comparison (e.g. "data privacy", "antitrust", "AI regulation", "food safety").
  • focus — Optional sub-topic or specific aspect to focus on (e.g. "enforcement mechanisms", "data subject rights", "remedies").