Epstein Files Plugin β query the DOJ Epstein Files Transparency Act release from any AI agent
Quickstart Β· Architecture Β· Tools Β· Use with AI Agents Β· Examples Β· Responsible Use
Turns a name, date, keyword, EFTA page number, or an open-ended question β about the email corpus, the photos, the transcripts, or the knowledge graph β into the exact, citable, official DOJ document. No hand-paging through ~2.8 million pages. No fighting DOJ's bot-blocked search.
Operates only on already-public DOJ court records and a public full-text mirror. Built for research, fact-checking, and source-location β not re-identification, harassment, or doxxing. See Responsible Use.
Epstein Files Plugin indexes and resolves documents in the public DOJ Epstein Files Transparency
Act release (Public Law 119-38, signed 2025-11-19) β roughly 1.4M documents / 2.8β2.9M pages
published across 12 DataSets at justice.gov/epstein, mirrored and indexed as 20 queryable
databases by the third-party service epstein-data.com (both figures verified live 2026-08-24;
DOJ's total collected corpus is larger still, ~6M pages, of which this is the portion published
so far β re-verify before citing as exhaustive).
Available as:
- π§© a Claude Code plugin β installed from a marketplace in two lines
- π an MCP server (
.mcp.json) β the same server, standalone β local stdio, no API keys, no remote host, works with any MCP-compatible client: Claude Desktop, Cursor, Windsurf, or a custom agent runtime built on the officialmcpSDK - π» a Python CLI β
python src/efta_researcher.py, no MCP client required - π¦ a Python library β
from efta_core import efta_to_url, get_dataset, import directly
- π Faster than manual lookup. DOJ's own search is blocked for automated/headless access (Akamai bot protection β see Responsible Use); this goes straight from a name, date, or keyword to the matching EFTA number, in seconds.
- π― Direct-to-source, every time. Every result resolves to the official
justice.gov/epsteinPDF URL β you verify the primary document yourself, never a paraphrase of it. - β Fact-checked, not sensationalized. The known-document registry ships with sourced fact-checks (EUvsDisinfo, Reuters, Tempo, and others) so a "connection" is labeled for what the document actually shows, not for what a viral caption claims.
- π§ Completely queryable, not just the inbox. Two purpose-built tools cover the email corpus; five generic tools reach all 20 databases β images, transcripts, OCR text, handwriting, depositions, the knowledge graph β plus a read-only SQL escape hatch for anything the filter API can't express.
- πΊοΈ Structure, reconstructed once. The 12-DataSet / EFTA-Bates-number boundary table was cross-checked against DOJ's own disclosure pages, so you don't re-derive it per query.
- π No lock-in. The same lookups work from a CLI, a Python import, or any MCP client.
flowchart LR
subgraph Client["Any MCP client"]
A["Claude Code / Claude Desktop\nCursor Β· Windsurf Β· custom agent"]
end
subgraph Server["epstein-files-plugin β local stdio, no auth"]
direction TB
PB["Purpose-built tools\nefta_search Β· efta_filter_email\nefta_lookup Β· efta_known_docs"]
GEN["Generic tools\nefta_list_databases Β· efta_list_tables\nefta_describe_table Β· efta_query_table\nefta_run_sql"]
LOCAL["Local-only\nefta_get_url β pure computation,\nno network call"]
end
subgraph Upstream["Third-party mirror"]
DS[("epstein-data.com\nDatasette JSON API\n20 databases")]
end
DOJ[("justice.gov/epstein\nofficial PDF source")]
A -- "MCP / stdio\nJSON-RPC" --> Server
PB --> DS
GEN --> DS
LOCAL -.->|"constructs URL,\nno request sent"| DOJ
DS -.->|"indexes"| DOJ
style Server fill:#1a2332,stroke:#4b8bbe,color:#e8edf4
style Upstream fill:#0f1720,stroke:#2dd4a7,color:#e8edf4
style DOJ fill:#0f1720,stroke:#94a3b8,color:#e8edf4
Two tool layers, deliberately: purpose-built wrappers over the single most common table (fast,
ergonomic, proper pagination), and a generic introspection/query/SQL layer that reaches every
other database without a dedicated tool per table β the answer to "can everything be queried," and
what keeps this working as epstein-data.com's schema evolves through 2031 without new code. See
CLAUDE.md for the
full design rationale.
| Goal | Use this |
|---|---|
| Find a document by name, date, or keyword | efta_search / efta_filter_email |
Turn a citation (EFTA00741068) into an official DOJ link |
efta_get_url |
| Check whether a viral claim is real | efta_known_docs β Research & Fact-Check Posture |
| Search images, transcripts, OCR text, or the knowledge graph | efta_list_databases β efta_query_table |
Run a join, a count, or a GROUP BY |
efta_run_sql |
| Wire this into an agent that isn't Claude Code | Use with AI Agents |
| Understand the EFTA numbering / DataSet system | DataSet Reference |
- Python 3.11 or later (3.10 reaches end-of-life 2026-10-31 β see Tech stack currency)
- pip
/plugin marketplace add Zereo0317/Epstein-Files-Plugin
/plugin install epstein-files-plugin@epstein-files-plugin
git clone https://github.com/Zereo0317/Epstein-Files-Plugin.git
cd Epstein-Files-Plugin
python -m pip install --upgrade pip
pip install -r requirements.txt # requests, mcp (pinned <2.0 β see below)python src/efta_researcher.py --list
python src/efta_researcher.py --search "trilateral commission"
python src/efta_researcher.py --sender epstein --recipient schank --date 2009-10-23
python src/efta_researcher.py --efta EFTA00741068
python src/efta_researcher.py --databases
python src/efta_researcher.py --tables image_analysis
python src/efta_researcher.py --sql "select dataset, count(*) as n from doc_search group by dataset" --database full_text_corpuspython src/mcp_server.pyπ Purpose-built (the common case β full-text + email metadata):
| Tool | Purpose |
|---|---|
efta_search(query, limit, cursor) |
Substring search across the Datasette index β true total match count + cursor paging |
efta_filter_email(sender, recipient, date_exact, date_prefix, subject, limit, cursor) |
Filter emails by metadata fields β same total-count + paging |
efta_known_docs(category) |
List pre-verified, fact-checked known documents |
efta_get_url(efta_number) |
Convert an EFTA number to its official DOJ PDF URL |
efta_verify_url(efta_number) |
HEAD-check whether a DOJ PDF URL is live (see caveat below) |
efta_lookup(efta_number) |
Full document metadata from the Datasette index |
𧬠Generic (every one of the 20 databases, no hardcoding per table):
| Tool | Purpose |
|---|---|
efta_list_databases() |
List all 20 Datasette databases (images, transcripts, OCR, depositions, ...) |
efta_list_tables(database) |
List every table in one database, with columns + row counts |
efta_describe_table(database, table) |
Column list + row count for one table |
efta_query_table(database, table, filters, limit, cursor) |
Filter-suffix query against any table |
efta_run_sql(database, sql, params, limit) |
Read-only SQL β joins, aggregation, GROUP BY; Datasette rejects any non-SELECT with HTTP 400 |
β
All 11 tools are annotated readOnlyHint/idempotentHint (and openWorldHint on everything
network-facing) per the MCP tool-annotations convention β a client can safely auto-run them.
β οΈ Pagination:limitcaps at 50β100 depending on the tool. A query can match far more (e.g. "pizza" currently matches 233 documents) β paged tools surface(N of TOTAL shown)and, when more exist, acursorto continue.
β οΈ URL verification: justice.gov gates every PDF behind an age-verify + Akamai challenge, so a raw HTTP status can't reliably distinguish live from missing. URL correctness comes from the verified DataSet boundary table below, not from probing justice.gov.
β Not covered by the purpose-built tools alone:
image_analysis(92K captioned images),transcripts(435 audio/video transcripts),knowledge_graph,ocr_database,handwriting_transcriptions, and 13 more β all reachable via the generic tools instead. Callefta_list_databases()for the live, current list rather than trusting this table.
Epstein Files Plugin is MCP-first, not Claude-first: a standard local stdio server (built on the
FastMCP class bundled inside the official mcp Python SDK) speaking plain Model Context
Protocol. It works with any MCP-compatible client.
| Client | How it connects |
|---|---|
| Claude Code / Claude Desktop | /plugin marketplace add + /plugin install, or the raw .mcp.json |
| Cursor / Windsurf / Cline | Add the server entry from .mcp.json to the client's MCP settings |
| OpenClaw | Add the same generic config below under mcpServers in your own ~/.openclaw/openclaw.json (or openclaw config set mcpServers.epstein-files-plugin.command "python" etc.) β a local stdio server needs no transport field, OpenClaw auto-detects it from command. This plugin's own ClawHub listing manifest can't auto-wire this for you (OpenClaw's plugin manifest has no MCP-server field as of the current release β see CLAUDE.md); this per-user config is the real, working path. |
| ChatGPT, Gemini, or any custom/headless agent | Point it at src/mcp_server.py over stdio β no plugin system or Claude dependency required |
{
"mcpServers": {
"epstein-files-plugin": {
"command": "python",
"args": ["/absolute/path/to/epstein-files-plugin/src/mcp_server.py"]
}
}
}No API keys, no auth, no remote server β a local process talking stdio, identical behavior in every client.
Installed as a plugin, the same server auto-loads from this repo's .mcp.json (uses
${CLAUDE_PLUGIN_ROOT}, no path editing needed):
{
"mcpServers": {
"epstein-files-plugin": {
"command": "python",
"args": ["${CLAUDE_PLUGIN_ROOT}/src/mcp_server.py"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}| Variable | Default | Affects |
|---|---|---|
EFTA_DATASETTE_BASE_URL |
https://epstein-data.com |
Every search/query/SQL tool |
EFTA_DOJ_BASE_URL |
https://www.justice.gov |
efta_get_url, efta_verify_url, the CLI's --download/--verify |
A future change to either third-party host is a config change, not a code change.
Example 1 β Resolve a citation to its official source
User request: "What's the DOJ URL for EFTA00741068, and which DataSet is it in?"
Response:
EFTA: EFTA00741068
DataSet: DS9
URL: https://www.justice.gov/epstein/files/DataSet%209/EFTA00741068.pdf
Under the hood:
efta_get_url("EFTA00741068") parses the Bates number, resolves it against the verified
12-DataSet boundary table, and constructs the official DOJ URL β no network call, no guessing.
Example 2 β Find an email by sender, recipient, and date
User request: "Find the Epstein -> Roger Schank email from October 23, 2009."
Response:
Found 3 email(s):
EFTA00741068 DS9 2009-10-23 12:01:12 <- primary
EFTA00885615 DS9 2009-10-23 12:01:12 (OCR duplicate, reads "grnail.com")
EFTA01821140 DS10 2009-10-23 12:01:12 (third copy, later processing batch)
Under the hood:
efta_filter_email(sender="epstein", recipient="schank", date_exact="2009-10-23") queries the
epstein-data.com Datasette API (DOJ's own /multimedia-search is blocked for headless clients)
and returns every metadata match, so duplicate copies can be cross-referenced by timestamp.
Example 3 β Search beyond the email corpus (generic tools)
User request: "Any photos in the release that show a passport?"
Response:
efta_list_tables("image_analysis") -> "images" table, 92,249 rows, column "analysis_text"
efta_query_table("image_analysis", "images", filters={"analysis_text__contains": "passport"})
-> matching rows with efta_number, source_pdf, and the analysis text itself
Under the hood:
image_analysis isn't reachable through efta_search (that only covers full_text_corpus).
efta_query_table works against any of the 20 databases using the same filter-suffix syntax,
so no dedicated "image search" tool was needed.
Example 4 β A question the filter API can't express (raw SQL)
User request: "Break down the document count by DataSet."
Response:
efta_run_sql("full_text_corpus",
"select dataset, count(*) as n from doc_search group by dataset order by dataset")
-> 1:650, 2:150, 3:57, 4:143, 5:82, 6:13, 7:17, 8:10479, 9:480658, 10:496404,
11:331597, 12:12339, 98:6, 99:23210 (live counts, 2026-08-24)
Note: two values (98, 99) fall outside the documented 1-12 DataSet scheme β small catch-all
buckets in the source data itself. efta_get_url()/get_dataset() only resolve DataSets 1-12.
EFTA numbers are page (Bates) identifiers, not document identifiers β a 20-page PDF consumes
20 consecutive EFTA numbers. Boundaries below are the forensic per-file ranges from the
rhowardstone/Epstein-research-data mapping, cross-checked against DOJ's own disclosure pages.
| DataSet | EFTA range | Contents |
|---|---|---|
| DS01 | 1 β 3,158 | Photos, physical scans |
| DS02 | 3,159 β 3,857 | Photos, seized scans |
| DS03 | 3,858 β 5,586 | Grand jury exhibits |
| DS04 | 5,705 β 8,320 | Records, court filings |
| DS05 | 8,409 β 8,528 | Seized scans, depositions |
| DS06 | 8,529 β 8,998 | Depositions, indictments |
| DS07 | 9,016 β 9,664 | Transcripts |
| DS08 | 9,676 β 39,023 | Emails, police reports |
| DS09 | 39,025 β 1,262,781 | Main email corpus |
| DS10 | 1,262,782 β 2,205,654 | Emails, financial |
| DS11 | 2,205,655 β 2,730,264 | Emails, device data |
| DS12 | 2,730,265 β 2,858,497 | Court filings, FBI + expansion |
DOJ URL pattern: https://www.justice.gov/epstein/files/DataSet%20{N}/EFTA{efta:08d}.pdf
This release attracts conspiracy framings. Every entry in the known-document registry
(efta_known_docs) is confidence-tagged and de-sensationalized:
| Topic | What the documents show |
|---|---|
| Trilateral Commission / CFR | Epstein's own bio listed him as a former member β elite networking, not a plot |
| Rothschild | A real advisory relationship (~$25M Southern Trust agreement); the "Ukraine upheaval" email β EUvsDisinfo flagged the "coup" version as disinformation |
| Rockefeller | A Rockefeller University board seat + donor relationship β institutional, not "bloodline" |
| Illuminati | An inbound, unsolicited email sent to Epstein; no reply on record; not evidence of membership |
| Gates / BGC3 | A real pandemic-preparedness scope document; fact-checkers found no COVID-19 planning link |
- β
Operates only on already-public DOJ releases at
justice.gov/epsteinand a public third-party full-text mirror (epstein-data.com). No private data, no paywalled sources, no scraping behind a login. - β Every claim in the known-document registry carries a source and a confidence tag β a "connection" is labeled for what a document literally shows, never for what a viral caption claims.
- β
efta_run_sqlbroadens what can be queried, not the ethical posture: Datasette's own API only acceptsSELECT(a non-SELECTis rejected with HTTP 400 before it reaches SQLite β verified live), and it reaches no data epstein-data.com doesn't already expose to anyone browsing its site directly. - β Not for re-identification, harassment, or doxxing. This is source-location and verification tooling, not an investigation or accusation engine β it does not allege wrongdoing beyond what a document shows.
- β Not legal advice, not an official DOJ product, and not affiliated with epstein-data.com β an independent client of their public API.
- Python: 3.11+ required (bumped from 3.10 β EOL 2026-10-31). Tested against 3.14.7.
- MCP SDK: pinned
mcp>=1.29.0,<2.0.0. The official SDK's v2.0.0 (2026-07-28) renamedmcp.server.fastmcp.FastMCPtomcp.server.mcpserver.MCPServerβ a breaking change this server hasn't migrated to. An unpinnedmcp>=1.0.0would silently resolve to v2.x and fail to import. The unrelated standalonefastmcpPyPI package (PrefectHQ, now v3.x/4.0) is not a dependency. - pip: install command above runs
python -m pip install --upgrade pipfirst. - requests:
>=2.31.0, no known constraint against newer 2.x releases.
.claude-plugin/plugin.json Plugin manifest (Claude Code convenience only)
.mcp.json Local stdio MCP server config (client-agnostic)
src/efta_core.py DataSet boundary table, EFTA -> URL, known-document registry
src/epstein_datasette.py epstein-data.com Datasette API client (purpose-built + generic layer)
src/doj_auth.py justice.gov public anti-bot challenge helper + verification
src/efta_researcher.py Standalone CLI
src/mcp_server.py FastMCP server exposing the 11 tools above
skills/efta-research/ Claude Code skill: research methodology (optional convenience)
skills/doj-auth/ Claude Code skill: justice.gov access details (optional convenience)
This is a public, single-maintainer research tool (Zereo0317/Epstein-Files-Plugin). Issues and
pull requests are welcome.
MIT-0 (MIT No Attribution) β see LICENSE. Chosen over plain MIT specifically for
ClawHub compatibility, which requires MIT-0 with no per-skill overrides. The repository is public
on GitHub; the license grant governs redistribution/reuse of the code by anyone.
Epstein Files Plugin only surfaces documents the DOJ has already made public under the Epstein Files Transparency Act, plus a public third-party full-text mirror (epstein-data.com) of that same release. It resolves citations to their official source and reports what a document literally contains β it does not conduct original investigation, does not allege wrongdoing beyond what a document shows, and does not host, re-host, or expose any non-public data. Intended for research, fact-checking, and source verification β not re-identification, harassment, or doxxing.