Catalog PyPI
PACKAGE EXPLORERView in registry

acatome-quest-mcp

PyPI

Paper-request MCP: track, resolve, fetch (OA-only), and flag misconceptions for scientific papers

arxivcitationsdoillmmcppapersunpaywall
Versions collected1
Direct dependencies6From release 0.2.0
Last observed20 Oct, 17:52 UTC

README

Version 0.2.0 documentation

acatome-quest-mcp

Paper-request MCP for scientific papers. The missing piece between precis-mcp (navigates what's already in your library) and acatome-extract (ingests PDFs that land in an inbox).

An LLM says "I want this paper" (DOI, arXiv id, title, or free-form citation). Quest:

  1. Checks the store first — no duplicate work if we already have it.
  2. Resolves the metadata via Crossref + Semantic Scholar + arXiv.
  3. Flags misconceptions — broken DOI, DOI↔title mismatch, duplicate of an existing slug, fabrication suspect.
  4. Fetches the PDF from legitimate open-access sources only and drops it into the existing watch inbox, where acatome-extract takes over.
  5. Returns a request id in milliseconds. Slow extraction happens out of band; the MCP call never blocks.

Open access only — by policy

Quest fetches from arXiv, Unpaywall, OpenAlex, Europe PMC, and Semantic Scholar's open-access index only. It does not, will not, and cannot be configured to use Sci-Hub, LibGen, institutional proxies without explicit opt- in, or any other paywall-circumvention mechanism. Failed retrievals yield a needs_user status with the publisher URL, for you to retrieve manually.

Install

pip install acatome-quest-mcp
# or with uv
uv add acatome-quest-mcp

For dedup against a local acatome-store:

pip install 'acatome-quest-mcp[store]'

Four tools

ToolWhat it does
submit(ref, *, dry_run=False, source=None, priority=0, created_by=None)Resolve + optionally queue. Idempotent.
status(id=None, *, filter=None)Read one or many requests.
update(id, mode, **kwargs)Mutate. Modes: confirm, repoint, flag, priority, cancel.
submit_file(url?, content_base64?, filename?, request_id?, ref?, created_by?)Attach a user-supplied PDF (e.g. Discord attachment) to an existing request or create a new one, flip to ingesting.

submit

submit(ref={"doi": "10.1021/jacs.2c01234"})
submit(ref={"title": "Anion exchange membranes for NOx reduction",
            "authors": ["Feng, Z."], "year": 2024})
submit(ref={"raw": "Feng et al. 2024, Adv. Funct. Mater. 34, 2300512"})
submit(ref={"doi": "10.1234/x"}, dry_run=True)      # resolve only, no queue
submit(ref={"doi": "10.1234/x"},
       source={"document": "ch02.tex", "line": 147})

Response:

{
  "id": "9f3b…",
  "status": "found_in_store",
  "resolved": {"doi": "10.1021/jacs.2c01234",
               "title": "…", "authors": ["…"], "year": 2024,
               "ref": "smith2022jacs"},
  "candidates": [],
  "misconceptions": []
}

status

status(id="9f3b…")
status(filter={"status": "needs_user"})
status(filter={"created_by": "asa", "has_misconception": True})
status(filter={"source_document": "ch02.tex"})

update

update(id, mode="confirm", choice=0)            # pick candidates[0]
update(id, mode="repoint", doi="10.1023/A:…")   # user-corrected DOI
update(id, mode="flag", code="retracted",
       evidence="Retraction Watch 2024-08-12")
update(id, mode="priority", priority=5)
update(id, mode="cancel")

submit_file

# User drops a PDF for an already-tracked request (reopens failed / needs_user):
submit_file(url="https://cdn.discordapp.com/…/paper.pdf",
            request_id="7f3a…",
            filename="feng2024.pdf")

# User supplies both a PDF and a DOI in one step (creates the request):
submit_file(url="https://cdn.discordapp.com/…/paper.pdf",
            ref={"doi": "10.1021/jacs.2c01234"},
            created_by="asa")

# Bytes already in memory (no URL to fetch):
submit_file(content_base64="JVBERi0xLjQKJf…",
            request_id="7f3a…")

PDF magic bytes are validated; HTML error pages are rejected. The file is written to the extractor's inbox (~/.acatome/inbox/ by default) and the request flips to ingesting. If the paper's DOI is already in the store, the tool short-circuits to found_in_store without writing anything.

CLI

The acatome-quest binary exposes the same surface as the MCP plus a couple of shell-friendly helpers:

acatome-quest submit 10.1021/jacs.2c01234
acatome-quest status <id>
acatome-quest status --filter status=needs_user
acatome-quest status --filter status=needs_user --count     # just prints "3"
acatome-quest update <id> repoint --doi 10.1023/A:…
acatome-quest submit-file --path ./feng2024.pdf --request-id 7f3a…
acatome-quest submit-file --url https://.../paper.pdf --doi 10.1021/jacs.2c01234
acatome-quest report                                         # markdown worklist
acatome-quest report --document ch04.tex --format markdown   # scoped
acatome-quest runner [--once]
acatome-quest reconcile

report renders a paste-ready markdown document for every request in needs_user, failed, or extract_failed — each entry with citation, DOI/arXiv link, failure reason, misconception evidence, and a concrete suggested action (repoint DOI, drop PDF into ~/.acatome/inbox/, request via interlibrary loan, …). Hand it to a librarian or paste into an ILL form.

Statuses

StatusMeaning
queuedAccepted, not yet fetched
resolvingMetadata lookup in progress (transient)
found_in_storeDedup hit — slug in resolved.ref
needs_userDisambiguation or manual fetch required
fetchingRunner has claimed and is downloading
ingestingPDF in inbox, waiting for acatome-extract watch
ingestedExtraction done, slug in resolved.ref
extract_failedPDF delivered but extraction failed
failedAll sources exhausted
cancelledupdate(mode=cancel) was called

Misconception codes

CodeSeverityTrigger
doi_invalidmajorCrossref 404 or syntactically malformed
doi_truncatedmajor404, but doi + digit resolves
doi_title_mismatchcriticalDOI resolves but title fuzz < 60 vs request
title_not_foundcriticalNo S2/Crossref hit (fabrication suspect)
duplicate_ofminorAlready in store under another slug
retractedcriticalS2 / Retraction Watch flag
preprint_ofinfoarXiv preprint of a later journal paper
pdf_mismatchcriticalUser-dropped PDF resolved to a different paper than the request it was attached to

Architecture

 agent ──submit()──► acatome-quest-mcp (FastMCP, stdio)
                            │
                            ▼
              cluster.papers.requests (Postgres)
                            │
                            ▼
           acatome-quest-runner (launchd, poll 30 s)
                  │
          fetch: arxiv → unpaywall → …
                  │
                  ▼
          ~/.acatome/inbox/<slug>__<hash>.pdf
                  │
                  ▼
          acatome-extract watch  →  acatome-store
                  ▲
                  └── runner polls by DOI, flips to `ingested`

Configuration

Env varDefaultDescription
DATABASE_URLpostgresql://localhost/clusterPostgres DSN
QUEST_SCHEMApapersSchema name for the requests table
ACATOME_INBOX~/.acatome/inboxDrop directory watched by acatome-extract
UNPAYWALL_EMAIL(required at runner start)Polite-pool contact
ACATOME_CROSSREF_MAILTO(recommended)Crossref polite pool
SEMANTIC_SCHOLAR_API_KEY(optional)Raises S2 rate limit
QUEST_POLL_INTERVAL30Runner tick seconds
QUEST_MAX_CONCURRENT4Max parallel fetches
QUEST_INGEST_TIMEOUT900Seconds to wait for ingest after PDF drop
QUEST_MAX_OPEN_PER_AGENT50Per-created_by cap

Development

uv sync
uv run pytest
uv run ruff check .
uv run mypy src tests

License

GPL-3.0-or-later. See LICENSE.

Downloads & popularity

3downloads
1-day window · source-reported counts20 Oct 2026
36180
2026-07-24: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-07-24–2026-07-242026-07-27: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-07-27–2026-07-272026-08-01: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-01–2026-08-012026-08-02: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-02–2026-08-022026-08-03: 10 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-03–2026-08-032026-08-04: 5 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-04–2026-08-042026-08-06: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-06–2026-08-062026-08-09: 3 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-09–2026-08-092026-08-10: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-10–2026-08-102026-08-11: 3 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-11–2026-08-112026-08-13: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-13–2026-08-132026-08-14: 5 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-14–2026-08-142026-08-15: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-15–2026-08-152026-08-17: 6 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-17–2026-08-172026-08-18: 36 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-18–2026-08-182026-08-19: 4 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-19–2026-08-192026-08-20: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-20–2026-08-202026-08-21: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-21–2026-08-212026-08-23: 3 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-23–2026-08-232026-08-24: 9 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-24–2026-08-242026-08-28: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-28–2026-08-282026-08-30: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-30–2026-08-302026-08-31: 3 · observed 2026-10-21T15:54:41.5303589Z · period 2026-08-31–2026-08-312026-09-03: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-03–2026-09-032026-09-05: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-05–2026-09-052026-09-06: 8 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-06–2026-09-062026-09-07: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-07–2026-09-072026-09-09: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-09–2026-09-092026-09-10: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-10–2026-09-102026-09-12: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-12–2026-09-122026-09-17: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-17–2026-09-172026-09-18: 7 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-18–2026-09-182026-09-21: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-21–2026-09-212026-09-23: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-23–2026-09-232026-09-24: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-24–2026-09-242026-09-25: 3 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-25–2026-09-252026-09-26: 7 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-26–2026-09-262026-09-28: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-28–2026-09-282026-09-30: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-09-30–2026-09-302026-10-01: 3 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-01–2026-10-012026-10-03: 3 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-03–2026-10-032026-10-04: 4 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-04–2026-10-042026-10-06: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-06–2026-10-062026-10-07: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-07–2026-10-072026-10-08: 9 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-08–2026-10-082026-10-09: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-09–2026-10-092026-10-10: 4 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-10–2026-10-102026-10-11: 4 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-11–2026-10-112026-10-12: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-12–2026-10-122026-10-13: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-13–2026-10-132026-10-15: 1 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-15–2026-10-152026-10-16: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-16–2026-10-162026-10-17: 6 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-17–2026-10-172026-10-18: 2 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-18–2026-10-182026-10-19: 4 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-19–2026-10-192026-10-20: 3 · observed 2026-10-21T15:54:41.5303589Z · period 2026-10-20–2026-10-20
24 Jul20 Oct

pypistats · 56 observations shown. Missing days are unknown. Source category: overall: without mirrors.

View observed values
Date / source periodValueObserved at
2026-10-20 – 2026-10-2032026-10-21T15:54:41.5303589Z
2026-10-19 – 2026-10-1942026-10-21T15:54:41.5303589Z
2026-10-18 – 2026-10-1822026-10-21T15:54:41.5303589Z
2026-10-17 – 2026-10-1762026-10-21T15:54:41.5303589Z
2026-10-16 – 2026-10-1622026-10-21T15:54:41.5303589Z
2026-10-15 – 2026-10-1512026-10-21T15:54:41.5303589Z
2026-10-13 – 2026-10-1322026-10-21T15:54:41.5303589Z
2026-10-12 – 2026-10-1222026-10-21T15:54:41.5303589Z
2026-10-11 – 2026-10-1142026-10-21T15:54:41.5303589Z
2026-10-10 – 2026-10-1042026-10-21T15:54:41.5303589Z
2026-10-09 – 2026-10-0922026-10-21T15:54:41.5303589Z
2026-10-08 – 2026-10-0892026-10-21T15:54:41.5303589Z
2026-10-07 – 2026-10-0712026-10-21T15:54:41.5303589Z
2026-10-06 – 2026-10-0612026-10-21T15:54:41.5303589Z
2026-10-04 – 2026-10-0442026-10-21T15:54:41.5303589Z
2026-10-03 – 2026-10-0332026-10-21T15:54:41.5303589Z
2026-10-01 – 2026-10-0132026-10-21T15:54:41.5303589Z
2026-09-30 – 2026-09-3012026-10-21T15:54:41.5303589Z
2026-09-28 – 2026-09-2822026-10-21T15:54:41.5303589Z
2026-09-26 – 2026-09-2672026-10-21T15:54:41.5303589Z
2026-09-25 – 2026-09-2532026-10-21T15:54:41.5303589Z
2026-09-24 – 2026-09-2422026-10-21T15:54:41.5303589Z
2026-09-23 – 2026-09-2312026-10-21T15:54:41.5303589Z
2026-09-21 – 2026-09-2112026-10-21T15:54:41.5303589Z
2026-09-18 – 2026-09-1872026-10-21T15:54:41.5303589Z
2026-09-17 – 2026-09-1712026-10-21T15:54:41.5303589Z
2026-09-12 – 2026-09-1212026-10-21T15:54:41.5303589Z
2026-09-10 – 2026-09-1022026-10-21T15:54:41.5303589Z
2026-09-09 – 2026-09-0922026-10-21T15:54:41.5303589Z
2026-09-07 – 2026-09-0712026-10-21T15:54:41.5303589Z
2026-09-06 – 2026-09-0682026-10-21T15:54:41.5303589Z
2026-09-05 – 2026-09-0512026-10-21T15:54:41.5303589Z
2026-09-03 – 2026-09-0312026-10-21T15:54:41.5303589Z
2026-08-31 – 2026-08-3132026-10-21T15:54:41.5303589Z
2026-08-30 – 2026-08-3012026-10-21T15:54:41.5303589Z
2026-08-28 – 2026-08-2812026-10-21T15:54:41.5303589Z
2026-08-24 – 2026-08-2492026-10-21T15:54:41.5303589Z
2026-08-23 – 2026-08-2332026-10-21T15:54:41.5303589Z
2026-08-21 – 2026-08-2122026-10-21T15:54:41.5303589Z
2026-08-20 – 2026-08-2012026-10-21T15:54:41.5303589Z
2026-08-19 – 2026-08-1942026-10-21T15:54:41.5303589Z
2026-08-18 – 2026-08-18362026-10-21T15:54:41.5303589Z
2026-08-17 – 2026-08-1762026-10-21T15:54:41.5303589Z
2026-08-15 – 2026-08-1522026-10-21T15:54:41.5303589Z
2026-08-14 – 2026-08-1452026-10-21T15:54:41.5303589Z
2026-08-13 – 2026-08-1322026-10-21T15:54:41.5303589Z
2026-08-11 – 2026-08-1132026-10-21T15:54:41.5303589Z
2026-08-10 – 2026-08-1012026-10-21T15:54:41.5303589Z
2026-08-09 – 2026-08-0932026-10-21T15:54:41.5303589Z
2026-08-06 – 2026-08-0622026-10-21T15:54:41.5303589Z
2026-08-04 – 2026-08-0452026-10-21T15:54:41.5303589Z
2026-08-03 – 2026-08-03102026-10-21T15:54:41.5303589Z
2026-08-02 – 2026-08-0212026-10-21T15:54:41.5303589Z
2026-08-01 – 2026-08-0112026-10-21T15:54:41.5303589Z
2026-07-27 – 2026-07-2712026-10-21T15:54:41.5303589Z
2026-07-24 – 2026-07-2422026-10-21T15:54:41.5303589Z

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.2.020 Apr 20266

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
retospect/acatome-quest-mcp

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 17:52 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:2ac5850761f973e8f7a2a9c7918cbbd0b2389419e8249de0ca12ed98284c5346