# EULEX MCP — Anthropic Claude for Legal Review Checklist

One-page acceptance checklist for the [Anthropic Claude for Legal
Connectors program](https://github.com/anthropics/claude-for-legal/blob/main/CONNECTORS.md).
Use as the cover sheet for the connector PR.

> Connector: **EULEX** — EU legal-research MCP server (regulations,
> directives, case law, treaties, transposition status, Eurostat).
> Connector type: **Remote MCP** over Streamable HTTP.
> Endpoint: `https://mcp.eulex.ai/mcp`.
> Authentication: OAuth 2.1 (DCR + PKCE) · PAT · Service JWT.
> Status: **read-only** — no write tools, no irreversible operations.

---

## Connector basics

- [x] **Remote MCP over HTTPS.** Endpoint is `https://mcp.eulex.ai/mcp`,
      transport is Streamable HTTP per current MCP spec. TLS 1.2+.
- [x] **Standards-compliant authentication.** Three paths documented in
      [`MCP_AUTH.md`](./MCP_AUTH.md):
      OAuth 2.1 with Dynamic Client Registration (RFC 7591) and PKCE
      (RFC 7636); RFC 9728 protected-resource metadata; RFC 8414
      authorization-server metadata; bearer Personal Access Tokens
      (90-day TTL); short-lived service JWTs (15 min).
- [x] **Stable, versioned tool surface.** v4.0 freezes a 12-tool public
      surface; major version bump telegraphs the breaking rename from
      v3.x. JSON schema artefact:
      [`mcp_tools_v4.schema.json`](./mcp_tools_v4.schema.json).

## Liveness and observability

- [x] **`/health` endpoint** returns `{status, service,
      build_version, tool_count, revision, uptime_seconds}` with
      `Cache-Control: no-store`. Unauthenticated, cheap, suitable for
      Cloud Run health probes and external uptime monitors. The
      `tool_count` is enumerated once during the Starlette lifespan
      startup and cached on `app.state` so the probe is O(1). We
      deliberately do **not** expose `/healthz` — Google Frontend (in
      front of Cloud Run custom domains) reserves that path for its
      own probes and short-circuits requests before they reach the
      container. External monitors should hit `/health`.
- [x] **Structured startup log** — `EULEX MCP Server initialized
      with N tools (vX.Y.Z): <comma-separated names>` is emitted on
      every cold start and is greppable in Cloud Logging for alerting.

## Tool design

- [x] **Read-heavy.** All 12 public tools are annotated
      `readOnlyHint=true` and `destructiveHint=false`; the server does
      not expose write, destructive, or irreversible operations.
- [x] **Human-readable `title` on every tool.** v4.0.6 adds a
      reviewer-facing `title` to every tool (e.g. `"Search EU
      Legislation"`, `"Get EU Document Section"`,
      `"EU Directive Transposition Status"`). The `name` (`search`,
      `get_section`, …) remains the stable agent-callable identifier;
      `title` is what UIs render in tool-pickers.
- [x] **Tools documented with inputs, outputs, and examples.**
      [`MCP_TOOLS.md`](./MCP_TOOLS.md) contains a full table with
      input summaries, output / provenance, tier, latency hints, and
      the agent composition recipes that replace the three hidden
      tools (`compare_documents`, `compliance_snapshot`,
      `check_in_force_live`).
- [x] **Idempotency annotated correctly.** Cached lookups are
      `idempotentHint=true`; live SPARQL / Eurostat calls
      (`eu_transposition`, `eurostat_query`) are
      `idempotentHint=false`, `openWorldHint=true`.

## Data quality and provenance

- [x] **Provenance on every response.** Every tool returns
      `eulex_citation` (CELEX + section + `— via eulex.ai`); EUR-Lex /
      Eurostat-backed responses also include `source_url`. See
      [`MCP_TOOLS.md`](./MCP_TOOLS.md) and
      [`MCP_DATA_COVERAGE.md` § Provenance and citation](./MCP_DATA_COVERAGE.md#provenance-and-citation).
- [x] **Disclaimer surfaced.** `about()` returns the disclaimer string
      ("EULEX AI provides search over EU legislation for informational
      purposes. Always verify with official EUR-Lex sources. Not legal
      advice.") as a stable field that clients can render verbatim.
- [x] **Data coverage explicit.** [`MCP_DATA_COVERAGE.md`](./MCP_DATA_COVERAGE.md)
      enumerates the six live sources (EUR-Lex 198k+, Sections 581k+,
      Neo4j ~800k nodes (live) / 2.2M edges, Pinecone 2.3M, Cellar SPARQL
      live, Eurostat REST), languages (EN only in v4.0), geographic
      scope (EU-27 + HR), and known limitations.
- [x] **Freshness traceable.** `about()` returns a per-source
      `last_sync` timestamp (latest EUR-Lex sync at writing:
      2026-05-13 12:03 UTC).

## Reliability and operational fitness

- [x] **Rate limits and graceful degradation documented.**
      [`MCP_DATA_COVERAGE.md` § Rate limits and graceful degradation](./MCP_DATA_COVERAGE.md#rate-limits-and-graceful-degradation)
      covers free/plus quotas, per-tool latency p95 targets, fallback
      paths when an upstream is slow or down (Cellar / Eurostat /
      CloudSQL / Neo4j / Pinecone / Memorystore Redis), and the
      typed-error envelope returned to MCP clients.
- [x] **Slow tools called out.** `verify(live=true)`,
      `eu_transposition`, `eurostat_query` are explicitly flagged with
      latency hints (5–30 s) and recommended client timeouts (≥ 30 s)
      in `MCP_TOOLS.md` and `MCP_DATA_COVERAGE.md`.
- [x] **Errors are structured, not 500s.** Every tool catches and
      returns a typed Pydantic envelope with a human-readable `error`
      field; the server never raises a 500 to the MCP client. Permission
      errors include the upgrade link
      (`https://eulex.ai/landing/pricing`).

## Safety / hardening

- [x] **Injection-resistance documented.**
      [`MCP_DATA_COVERAGE.md` § Injection-resistance / retrieved content is data, not instructions](./MCP_DATA_COVERAGE.md#injection-resistance--retrieved-content-is-data-not-instructions)
      states that retrieved content is data to cite, not instructions
      to the agent; metadata vs content distinction is explicit; no
      tool can perform a write or trigger an out-of-allowlist network
      call.
- [x] **No destructive paths.** No write tools. No file I/O. No
      network calls outside the configured upstream allowlist
      (CloudSQL, Neo4j Aura, Pinecone, EUR-Lex Cellar, Eurostat REST,
      Memorystore Redis).
- [x] **Tier gating clearly enforced.** Plus-tier tools
      (`eu_transposition`, `eurostat_query`) are guarded by
      `tier_gate.require_plus_tier(...)` and return a typed
      "Upgrade required" message when called by free-tier tokens.

## Examples (smoke prompts for reviewers)

Five reproducible end-to-end prompts the reviewer can run from Claude
once the connector is enabled. All resolve to public CELEX IDs that
EULEX indexes today:

1. **Semantic search** — "What does the AI Act say about high-risk AI
   systems?" → `search` returns ranked sections from CELEX
   `32024R1689` (AI Act).
2. **Exact section fetch** — "Show me GDPR Article 6." → `get_section`
   on `32016R0679`, `section_ref="6"`.
3. **In-force check** — "Is the GDPR currently in force? Live check
   please." → `verify(celex_id="GDPR", live=true)` hits Cellar SPARQL.
4. **Graph traversal** — "What acts implement DORA?" → `get_related`
   on `32022R2554` with `include_implementing_acts=true`.
5. **Transposition** — "Has Croatia transposed NIS2?" →
   `eu_transposition(doc_id="NIS2", member_state="HR")`.
6. **Compose comparison (no MCP primitive)** — "Compare Article 5
   GDPR vs Article 5 AI Act." → agent composes two `get_section`
   calls and reasons over both texts.
7. **Eurostat** — "GDP growth in EU member states 2023." →
   `eurostat_query(question=...)` returns a markdown table.

Expected citations on every answer: at minimum the `eulex_citation`
string; for EUR-Lex responses also the `source_url` link back to the
canonical EUR-Lex page.

## Plugin fit / submission metadata

- [x] **Suggested plugin maps:** `regulatory-legal` (primary fit) or
      `ai-governance-legal` (because of native AI Act + DORA + DSA
      coverage). EULEX is comfortable being placed in either.
- [x] **One-line connector description** for `.mcp.json`: *"EULEX —
      semantic search and citation graph for EU regulations,
      directives, CJEU case law, and transposition status."*
- [x] **Auth method for `.mcp.json`:** OAuth 2.1 (DCR + PKCE)
      preferred for end users; PAT for headless / CI integrations.
- [x] **Sample `.mcp.json` snippet** — see `MCP_AUTH.md` § "Examples
      for various clients".
- [x] **Support / contact:** Listed in the connector PR
      (mailto + GitHub issues + status page).

## Known limitations (full disclosure)

- [x] All legal text is **English only** in the v4.0 index;
      multi-language support is on the roadmap but not shipped.
- [x] **Live Cellar SPARQL** (`verify(live=true)`, `eu_transposition`)
      and **Eurostat REST** (`eurostat_query`) can take 5–30 s; we
      document this prominently and clamp client expectations.
- [x] `compare` and `compliance_snapshot` are **not** MCP primitives
      in v4.0 — they are agent compositions over `get_section`,
      `get_metadata`, `verify`, `get_related`, and `eu_transposition`.
- [x] **Not legal advice.** Surface the `about()` disclaimer to end
      users.
- [x] **No write tools / no irreversible operations** in v4.0; the
      multi-backend `source` parameter is future work.

---

## Anthropic Software Directory submission (Connectors Directory)

Cross-referenced against the three current Anthropic policy documents
in addition to the legal-vertical checklist above:

- [Submitting to the Connectors Directory](https://claude.com/docs/connectors/building/submission)
- [Anthropic Software Directory Terms](https://support.claude.com/en/articles/13145338-anthropic-software-directory-terms)
- [Anthropic Software Directory Policy](https://support.claude.com/en/articles/13145358-anthropic-software-directory-policy)

### Submission requirements (form fields)

- [x] **Server basics** — name `EULEX AI`; URL `https://mcp.eulex.ai/mcp`;
      tagline *"EU regulation, via MCP."*; description: see
      [landing page](https://mcp.eulex.ai/) hero copy and `MCP_TOOLS.md`.
- [x] **Connection details** — auth: OAuth 2.1 (DCR + PKCE); transport:
      Streamable HTTP; capability profile: read-only; required
      capabilities: `tools`.
- [x] **Allowed link URIs** (declared so reviewers / users skip the
      "Open external link" prompt for our own surfaces):
      - `https://eulex.ai`
      - `https://mcp.eulex.ai`

      Third-party canonical sources we cite (`eur-lex.europa.eu`,
      `ec.europa.eu/eurostat`, `curia.europa.eu`) are intentionally
      **not listed** — Anthropic strips entries the submitter does
      not own. Users are simply prompted once per click for those.
- [x] **Tool annotations** — every tool emits
      `title`, `readOnlyHint=true`, `destructiveHint=false`, plus the
      relevant `idempotentHint` / `openWorldHint`. Confirmed live via
      `tools/list` against `https://mcp.eulex.ai/mcp` on the v4.0.6
      revision.
- [x] **Documentation link (public)** — https://mcp.eulex.ai/docs
      (companion docs index) and per-doc slugs `/docs/tools`,
      `/docs/auth`, `/docs/coverage`, `/docs/review`.
- [x] **Privacy policy link (public)** — https://eulex.ai/privacy
      (linked from landing footer and connector README).
- [x] **Support channel** — `mailto:support@eulex.ai` (24 h response
      target on workdays, 72 h weekends/holidays).
- [x] **Security disclosure channel** — `mailto:security@eulex.ai`
      surfaced through https://mcp.eulex.ai/.well-known/security.txt
      (RFC 9116). Out-of-band fallback: `support@eulex.ai`.
- [x] **Test account / sample data for the reviewer** — provided to
      Anthropic out-of-band via the submission form. Procedure:
      1. Anthropic reviewer emails `support@eulex.ai` from the
         submission form thread.
      2. EULEX issues a 30-day Plus-tier Personal Access Token via
         the WordPress admin (`mcp_pats` table, `tier=plus`,
         `note=anthropic-reviewer-<YYYYMM>`); revoked after launch.
      3. Reviewer adds the connector in Claude as
         `Authorization: Bearer <PAT>` per `MCP_AUTH.md` §
         "Personal Access Tokens".
      4. Reviewer runs the seven smoke prompts above; all 12 tools
         (Free + Plus) become callable.
- [x] **≥ 3 working example prompts** — see *Examples (smoke prompts
      for reviewers)* above (we ship seven). Same five prompts also
      appear in the connector `README.md` for end-user discovery.
- [x] **Branding** — logo `https://eulex.ai/landing/logo.png`
      (PNG 578×182, RGBA, 6.5 KB); favicon
      `https://eulex.ai/favicon.ico`; both surfaced through the
      MCP `Icon` declaration in `server.py` and the landing page.

### Software Directory Policy compliance

| Policy clause | Implementation |
|---|---|
| 1A — no Usage Policy violation | Read-only legal research, no medical/legal/financial advice generated, only retrieval + citation |
| 1B — no guardrail circumvention | Tool descriptions stick to scope; no jailbreak helpers |
| 1C — privacy first | Tokens Fernet-encrypted in Redis, JWT TTL 7 d, PAT revocation cache |
| 1D — minimal data collection | Tier-gate logs only `(user_id, tool_name, timestamp, success_bool)`; query content is **not** persisted |
| 1E — no IP infringement | EUR-Lex content is public domain (Decision 2011/833/EU); attribution preserved |
| 1F — no Claude memory access | No tool reads chat history, files, or memory |
| 2A–G — instructional software | Narrow descriptions, no dynamic instructions, no hidden text, no coercion of other tool calls |
| 3A — privacy policy link | https://eulex.ai/privacy |
| 3B — verified contact | `support@eulex.ai` + `security@eulex.ai` |
| 3C — documentation | `/docs/{tools,auth,coverage,review,schema.json}` |
| 3D — reviewer test account | Procedure documented above |
| 3E — ≥ 3 examples | 7 smoke prompts above + 5 in connector README |
| 3F — endpoint ownership | `mcp.eulex.ai` and `eulex.ai` are owned by Augment d.o.o. (DNS / WHOIS verifiable) |
| 3G — maintenance | Active deployment, daily corpus refresh, version bumps logged in `pyproject.toml` |
| 3H — agree to terms | Accepted at submission-form checkbox |
| 4A–C — unsupported use cases | N/A — no money transfers, no AI image/video/audio generation, not an ad surface |
| 5A — graceful errors | Typed Pydantic envelopes, no 500s |
| 5B — token frugality | `top_k` capped at 50 (default 10); `summary_only`, `nim_details_cap`, `find_by_date.limit` controls |
| 5C — tool names ≤ 64 chars | Longest public name: `eu_transposition` = 16 chars |
| 5D — OAuth + recognized CA | Cloudflare-managed TLS cert (chains to ISRG/DigiCert) |
| 5E — annotations | `title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint` on all 12 tools |
| 5F — Streamable HTTP | `mcp.http_app(path="/mcp")` |
| 5G — recent dependencies | N/A (remote server, not local) |

### Software Directory Terms (representations made at submission)

- [x] We hold and will maintain rights to operate the EULEX backend
      and to grant Anthropic the displayability licence for our
      logo, name, and connector description.
- [x] EULEX MCP and its ordinary use comply with applicable EU /
      Croatian law and Anthropic's Software Directory Policy.
- [x] Information provided in the submission form is accurate and we
      will keep it up to date (build version, document counts,
      reviewer test PAT, contact channels).
- [x] We provide and adhere to https://eulex.ai/privacy. Third-party
      processors (OpenAI for query intent + reranking, Anthropic for
      synthesis on the consumer surface, Pinecone for vector storage,
      Neo4j Aura for graph storage, Google Cloud SQL + Memorystore
      for relational + cache) are listed in the privacy policy with
      retention windows.
- [x] We will respond to Anthropic and third-party security
      vulnerability reports through https://mcp.eulex.ai/.well-known/security.txt
      with a reasonable standard of care.

---

Reviewed against [`anthropics/claude-for-legal/CONNECTORS.md`](https://github.com/anthropics/claude-for-legal/blob/main/CONNECTORS.md)
on **2026-05-14** for v4.0.0; cross-checked against the Anthropic
Software Directory Submission / Terms / Policy on **2026-05-16** for
v4.0.6 (the release that added `title` + `destructiveHint=false`
annotations and the `/.well-known/security.txt` route).
