farr-cite
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@farr-citeFind evidence in my library for the claim that random seed recording aids reproducibility."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
farr-cite
farr-cite keeps a searchable library of research papers on your own computer. It finds the passages in those papers that support a claim, and it writes a citation only for a paper that is actually in the library. Ask it to cite anything else and it refuses, so an invented or misremembered reference cannot slip into a manuscript.
It is a command-line tool and an MCP server (so an AI assistant can use the same library, under the same rules). It runs entirely on your machine; the only network calls are to the open scholarly services named below.
Quickstart (5 minutes)
You need Python 3.10 or newer. No PDF of your own is needed: the example paper is fetched under its open licence.
pip install farr-cite
farr-cite init --email you@example.org # use your real address; the open services ask for one
farr-cite fetch 10.1371/journal.pcbi.1003285
farr-cite search "random seed"
farr-cite evidence "record the random seed of every analysis"
farr-cite cite 10.1371/journal.pcbi.1003285
farr-cite cite 10.1000/not-heldUntil the first release is on PyPI, install from a clone instead: pip install . in this folder.
What you should see:
fetchreportsdownloaded under cc-by from europepmc. The example is Sandve et al. (2013), Ten Simple Rules for Reproducible Computational Research, PLOS Computational Biology, published under CC BY 4.0.searchandevidencelist passages, each with its citation key, section and DOI.The first
citeprints the reference and an inline form,(Sandve et al., 2013).The second
citeprintsREFUSED: 10.1000/not-held is not in your library ...and exits 1.
To add papers you already have:
farr-cite add paper.pdf --doi 10.xxxx/yyyy # metadata comes from Crossref
farr-cite add papers/ # every PDF; each DOI is read from its first pages
farr-cite add paper.pdf --doi 10.xxxx/yyyy --no-metadata --title "..." --authors "Family, Given; Family, Given" --year 2020The library lives in ~/.farr-cite (or wherever FARR_CITE_HOME or --home points).
Related MCP server: ResearchMCP
Commands
Command | What it does |
| create the library; store the contact email the open services ask for |
| add your own PDFs (or JATS XML) |
| download an openly licensed paper; refuse anything else |
| full-text and author search; every passage names its paper |
| the passages that best match a claim, at most two per paper |
| a paper's sections, or the text of one |
| a citation for a held DOI; refusal for any other |
| check every citation in a draft |
| retrieval benchmark: recall@k and MRR |
| what is held; remove a paper |
| run the MCP server on stdio |
Every command takes --json. Exit codes: 0 success, 1 a verdict (a refusal, a problem in a
draft, nothing fetched), 2 a usage or configuration error.
How it works
Text is extracted with pypdf (or read from JATS XML, the format open-access archives publish in), split into sections where a heading can be recognised ("Introduction", "2. Methods", "Results and Discussion" ...) and into passages of about 120 words. Reference lists are not indexed: a bibliography is not evidence. Passages are indexed with SQLite FTS5 and ranked by BM25, with the title and author names searchable alongside the text. Metadata (title, authors, year, journal) comes from Crossref by DOI. Section detection on PDFs is a heuristic; a PDF with unusual headings ends up with fewer, larger sections, and its text is still searchable.
The refuse-to-cite rule
cite returns a citation only for a DOI the library holds. For any other DOI it refuses, says
so plainly, and exits 1:
REFUSED: 10.1000/not-held is not in your library, so farr-cite will not write a citation for it.
Do not cite it from memory. Add it first (...), or mark the claim [CITATION NEEDED].This refusal is the point of the tool. A citation written from memory, by a person or by a
language model, looks exactly like a real one; the only reliable test is whether the paper is in
hand. Because a held paper's text is in the library, the claim it is cited for can also be
checked with evidence or sections before it goes into a manuscript.
check applies the same rule to a whole draft. It finds every DOI and every pandoc-style
[@key] citation (keys are the ones cite prints, such as sandve2013, or come from a BibTeX
file passed with --bib) and reports, with line numbers:
held: in the library;
not held: a DOI the library does not have;
unknown key: a
[@key]that matches nothing;published after the citing year: a held paper whose year is later than the draft's own year, given with
--yearor asyear:in the draft's YAML front matter. A paper cannot cite work that did not exist yet; this usually means a wrong DOI or a mixed-up version.
It exits 0 only when every citation is held and none is from the future.
The open-access-only rule
fetch downloads a paper only when an open licence is recorded for the exact copy it
downloads. It asks four official open services, in this order:
arXiv, for
10.48550/arXiv.*DOIs: the licence the authors chose on submission.Europe PMC / PubMed Central: the licence of the open-access copy; the full text is downloaded as JATS XML and the licence stated inside the file is checked again.
Unpaywall: every open location carries its own licence and version; only a location with an open licence and a direct PDF link is used.
Crossref: a licence record and a full-text link are used together only when they name the same content version and any embargo has ended.
Open means a Creative Commons licence (CC BY, CC BY-SA, CC BY-NC, CC BY-ND and their combinations) or CC0 / public domain. "Free to read", publisher-specific and "implied" licences are not open, and neither is arXiv's default distribution licence.
If none of the four records an open licence, fetch refuses: the paper is not openly
licensed. There is no second route. farr-cite has no proxy or VPN support, reads no publisher
web pages, and has no login, cookie, institutional-access or EZproxy path; its HTTP client
ignores proxy settings in the environment. It runs from your own connection, identifies itself
with the contact email you configured, and keeps each service's pace (one request per second to
Crossref and Unpaywall, one every three seconds to arXiv).
Why so strict: a tool that quietly falls back to paywalled copies puts its users in breach of
publisher terms and of their institution's licence agreements, usually without their knowing.
For a paper that is not openly licensed, use your own copy and farr-cite add it.
MCP server
pip install "farr-cite[mcp]"Then register it with your MCP client, for example in a project's .mcp.json:
{"mcpServers": {"farr-cite": {"command": "farr-cite", "args": ["mcp"]}}}Tools: search, evidence, sections, cite, check, fetch, stats. They follow the same
rules as the command line: cite returns an error object for an unheld DOI, and fetch refuses
anything not openly licensed. Use --home before mcp to serve a library other than the
default.
Benchmark
bench measures how well evidence finds the right passage. A question set is a JSON file:
{"questions": [{"id": "seeds", "q": "why record the random seed ...",
"doi": "10.1371/journal.pcbi.1003285", "section": "Rule 6"}]}A returned passage counts as a hit when it comes from that DOI and its section name contains
section (omit section to accept any passage from the paper). For each question, the rank of
the first hit is recorded. recall@k is the share of questions with a hit in the top k;
MRR (mean reciprocal rank) is the average of 1/rank, counting 0 when there is no hit.
The repository ships an example set: 15 questions over three CC BY 4.0 papers. No paper is
committed; examples/bench/papers.txt lists the DOIs and fetch.sh downloads them through
farr-cite fetch, which re-checks each licence.
farr-cite init --email you@example.org
examples/bench/fetch.sh
farr-cite bench examples/bench/questions.jsonMeasured with version 0.1.0: recall@1 0.800, recall@5 0.933, recall@10 1.000, MRR 0.858. This is a small smoke test of the ranking, not a claim about retrieval quality in general; build a set from your own papers to measure what matters to you.
Development
pip install -e ".[dev]"
python -m pytest -qThe tests run offline: they build a library from small PDFs generated inside the tests and mock every HTTP call.
Licence
Apache-2.0. See LICENSE and NOTICE. Papers you fetch or add keep their own licences.
This server cannot be deployed
Maintenance
Related MCP Connectors
Academic literature search, retrieval, and private library management on top of OpenAlex.
Federated search of books and papers, BibTeX/RIS citations, open-access retrieval and reading.
Search arXiv/Semantic Scholar/OpenAlex + medical evidence (PubMed/Europe PMC) + LaTeX/PDF tools.
Search peer-reviewed papers and research methodology guidance from your AI agent.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA local-first database and assistant layer for organizing, analyzing, and retrieving research papers efficiently.-
- FlicenseNot gradedqualityBmaintenanceEnables LLMs to search arXiv, extract and analyze paper content, and build a personal semantically-searchable research library with saved papers and notes.-
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to browse, search, and retrieve papers from a local research library with read-only access, supporting multiple formats and automatic indexing.2MIT
- FlicenseAqualityCmaintenanceEnables Claude to search a local hybrid retrieval index of research papers and ingest new PDFs, providing research-paper memory queryable directly through natural language.2-