Eur Lex Mcp Server

io.github.cyanheads由 GitHub 帳號 cyanheads 發布v0.20.1更新於 Nov 4, 2026

Search EU legislation, CJEU case law, and treaties; traverse CELLAR graph; browse EuroVoc concepts.

已驗證Streamable HTTP可網頁執行網頁搜尋與抓取知識與記憶資料與分析

概覽

AI 產生的概覽

透過 CELLAR 檢索歐盟立法、條約與歐盟法院判例,解析法律引註、取得全文並追溯修訂與轉換關係。

可以做什麼
  • 解析引註:把 CELEX 編號、ELI URI、ECLI、官方公報引註、COM 文件號與程序編號定位到正規的法律作品
  • 檢索立法:依類型、日期、EuroVoc 主題、制定機構與生效狀態查找條約、條例、指令與準備性文件
  • 檢索判例:依案件編號、法院、會員國、程序類型、結果與主題查找歐盟法院及普通法院的判決、裁定與總辯護人意見
  • 取得文件:讀取中繼資料、引註資訊與全文(HTML、Markdown 或 Formex4 XML),支援大綱與章節選取
  • 追溯關係:列出修訂、廢止、合併版本、法律依據、解釋性判決、會員國轉換措施與立法程序
  • 瀏覽 EuroVoc 概念,並對 CELLAR 端點執行唯讀 SPARQL SELECT 查詢
適用情境
適合需要回答歐盟法問題的情境:確認某個引註對應的法案、查核指令是否生效或已被轉換、尋找某主題的判例,或釐清立法被修訂的脈絡。
執行需求
可使用託管的 HTTP 端點,或透過 npx 在本機執行(原始碼建置需 Node.js v24+ 或 Bun v1.4.0+)。不需 API 金鑰或帳號,CELLAR 與 EUR-Lex 端點皆公開。選用環境變數可覆寫 SPARQL 端點、內容基礎位址、結果上限、查詢逾時、傳輸方式、HTTP 主機與連接埠及驗證模式。
安裝前請注意
工具為唯讀:SPARQL 僅接受 SELECT,更新語句會被拒絕。查詢會送往歐盟出版局的公開端點,檢索詞與識別碼也隨之傳出;覆寫端點變數會把請求改送到其他位址。結果有上限且分頁止於第 10,000 列,查無紀錄並不代表該內容不存在。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Eur Lex Mcp Server,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.cyanheads%2Feur-lex-mcp-server/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "eur-lex": {
      "type": "http",
      "url": "https://eur-lex.caseyjhand.com/mcp"
    }
  }
}

README

@cyanheads/eur-lex-mcp-server

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

7 Tools • 2 Resources • 1 Prompt

Public Hosted Server: https://eur-lex.caseyjhand.com/mcp


Overview

EU legislation, CJEU case law, and treaties from EUR-Lex. Search documents and case law, fetch full text, resolve citations, trace how acts amend and cite each other, and browse the EuroVoc subject thesaurus.

Tools

ToolDescription
eurlex_search_documentsSearch EU legislation, treaties, and preparatory acts by type, date, EuroVoc subject, author institution, and in-force status
eurlex_get_documentFetch metadata (including ELI, Official Journal reference, dates of effect, and the legislative procedures an act belongs to with their status) and full text (HTML, Markdown, or Formex4 XML) for an act or case by CELEX, ELI, or work URI, with a section outline of either
eurlex_lookup_celexResolve a CELEX number, ELI URI, ECLI, OJ citation (Regulation (EU) 2016/679), Official Journal reference (OJ L 119, 4.5.2016, p. 1), Commission document number (COM(2021) 206 final), or procedure reference (2021/0106(COD)) to its canonical CELLAR work
eurlex_get_casesSearch CJEU and General Court case law by case number, court, case type, member state, procedure type and outcome, subject, and date range
eurlex_get_relationsTraverse the CELLAR relationship graph — amendments, repeals, consolidations, legal basis and the works adopted under it, the proposal an act adopts, interpreting rulings (by article), citations, transpositions
eurlex_browse_subjectsSearch the EuroVoc thesaurus to resolve terms to concept URIs for legislation searches (CJEU rulings carry no EuroVoc concept; search them by subject in eurlex_get_cases)
eurlex_query_sparqlRun a raw, read-only SPARQL SELECT against the CELLAR endpoint

Resources

ResourceDescription
eurlex://document/{celexNumber}Metadata snapshot for a CELLAR work
eurlex://document/{celexNumber}/relationsOne-hop relationship summary for a CELLAR work

All resource data is also reachable via tools.

Prompts

PromptDescription
eurlex_comparative_analysisFrame a comparative EU/US legal analysis for a policy domain

Skills

SkillDescription
eur-lex-guideFor agents calling the tools: where each CELEX, ELI, ECLI, and case-number form comes from, the checks to run before concluding an act is in force, repealed, uninterpreted, or final, and a CELLAR SPARQL and CDM reference for eurlex_query_sparql

The skill is in skills/. Plugin installs, the .mcpb bundle, the npm package, and the Docker image include it, and the server serves it to MCP clients through the Skills extension (skills/list, skill:// resources).


Capability reference

eurlex_search_documents tool

  • At least one filter: keyword (English titles, plus CELEX numbers or fragments such as 2016R0679; a keyword with letters and no digit, such as R(01), scans every CELEX and can take tens of seconds; no body search), document_type (REG, DIR, DEC, TREATY, JUDG, OPIN_AG, PROP, REC), date_from/date_to, eurovoc_concept (from eurlex_browse_subjects), author_institution, or in_force (true/false; false covers repealed, expired, and not-yet-in-force acts)
  • Pages of up to 100 via offset/limit (a larger limit is served at 100 and reported in limit_clamp), newest first; each row flags is_consolidated and is_corrigendum, and corrigenda and consolidated texts appear only under include_corrigenda and include_consolidated. Paging stops at row 10,000: the last page carries no next_offset and a notice giving the date_from/date_to window that continues past it
  • No match returns an empty page with a notice on how to broaden the filters; for eurovoc_concept with document_type JUDG or OPIN_AG, where CELLAR indexes no Court of Justice or General Court ruling by EuroVoc concept, the notice instead points to eurlex_get_cases subject; typed errors: no_filters, invalid_date_range, invalid_author_institution and invalid_keyword (no letters or digits), offset_past_window (offset 10,000 or more)
  • author_institution matches English authority labels and national-court names returned by eurlex_get_document, such as European Parliament or Supremo Tribunal de Justiça, with or without date bounds

eurlex_get_document tool

  • Exactly one of celex_number, eli_uri, or work_uri (pasted forms such as a CELEX: prefix or EUR-Lex URL are accepted); body as html (default), markdown, or xml (Formex4) in any of the 24 EUR-Lex languages, falling back to English. Case law also carries ecli, formation, referring_court, subject_matter, and case_reference, plus countries, procedure_types, subjects, and procedure_languages where CELLAR records them, as eurlex_get_cases rows carry them; a consolidated text reports its base act as base_act_celex
  • content_mode "paged" (default), "full", or "metadata_only", capped at 100,000 characters per call (a larger limit is reported in limit_clamp) with content_chars_total/has_more to page on; outline: true lists headings with offsets, and select (e.g. { articles: "1,5,17" }) returns just those sections. For judgments and AG opinions the outline lists section headings, and select: { operative_part: true } returns the ruling alone
  • is_superseded flags a newer consolidated version (current_consolidated_celex, consolidated_as_of), and resolve: "current_consolidated" serves it; in_force: false comes with repealed_by, end_of_validity, or entry_into_force where CELLAR records one. Typed errors: invalid_identifier_args, not_found, content_challenge (a WAF bot-challenge in place of text)
  • Citation facts, each absent when CELLAR records none: eli (a consolidated text keeps its own point-in-time ELI); oj_reference, the Official Journal reference (OJ L 119, 4.5.2016, p. 1–88; no series letter before 1968, a class letter as in OJ L 42I, OJ L, 2024/1689, 12.7.2024 for act-by-act publication), with pages from the English edition or, before 1973, the original-language editions, and the earliest issue for a reprinted act; dates_of_effect, every recorded date as { date, type?, provision? } with type one of entry_into_force, application, partial_application, provisional_application, takes_effect, takes_partial_effect (an act applying in stages lists its general date of application as application and each date covering only some provisions as partial_application) and provision the clause that sets the date, numbered as CELLAR records it (Article 113(a), Article 93.1); and transposition_deadlines for a directive. entry_into_force keeps its meaning of an entry still ahead on a not-in-force act. A consolidated text reports its base act's oj_reference, dates_of_effect, and transposition_deadlines
  • procedures lists the interinstitutional procedures an act belongs to, reached from a proposal or from the act a procedure adopted, each as { reference, status?, withdrawal_date?, adopted_acts? }: reference in its cited form (2021/0106(COD), which eurlex_lookup_celex resolves), status one of adopted, withdrawn, pending, not_adopted from the flag CELLAR sets (absent when it sets none or several, so a missing adopted_by edge or status never means pending), withdrawal_date on a procedure flagged withdrawn, and adopted_acts the CELEX numbers it produced. A consolidated text reports its base act's; case law belongs to none
  • Available legacy HTML/Markdown bodies may carry content_omissions: { tables }: missing-table markers counted across the full source, including outside the returned window. Paging cannot recover these tables. alternative_representations lists PDF streams advertised for the served work and language when discovery succeeds; XML availability remains independent. Metadata-only calls do not inspect source omissions
  • National implementing measures carry sparse national_measure citation fields: journal, number, pages, publication_date, and notification_date, including metadata-only calls. Numbers and pages retain their source spelling; publication, notification, and document dates are distinct, and each is omitted where CELLAR records its 1001-01-01 placeholder for an unknown date. When the body is unavailable, use the gazette citation to retrieve it; no national-portal URL is inferred, and notification does not prove complete transposition

eurlex_lookup_celex tool

  • A CELEX number, ELI URI, ECLI, or OJ citation naming its act type and year (Regulation (EU) 2016/679, Directive 95/46/EC, optionally followed by its parenthesized OJ reference, Directive 95/46/EC (OJ L 281, 23.11.1995, p. 31), or by the period ending a sentence); pasted forms (a CELEX: prefix, a EUR-Lex page URL, an ELI with or without scheme or language segment) are normalized and echoed in celex_number. A citation without its act type (95/46/EC) or year (Regulation No 17) is not parsed
  • An Official Journal reference resolves to the act starting on the cited page: issue, publication date, and first page (OJ L 281, 23.11.1995, p. 31, also of 23.11.1995, a page range, a class letter as in OJ L 42I, OJ C, and before 1968 the series-less OJ 13, 21.2.1962, p. 204/62); the year-first OJ 1995 L 281, p. 31, OJ 1995 L 281/31, and [1995] OJ L281/31; and act-by-act OJ L, 2024/1689, 12.7.2024 and OJ C, C/2024/2664, 29.4.2024. The spellings EUR-Lex act texts and the Court use read the same: OJ No L 281, O.J. L 281, a spaced date (23. 11. 1995), pp. 1–88 or p 31, and OJ L 2024/1689 without its comma. A cited date must equal the issue's publication date. Pages are matched on the English edition, or on any language before 1973 when the issue has no English pages. A reference without its year or first page (OJ L 281, OJ L 119/1) is not parsed. Recognized only under auto
  • A Commission document number resolves to the work carrying it: COM(2021) 206 final, also COM(2021)206, COM/2021/206, final/2 for a later version, a two-digit year as 19YY (COM(90) 314 final), and SEC, SWD, and JOIN numbers (not C(…) decisions). An interinstitutional procedure reference resolves to the act that initiated it: 2021/0106(COD), 2021/106 (COD), or 2021/0106/COD; one without its type is not read. Recognized only under auto
  • identifier_type auto-detects the format or sets it; ambiguous_identifier fires when auto-detection can't classify the input (including an OJ reference without its year or first page). A case number (C-131/12) returns found: false with a notice pointing to eurlex_get_cases
  • Returns work URI, confirmed CELEX number, resource type, date, and the case's ECLI; found: false with a notice for a well-formed identifier that matches no work, for an OJ reference whose date or page matches nothing, for one whose first page starts several acts, and for a document number held in several parts or a procedure with several initiating acts (the notice names each CELEX)

eurlex_get_cases tool

  • Filters: case_number (C-131/12, T-22/20, F-12/05, or a pre-1989 26/62; reaches every judgment, order, and AG opinion filed under it), court (CJEU or GC), case_type (judgment, order, ag_opinion), keyword (English titles, plus CELEX numbers or fragments such as 2013CJ0131), and date_from/date_to; primary records only unless include_derivative adds notices, abstracts, summaries, and corrigenda
  • Case-law facts CELLAR records: member_state (alpha-3 or two-letter code, any case; the referring court's state on a preliminary reference, the defendant on an infringement action, the applicant's state on a direct action), procedure_type (preliminary_ruling, annulment, staff_case, appeal, failure_to_fulfil_obligations, damages, interim_measures, appeal_against_penalty, failure_to_act, arbitration_clause), outcome (successful, unfounded, inadmissible, decision_unnecessary; with procedure_type, on the same procedure), and subject (a phrase matched against the English labels of CELLAR's case-law subject classification, every word required: "trade mark" reaches "Trade marks"; query_echo.subject_labels names the subjects matched)
  • Pages of up to 100 via offset/limit (a larger limit is served at 100 and reported in limit_clamp), newest first; each case carries its ECLI where recorded, countries, procedure_types, subjects, and procedure_languages where CELLAR records them, plus formation, advocate_general, display_title, parties, referring_court, subject_matter, and case_reference, and the raw title only when those fields miss part of it. Paging stops at row 10,000: the last page carries no next_offset and a notice giving the date_from/date_to window that continues past it
  • No match returns an empty page with a notice on how to broaden the filters, as does a subject matching no label (then no case is searched); typed errors: invalid_case_number, invalid_date_range, invalid_keyword and invalid_subject (no letters or digits), offset_past_window (offset 10,000 or more)
  • case_type: "ag_opinion" includes Advocate General opinions (OPIN_AG) and views (VIEW_AG); resource_type distinguishes AG Opinion from AG View

eurlex_get_relations tool

  • Exactly one of celex_number or work_uri; relation_types narrows to any of cites, amends, amended_by, repeals, repealed_by, implicitly_repeals, implicitly_repealed_by, legal_basis, basis_for, interprets, interpreted_by, consolidated_version, national_transposition, adopts, adopted_by (omit for all fifteen)
  • basis_for lists the works naming the act among their legal bases; interpreted_by lists the CJEU and General Court rulings interpreting it, and interprets what a ruling interprets; adopts lists the works an act adopts (usually its Commission proposal) and adopted_by the act that adopted a work. member_states narrows national_transposition to named member states (ISO 3166-1 alpha-3 or two-letter codes, echoed as alpha-3); using it without national_transposition fails as member_states_not_applicable
  • A first page (offset 0) that traverses national_transposition carries transposition_summary, counted over every measure rather than the page: by_member_state lists each member state with measures (GBR included) with its measure count and newest latest_date, and member_states_without_measures names the states in scope with none — the member_states filter, else the 27 current member states. A missing record is not proof of non-transposition. It is absent when no state in scope has a measure; a count CELLAR fails leaves the page without it, named in the notice
  • article narrows interpreted_by to rulings with a recorded provision in one article of the act (17, 6a, Article 17, Art. 17, any case; blank is omitted; a paragraph, range, or Roman numeral is rejected). It matches at any depth, ignores leading zeros, and a letter also matches its Latin ordinal (28c reaches Article 28 quater); rulings CELLAR records no provision for are left out, as the notice says, and the echoed article is the normalized form. Using it without interpreted_by fails as article_not_applicable
  • Amendment, repeal, interpretation, and adoption rows carry provisions, the provisions CELLAR records the edge as targeting, in compact codes (A17P1LC is Article 17(1)(c)) or authority-token codes (AR 43 PA 4); a row without them records none, which does not mean the edge reaches the whole act. A provisions lookup CELLAR fails returns the rows without them, named in the notice
  • One hop, paged per relation type and direction via offset/limit (up to 100, default 10; a larger limit is reported in limit_clamp), newest first. limit is the only page boundary: every type and direction returns up to that many whole rows, titles and provisions included, and next_offset is the offset plus the limit served. Each type and direction pages to row 10,000, then a notice routes older works to eurlex_query_sparql with a ready-to-run query. Omitting relation_types equals listing all fifteen types
  • Each relation carries relation_type, direction (outgoing/incoming), related_work_uri, and where known related_celex_number, related_date, related_title (English only), and related_member_state on national_transposition rows; empty_relation_types separates "no edges of this type" from "paged out". Typed errors: invalid_identifier_args, member_states_not_applicable, article_not_applicable, not_found, offset_past_window

eurlex_browse_subjects tool

  • Matches preferred and alternative EuroVoc labels, so a common synonym resolves to its concept, in any EU official language (default English); offset/limit pagination (up to 50; a larger limit is served at 50 and reported in limit_clamp), to row 10,000 (offset_past_window beyond)
  • Returns concept URI, preferred label, code, broader (parent) label, and the alternative label that matched when one did; an empty page with a notice when nothing matches
  • Exact label matches rank first, then label or word-start matches, then other substring matches, so "AI" leads with artificial intelligence

eurlex_query_sparql tool

  • Read-only SELECT only (update forms and ASK/CONSTRUCT/DESCRIBE are rejected); cdm:, skos:, and xsd: prefixes are auto-injected; optional timeout_hint (1000–55000 ms)
  • Results capped at MAX_SPARQL_RESULTS (default 100); a truncated result's notice says to add ORDER BY and repeat with a higher OFFSET, up to row 10,000. A zero-row result from an untyped string literal gets a notice to type it (^^xsd:string, ^^xsd:anyURI for an ELI) or language-tag it
  • Typed errors: not_read_only (a SPARQL Update), unsupported_query_form (ASK, CONSTRUCT, DESCRIBE, or no SELECT), sparql_error, sparql_timeout

eurlex://document/{celexNumber} resource

  • Metadata snapshot as application/json — resource type, author institution(s) labelled as eurlex_get_document labels them, Advocates General, date, English title, in-force flag, eli, oj_reference, dates_of_effect, transposition_deadlines, legal basis, EuroVoc subjects, and procedures (the four citation fields and the procedures as in eurlex_get_document); a consolidated text keeps its own eli, adds base_act_celex, and reads authors, in-force flag, oj_reference, dates_of_effect, transposition_deadlines, legal basis, subjects, and procedures from that act
  • celexNumber comes from eurlex_search_documents, eurlex_get_cases, or eurlex_lookup_celex

eurlex://document/{celexNumber}/relations resource

  • One-hop relationship summary over all fifteen eurlex_get_relations types, with no provisions, each related work with its related_date and English related_title where it has them, capped at 25 per relation type and direction (newest kept)
  • truncated plus a continuation pointer to eurlex_get_relations when more relations exist, its input naming the CELEX and offset 25 so the tool continues each type and direction where the summary stopped

eurlex_comparative_analysis prompt

  • Arguments: domain required; focus optional, folded into its matching analysis axis or added as its own section
  • Returns a research plan that restates the domain in EU legal vocabulary ("antitrust" → "competition law"), chains eurlex_browse_subjects → eurlex_search_documents → eurlex_get_document → eurlex_get_relations for the EU side and courtlistener_search_opinions for the US side, plus a six-axis analysis framework

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

EUR-Lex-specific:

  • No API key required — CELLAR SPARQL and the EUR-Lex REST content endpoints are both publicly accessible
  • SPARQL is POSTed with CDM prefix declarations built in; server-side LIMIT enforcement (max 100) guards against Virtuoso timeouts
  • Act text is fetched via CELLAR content negotiation; HTML passes through as served, multi-part Formex4 XML is assembled into one document, and Markdown is converted server-side
  • Syntax, compile, and sort-window errors fail at once as sparql_error (a sort-window error, SR353, hints to lower OFFSET or narrow the query) and timeouts as sparql_timeout, neither retried within the call; a sparql_timeout for running out of time is marked retryable, since a later call can finish, and Virtuoso's refusal of a too-costly query is not. Gateway pages and other transient failures are retried inside the call's shared query budget (SPARQL_QUERY_TIMEOUT_MS), and a retry ladder the budget cuts short reports the last attempt's own failure
  • Automatic English fallback when a requested translation is unavailable, with requested/effective language reported

Agent-friendly output:

  • EuroVoc prerequisite guidance in server-level instructions — agents are directed to eurlex_browse_subjects before concept-filtered searches
  • eurlex_lookup_celex confirms CELEX/ELI/ECLI existence upfront, preventing downstream errors in document or relation fetches
  • content_status, content_unavailability_reason, and requested/effective language fields distinguish skipped, available, absent, upstream-failed, and incomplete content without string parsing
  • Typed reason codes on every tool's error contract let agents branch on outcomes programmatically

Getting started

Connect to the hosted instance, no install:

sh
claude mcp add --transport http eur-lex-mcp-server https://eur-lex.caseyjhand.com/mcp

Or run it locally:

sh
claude mcp add eur-lex-mcp-server -- npx -y @cyanheads/eur-lex-mcp-server

For other clients, add this to the MCP config file:

json
{  "mcpServers": {    "eur-lex-mcp-server": {      "command": "npx",      "args": ["-y", "@cyanheads/eur-lex-mcp-server"]    }  }}

No API key is required. For Docker or a source build, see Running the server.


Configuration

All configuration is validated at startup via Zod schemas in src/config/server-config.ts.

VariableDescriptionDefault
CELLAR_SPARQL_ENDPOINTCELLAR SPARQL endpoint URL override (e.g., for a local Virtuoso mirror).http://publications.europa.eu/webapi/rdf/sparql
EURLEX_CONTENT_BASE_URLEU Publications Office CELLAR content resolver base URL override.http://publications.europa.eu
SPARQL_QUERY_TIMEOUT_MSClient-side timeout in milliseconds, an integer from 1 to 2147483647: the budget a call's CELLAR queries share (a call that chains queries spends it once, not per query) and the ceiling on any single query; an EUR-Lex content fetch gets its own timeout of this length, outside the shared budget.55000
MAX_SPARQL_RESULTSEnforced ceiling on LIMIT in all generated SPARQL queries.100
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTPort for HTTP server.3010
MCP_AUTH_MODEAuth mode: none, jwt, or oauth.none
MCP_SESSION_MODESession handling: stateful, stateless, or auto (auto resolves to stateful).stateless
MCP_LOG_LEVELLog level (RFC 5424).info
LOGS_DIRDirectory for log files (Node.js only).<project-root>/logs
LOG_TOOL_FAILURE_PAYLOADSLog failed tool calls' arguments and result, redacted by key name (free-form values are not), capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384).false
OTEL_ENABLEDEnable OpenTelemetry instrumentation.false

See .env.example for the full list of optional overrides.


Running the server

Local development

Requires Bun v1.4.0 or higher (or Node.js v24+).

  • Clone and install:

    sh
    git clone https://github.com/cyanheads/eur-lex-mcp-server.gitcd eur-lex-mcp-server && bun installcp .env.example .env   # optional: every variable has a default
  • Build and run:

    sh
    # One-time buildbun run rebuild
    # Run the built serverbun run start:stdio# orbun run start:http   # listens at http://localhost:3010/mcp
  • Run checks and tests:

    sh
    bun run devcheck   # Lint, format, typecheck, securitybun run test       # Vitest test suitebun run lint:mcp   # Validate MCP definitions against spec

Docker

sh
docker run --rm -p 3010:3010 ghcr.io/cyanheads/eur-lex-mcp-server:latest

The image defaults to HTTP transport, stateless session mode, and logs to /var/log/eur-lex-mcp-server. To run it over stdio from an MCP client, use "command": "docker" with "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/eur-lex-mcp-server:latest"]. To build locally, docker build -t eur-lex-mcp-server . then docker run --rm -p 3010:3010 eur-lex-mcp-server; OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.


Project structure

DirectoryPurpose
src/index.tscreateApp() entry point — registers tools, resources, prompts, and the published skills; initializes services.
src/configServer-specific environment variable parsing and validation with Zod.
src/services/cellar-sparqlCELLAR SPARQL service — POST client, binding mapper, LIMIT enforcement, CDM PREFIX declarations.
src/services/eurlex-contentCELLAR content service — content-negotiation GET client for /resource/celex/{CELEX} (Accept / Accept-Language) with English language fallback, and an in-process cache of served bodies so paging an act fetches it once.
src/mcp-server/toolsTool definitions (*.tool.ts). Seven tools across document search, retrieval, resolution, case law, relations, EuroVoc, and raw SPARQL.
src/mcp-server/resourcesResource definitions (*.resource.ts). Metadata and relations resources.
src/mcp-server/promptsPrompt definitions (*.prompt.ts). Comparative analysis prompt.
skills/Agent Skills published to the agents that call the tools (eur-lex-guide).
tests/Unit and integration tests mirroring src/.

Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
  • Register new tools and resources via the barrels in src/mcp-server/*/definitions/index.ts
  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks and tests before submitting:

sh
bun run devcheckbun run test

License

Apache-2.0 — see LICENSE for details.

來源:README.md,提交 708121c

工具

7

eurlex_lookup_celex

Resolve EU Legal Citation

Resolve an EU legal citation — a CELEX number, ELI URI, ECLI, an OJ citation naming its act type and year (e.g. "Regulation (EU) 2016/679", "Directive 95/46/EC"), an Official Journal reference naming its issue, date, and first page (e.g. "OJ L 119, 4.5.2016, p. 1"), a Commission document number (e.g. "COM(2021) 206 final", also SEC, SWD, JOIN), or an interinstitutional procedure reference (e.g. "2021/0106(COD)", resolved to the act that initiated it) — to its canonical CELLAR work, confirming it exists before you fetch or traverse it. Returns the work URI, confirmed CELEX number, document type, date, and the ECLI of a case that carries one. A CELEX that CELLAR holds under several works resolves to the one the EUR-Lex content resolver serves. An ECLI shared by several records (a judgment and its abstract or extract, or a joined AG opinion) resolves to the primary record with the lowest CELEX. An OJ reference whose first page starts several acts, a document number CELLAR holds in several parts, and a procedure with several initiating acts return found false, the notice naming each CELEX.

輸入參數identifier必填identifier_type

eurlex_browse_subjects

Browse EuroVoc Subjects

Search the EuroVoc thesaurus, resolving a keyword into concept URIs usable in the eurovoc_concept subject filter of eurlex_search_documents. CELLAR indexes no judgment, order, or Advocate General opinion of the Court of Justice or General Court by EuroVoc concept; only EFTA Court judgments carry one, so search case law by subject with eurlex_get_cases subject. Matches both preferred and alternative (non-preferred) labels, so a common synonym reaches the concept it stands for. Returns each concept URI, its preferred label in the requested language, code, broader (parent) label, and the alternative label that matched when one did. Concepts with an exact label match come first, then those whose label or one of its words starts with the keyword, then other substring matches, each group ordered by preferred label.

輸入參數limitoffsetkeyword必填language

eurlex_search_documents

Search EU Documents

Search EU legislation, treaties, and preparatory acts across the CELLAR corpus by document type, date range, EuroVoc subject, author institution, and in-force status. Keyword matches English titles and CELEX strings only — there is no full-text body search. Corrigenda are excluded by default so primary acts fill the page (set include_corrigenda to include them). Returns a page of CELEX numbers, work URIs, type labels, dates, and titles, newest first, each flagged with is_consolidated and is_corrigendum. At least one filter is required.

輸入參數limitoffsetdate_tokeywordin_forcedate_fromdocument_typeeurovoc_conceptauthor_institutioninclude_corrigendainclude_consolidated

eurlex_get_cases

Search CJEU/GC Case Law

Search CJEU and General Court case law — judgments, orders, and Advocate General opinions and views — by case number, court, case type, member state, procedure type and outcome, subject, keyword, and date range. A case number reaches every judgment, order, AG opinion, and AG view filed under it. By default only these primary records are returned; derivative judicial information notices, case abstracts, summaries, and corrigenda are excluded so distinct cases fill the page (set include_derivative to include them). Keyword matches English case titles (which carry party names) and CELEX strings; there is no full-text body search. member_state, procedure_type, outcome, and subject match the facts CELLAR records on each case, so a case it records none of a filtered fact for never matches. Returns each case with its CELEX number (whose sixth character names the court: C, T, or F), work URI, ECLI, date, and type; where CELLAR records them, its countries, procedure types with outcome, subjects, and procedure languages; and — parsed from the title where present — the formation, Advocate General, parties, referring court, subject matter, and case reference. The raw CELLAR title is returned only when those fields do not capture all of it.

輸入參數courtlimitoffsetdate_tokeywordoutcomesubjectcase_typedate_fromcase_numbermember_stateprocedure_type另有 1 個

eurlex_get_document

Get EU Document

Fetch the metadata and full text of an EU act or case-law record by CELEX number, ELI URI, or work URI. Returns structured metadata (title, date, type, ELI, Official Journal reference, typed dates of effect, transposition deadlines, author institution, Advocates General, legal basis, EuroVoc subjects, in-force status and, for an act not in force, its repealing acts, end of validity, or pending entry into force; the legislative procedures the act belongs to, each with its status — adopted, withdrawn, pending, or not adopted — and the acts it produced; for case law, the ECLI, the formation, referring court, subject matter, and case reference parsed from the title, and the countries, procedure types with their outcome, subjects, and procedure languages CELLAR records) plus the body as HTML, Markdown, or Formex4 XML, defaulting to English with automatic fallback. Every body returned in one call is capped at 100,000 characters — paged and full windows page onward with offset/limit; use outline: true for a heading map and select to pull specific articles, chapters, recitals, or annexes of an act, or the headed sections and operative part of a judgment or order, reading a selected section on its own from the offset and chars in selected_sections.

輸入參數limitformatoffsetselecteli_urioutlineresolvelanguagework_uricelex_numbercontent_modeinclude_recitals

eurlex_get_relations

Get CELLAR Relationship Graph

Traverse the one-hop CDM relationship graph of an EU act: what it amends or is amended by, what it repeals or is repealed by (explicit and implicit), its consolidated versions, national transposition measures (on a first page also counted per member state, naming the member states with none), its legal basis and the works adopted under it, the proposal it adopts (or, for a proposal, the act that adopted it), the CJEU rulings interpreting it (or, for a ruling, the acts it interprets), and works that cite it. Amendment, repeal, interpretation, and adoption rows carry the provisions CELLAR records each edge as targeting, and article narrows interpreted_by to the rulings on one article. Returns direct relations only, paginated per relation type and direction. Requires a CELEX number or CELLAR work URI.

輸入參數limitoffsetarticlework_uricelex_numbermember_statesrelation_types

eurlex_query_sparql

Raw CELLAR SPARQL Query

Run a raw, read-only SPARQL SELECT against the CELLAR Virtuoso endpoint — an escape hatch for CDM ontology traversals the curated tools do not cover. Only SELECT is accepted; update forms and ASK/CONSTRUCT/DESCRIBE are rejected before execution, and results are capped at the server row cap (100 by default). The cdm:, skos:, and xsd: prefixes are auto-injected.

輸入參數sparql_query必填timeout_hint

版本歷史

12
  1. v0.20.1最新Nov 4, 2026
  2. v0.20.0Oct 26, 2026
  3. v0.19.2Oct 25, 2026
  4. v0.19.1Oct 23, 2026
  5. v0.19.0Oct 15, 2026
  6. v0.18.2Oct 7, 2026
  7. v0.18.1Sep 26, 2026
  8. v0.18.0Sep 26, 2026
  9. v0.16.0Sep 26, 2026
  10. v0.13.0Sep 25, 2026
  11. v0.12.2Sep 21, 2026
  12. v0.12.1Sep 16, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分