Canonical: https://thonly.org/research/mcp · Licence: CC0 1.0
The corpus is served over MCP at https://corpus.333.eco/mcp. There is no account, no key and no rate limit to negotiate.
{ "mcpServers": { "corpus": { "url": "https://corpus.333.eco/mcp" } } }
Or run it on your own machine, fully offline once downloaded. The package has no dependencies at all — not even an MCP SDK — and needs Node 20 or newer.
{ "mcpServers": { "corpus": { "command": "npx", "args": ["-y", "@333eco/corpus"] } } }
Most clients take one of those blocks; consult your own client's documentation for where it goes. The two surfaces answer identically, and a check in the server's own build fails if they ever advertise different tools or give different answers to the same call.
| Tool | What it does |
|---|---|
search_corpus | Full-text search, with diacritics optional (metta finds mettā). Returns matching documents with an excerpt and a provenance envelope — not the full text — and a line naming the call that reads them in full. |
get_document | One document in full, behind its provenance header and ending at its [END OF DOCUMENT] line. |
read_documents | Whole documents at once: a shelf (the same filters as list_documents) or a list of slugs, one block per document, paged by size and never splitting a document. |
list_documents | Slugs, titles, genres, licences, provenance summaries and each document's size in bytes and words. Filter by genre, topic category, voice or licence; the response names the read_documents call for what it listed. |
check_passage | Whether a passage is served — verbatim, with the same words, or not — and for a near miss, the nearest served passage and exactly how the two differ. It judges the passage, never who quotes it. |
list_predictions | The pre-registered predictions of the research programme, with each one's registered falsifier and current status. |
get_prediction | One prediction by identifier, with the envelope of the paper that registered it. |
get_program | The programme's hard core, chapters, stopping rule and its own count reconciliation, verbatim. |
The last three appear only where the served index carries a research programme; an index built over a corpus without one advertises five tools, not eight.
Search answers from excerpts; a model answers from what it opened. For a broad question, read the relevant shelf in full — the listing reports sizes first, so a caller can see whether it fits. Every document ends with an [END OF DOCUMENT] line, by every route: the server never cuts a document, but a client may, and a cut document reads as a complete one.
One move in this API is genuinely not obvious, and it is deliberate: a prediction resolves to its stating paper's envelope, not the register's. A prediction's authority is the document that registered it before the data existed. The register is an index, and an index is not evidence.
Every document is also addressable as a resource at corpus://{slug}. A resource read returns the provenance header first, then the document verbatim and its end line, so a client that hands the contents straight to a model passes the proof along with the text.
Three prompts ship, and they are worked examples of the API rather than instructions about the subject matter: orient (what is in this corpus), verify_a_quote(slug) (the verification path, end to end), and what_would_falsify(claim) (find a registered falsifier and resolve it to its stating paper). The slug argument is completable, because a prompt argument nobody can autocomplete is only usable by someone who already knows the answer.
Every document arrives behind a provenance header, and every search and listing result carries the same envelope as structured data: the document's SHA-256, its DOI where one exists, an OpenTimestamps proof anchored in the Bitcoin blockchain, and the exact command that checks them — so a passage can be verified before it is cited, rather than taken on the strength of the channel it arrived over.
"provenance": {
"sha256": "d6ac93f9…50ecc3c",
"doi": "10.5281/zenodo.22440983",
"concept_doi": "10.5281/zenodo.22240458",
"source_url": "https://raw.githubusercontent.com/thonly/publications/main/…",
"sha256_covers": "the complete source file at source_url, including its
metadata block — NOT the `text` field in this response",
"opentimestamps": true
}
That sha256_covers line matters more than it looks. The hash covers the whole source file at source_url, not the text you were served — so hashing the response will not reproduce it. Fetch the named source and hash that:
curl -sL <source_url> | shasum -a 256 # compare with provenance.sha256
ots verify <path>.ots # in the source repository
A verifiable claim that requires you to already know where the file lives is not one. The envelope names the location so that closing the loop is a single command.
It never summarises. Text is returned verbatim, always. This is not a preference: a summary cannot be hash-verified, so summarising at the server would destroy the only property the server has. A retrieval service that asserts is an authority, and it propagates its errors; one that exposes is a witness, and it is caught by the first reader who bothers.
It proves bytes, not truth — and not currentness. A timestamp establishes that this exact text existed no later than its date. It says nothing about authorship, originality, or whether any claim in the document is correct. And a genuine, anchored, superseded version verifies perfectly: the anchors order versions by age, not by canonicality. Fetch the named source and compare if what you need is the current text.
Nothing goes missing silently. The index build records every file it considered and what became of it — served, excluded with a reason, or held — and refuses to finish unless the three add up. Both servers refuse to serve a corpus that does not match that manifest, which is public at corpus.333.eco/manifest.json. It detects a dropped document, not a tampered one; the SHA-256 is the other half.
The licence gate is in the builder, not the request path. The server has no filesystem access to the corpus at all — it can only serve what the index already contains. A file that declares no licence is excluded and reported, never assumed public domain, and a document under CC-BY carries attribute_to in its licence block. A gate a refactor can route around is a rule; a gate in the artifact is a property.
The hosted endpoint counts calls by the client software's own name from its handshake — never an IP address, never any identifier derived from one, never a per-caller id of any kind. The only search text ever stored is a search that matched nothing, because the reason to keep a query is to learn what the corpus lacks; a successful search says only what someone was reading.
The npm package records nothing and sends nothing. Its two report commands, --report-gap and --report-bug, send only when you type them, and print the whole payload before the request.
The endpoint discloses all of this itself, under records, at corpus.333.eco — readable before you call anything. A privacy policy is a page someone has to go and find.
The argument, and its limits, are published as Provenance-Carrying Retrieval — including what the mechanism does not establish. The server's source is at github.com/333eco/corpus.333.eco.