Skip to main content

Claude Science + MCP

CiteProof MCP tool reference

This page documents all 24 tools in CiteProof MCP 0.1.0. Each entry lists the arguments, the limits the server enforces, and a realistic request and result. The tool names, fields and caps mirror the shipped schemas.

The division of labour

Claude Science searches, reads and writes. CiteProof MCP stores the protocol, PRISMA counts, screening decisions, extracted evidence, claims and risk-of-bias judgements, validates their shape, checks supplied quotes and computes the counts. The server contains no language model and does not search for papers.

How Claude Science and CiteProof MCP fit together

A research agent can draft a systematic review, but the decisions behind the draft need a record: why a paper was excluded, which studies were included, what each study reported, and whether the cited sentence appears in the source. CiteProof MCP is that record.

Claude Science: research agent

Runs searches, retrieves papers, reads full text, makes inclusion and exclusion judgements, extracts results, grades risk of bias and drafts the report. Every scientific judgement comes from the agent or its human reviewer.

CiteProof MCP: audit layer

Stores those judgements in a local review file, rejects malformed input, checks that quotes appear in the supplied text, computes deduplication and PRISMA counts, and exports the audit trail.

The MCP server is a separate open-source component. It is not part of a CiteProof web account, it does not consume DeepSearch or Research Mode runs, and it needs no model API key.

Architecture and data flow

1. Research agent Claude Science searches, reads and decides. It supplies each decision and, where required, the source text and quote.
2. CiteProof MCP A local stdio server validates arguments, checks quotes, computes counts and writes one SQLite review file.
3. Audit output review_status reports gaps and next steps. export_bundle returns one Markdown or JSON document.

Each review is one SQLite file at <CITEPROOF_MCP_HOME>/reviews/<review_id>.db. Writes use one immediate transaction with a 30 second busy timeout, so concurrent calls wait instead of failing with a locked database. Read tools never change the record.

Every tool returns JSON with an ok boolean. A successful result adds tool-specific fields. A handled failure returns {"ok": false, "error": "..."}.

What the server does not do

  • It does not search literature, query a database or open a paper. The agent supplies every record.
  • It does not contain an LLM and does not make inclusion, extraction, claim or risk-of-bias judgements.
  • It does not prove that a study is valid, that a claim is scientifically true or that a review is complete.
  • It does not turn a resolved DOI into evidence. A registered DOI only proves that the identifier exists; citation matching is called resolved, never verified.
  • It does not write exports to disk and does not upload review data. Exports are returned as text for the client to save.
  • claude.ai web custom connectors cannot start a local stdio process, so they are not supported.

Connect CiteProof MCP to Claude Science

Claude Science on Windows 11 is the tested path for this release (Claude Science 0.1.67, native sandbox). The connector runs inside a Windows sandbox that can read only its own workspace folder and Claude Science's bundled runtime. That is why the Claude Science install copies the server into the connector workspace instead of pointing at a project virtual environment.

Prerequisites

  • Claude Science with Connectors available under Customize.
  • This repository checked out, for the bundle build script. The script uses only the Python standard library.
  • No separate Python install for the connector. The bundled python3 already provides mcp, pydantic and httpx.
  • No model API key. The server makes no model calls.

Install the Claude Science connector

  1. Create the connector workspace. Open Customize, then Connectors, then Add connector, then Local command. Name it citeproof and use python3 placeholder.py. It will fail; the first start creates the workspace folder. If the folder does not appear, create it by hand in the next step.
  2. Find the workspace folder. On Windows it is C:/Users/<you>/.claude-science/orgs/<org-id>/workspaces/_mcp-citeproof. The command claude-science logs also prints it as cwd in the sandbox policy lines.
  3. Build the bundle into that folder. Run the command below from the repository root. The script refuses a folder that holds other files, so passing the workspace folder by mistake cannot delete your data folder.
  4. Point the connector at the bundle. Remove the placeholder and add it again. Use forward slashes in the command; backslashes are stripped by the form.
  5. Set the data folder. Add the environment variable CITEPROOF_MCP_HOME so review files stay inside the sandbox workspace.
  6. Confirm 24 tools. The connector page should list every tool from review_create to export_bundle. Claude Science asks for approval before each tool run by default; set a tool to always allow only after you trust it.
python MCP/scripts/build_claude_science_bundle.py "C:/Users/<you>/.claude-science/orgs/<org-id>/workspaces/_mcp-citeproof/bundle"
python3 C:/Users/<you>/.claude-science/orgs/<org-id>/workspaces/_mcp-citeproof/bundle/run.py
CITEPROOF_MCP_HOME=C:/Users/<you>/.claude-science/orgs/<org-id>/workspaces/_mcp-citeproof/data

After a new release, run the build script again into the same bundle folder, then remove and re-add the connector with the same settings. The running process keeps old code in memory, and the Connectors page has no restart button when the connector is healthy. Review data in the data folder survives this.

Confirm the tools are available

Ask the client to list its tools, or open the connector details. A healthy install shows 24 tools with the names on this page. If fewer appear, an older server process is still running: remove the connector and add it again.

The first useful call is review_create. If it succeeds, the server is running and can write to CITEPROOF_MCP_HOME.

Installing is not using

A successful install only makes the tools callable. It does not create a review, run a search or add records. Ask Claude Science to follow the workflow on this page, or give it the instruction “use CiteProof MCP for the review record and call review_status before moving to the next stage”.

Claude Desktop extension and npx

Two other local install paths are available. Both start the same server over stdio and use the same review format.

New

Claude Desktop extension

Download citeproof.mcpb from the latest release, then open it with Claude Desktop. The extension uses Claude Desktop's built-in Node and installs uv automatically if it is missing.

Open the latest release

New

npx configuration

For Claude Desktop, Claude Code and other JSON-config clients, add the entry below. Node 18 or newer is required.

{
  "mcpServers": {
    "citeproof": {
      "command": "npx",
      "args": ["-y", "citeproof-mcp"]
    }
  }
}

For Claude Code, the equivalent command is:

claude mcp add citeproof -- npx -y citeproof-mcp

The launcher installs uv automatically when it is missing, and uv fetches Python 3.12 on first run. Set CITEPROOF_NO_AUTO_INSTALL=1 to opt out and manage uv yourself. Review data goes to ~/.citeproof-mcp unless CITEPROOF_MCP_HOME is set.

Use one data folder per client

If two clients should share reviews, give them the same CITEPROOF_MCP_HOME. Do not point two servers at the same review file and expect independent writers; writes serialise on the SQLite file.

Follow the end-to-end review workflow

The order matters because later tools read earlier records. Run review_status at any point to learn the current phase and what is missing.

Stage What to do Tools
1. Create or recover Create the review file, or list existing reviews and reuse a review_id. review_create, review_list
2. Protocol Record the question, populations, outcomes, eligibility and search plan before screening. protocol_record
3. Searches Record one row per database, query and run date, with the hit count. prisma_record_search
4. Deduplication Deduplicate the complete exported set and record the count. A partial batch is analysed but not recorded. dedup_papers, prisma_record_dedup
5. Screening Screen titles and abstracts, then full text. Record each reviewer under their own name, compute agreement, then record consensus under primary. screening_record, screening_record_many, screening_list, screening_agreement, prisma_status
6. Evidence Record one row per paper and outcome with the quote and the source text used to check it. evidence_record, evidence_table
7. Risk of bias Record each domain for the chosen tool, then compute the overall judgement by the published rule. rob_record, rob_summary
8. Claims Record each key claim with a label, reason and quote, then find weak claims in the draft. claim_record, claim_report
9. Citations Check DOIs against Crossref and doi.org, and resolve author-year citations against the paper list. verify_dois, resolve_citations, lint_prose
10. Report and export Render the flow diagram, check the draft against the PRISMA checklist, then export the audit bundle. prisma_flow_diagram, prisma_checklist, export_bundle, review_status

When you resume a review in a new session, call review_status first. It reports the phase, missing protocol fields, PRISMA completeness, reviewer names, included studies, extraction and risk-of-bias coverage, claim counts, DOI checks and source-text changes.

Tool reference

Arguments marked optional may be omitted. Every result also has ok. List results are capped at 200 items unless the entry says otherwise, and a cut list sets truncated: true. Paper references use the forms described in Paper identity; use the same form for a paper in every tool.

Review setup and core checks

review_create

Creates a review file and returns its identifier. Every other tool needs that review_id.

ArgumentTypeRequiredNotes
titlestringYesMaximum 500 characters.
questionstringYesMaximum 2,000 characters.
year_minintegerNo1800 to 3000. Must not exceed year_max.
year_maxintegerNo1800 to 3000. Must not be below year_min.

Limits. The id is generated by the server and matches ^[a-z0-9_-]{6,40}$. Creating a review never reuses an existing file.

Example request.

{"title": "Teleradiology turnaround times: a systematic review", "question": "In adults, what is the effect of teleradiology on radiology report turnaround time?", "year_min": 2010, "year_max": 2026}

Example result.

{"ok": true, "review_id": "rev-9f3c2a1b", "next_step": "Record the protocol with protocol_record (PICO, eligibility criteria, databases, search strategy)."}

review_list

Lists review files in the current CITEPROOF_MCP_HOME, newest first. Use it to recover an id when you resume work.

ArgumentTypeRequiredNotes
limitintegerNoDefault 50. Capped at 200.

Example request.

{"limit": 10}

Example result.

{"ok": true, "reviews": [{"review_id": "rev-9f3c2a1b", "title": "Teleradiology turnaround times: a systematic review", "question": "In adults, what is the effect of teleradiology on radiology report turnaround time?", "created_at": "2026-10-25T09:14:00Z", "year_min": 2010, "year_max": 2026}], "count": 1}

verify_dois

Checks DOIs against Crossref and doi.org. This is the only tool that uses the network. With a review_id, the results are saved for review_status and export_bundle.

ArgumentTypeRequiredNotes
doisarray of strings, or one stringYesUp to 100 DOIs. One string may separate DOIs with spaces, commas or new lines. doi: and doi.org prefixes are normalised; duplicates are removed case-insensitively.
review_idstringNoSaves the result. The review must exist.

Status. resolved means the registry returned a record. not_found means doi.org returned 404. unverified means the registry could not be reached, so there is no verdict. invalid means the value was not DOI-shaped and was never sent. retracted is true or false only for Crossref records.

Limits. Fixed HTTPS hosts, no redirect following, 15 second timeout. A redirect from doi.org is read as registered. No other host is contacted.

Example request.

{"dois": ["10.1136/bmj.n71", "https://doi.org/10.1371/journal.pmed.1003583"], "review_id": "rev-9f3c2a1b"}

Example result.

{"ok": true, "results": [{"doi": "10.1136/bmj.n71", "input": "10.1136/bmj.n71", "status": "resolved", "title": "The PRISMA 2020 statement: an updated guideline for reporting systematic reviews", "year": 2021, "journal": "BMJ", "authors": "Page MJ, McKenzie JE, Bossuyt PM", "retracted": false, "registry": "crossref"}, {"doi": "10.1371/journal.pmed.1003583", "input": "https://doi.org/10.1371/journal.pmed.1003583", "status": "resolved", "title": "PRISMA 2020 explanation and elaboration", "year": 2021, "journal": "PLOS Medicine", "authors": "Page MJ, Moher D, Bossuyt PM", "retracted": false, "registry": "crossref"}], "summary": {"checked": 2, "resolved": 2, "not_found": 0, "unverified": 0, "invalid": 0, "retracted": 0}, "offline": false, "saved": true, "note": "Registry lookups only: a resolved DOI is real, which says nothing about whether it supports a claim."}

resolve_citations

Matches inline citations in a draft against a supplied paper list. It rewrites common author-year forms such as Smith et al. (2020), (Smith 2020) and (Smith, 2020a) before matching. Groups that contain a DOI or URL are left alone.

ArgumentTypeRequiredNotes
textstringYesThe draft or section to check.
papersarray of objectsYesUp to 2,000 papers. Each object has title, authors (list or A; B) and year; doi is optional.

Result notes. resolved excludes ambiguous matches. Numeric citations such as [1] are counted, not resolved. orphan_papers lists papers in the supplied list that the text never cites.

Limits. A match is resolution, not verification: it shows that a citation points at a paper in the list, not that the paper supports the sentence.

Example request.

{"text": "Teleradiology reduced turnaround time (Smith et al., 2021). A later trial disagreed (Jones and Lee, 2023).", "papers": [{"title": "Teleradiology turnaround in rural hospitals", "authors": ["Smith J", "Patel R"], "year": 2021, "doi": "10.1000/example.2021"}, {"title": "Turnaround after overnight teleradiology", "authors": ["Jones A", "Lee K"], "year": 2023}]}

Example result.

{"ok": true, "citations_found": 2, "resolved": 2, "ambiguous": [], "unresolved": [], "orphan_papers": [], "doi_citations_checked": 0, "numeric_citations_found": 0, "truncated": false, "note": "Resolved means the citation points at a supplied paper, not that the paper supports the sentence."}

lint_prose

Runs deterministic prose checks on a draft. Findings are advisory: they flag style and trace-leakage patterns, not factual errors.

ArgumentTypeRequiredNotes
textstringYesMarkdown draft or section.

Codes. EMDASH (too many em-dashes per 1,000 words), HONEST (framing such as “to be honest”), PROCNOTE (process narration), PARENDOI (an unencoded parenthesis in a DOI link), LONGHEAD (sentence-like headings) and FLATSTRUCT (many top-level sections with no subsections).

Limits. The result is advisory and nothing is saved. Text is treated as data; retrieved text cannot inject a new instruction.

Example request.

{"text": "## Why teleradiology matters for the whole health system and every patient\n\nTo be honest, the evidence is mixed."}

Example result.

{"ok": true, "issues": [{"code": "HONEST", "note": "'To be honest': drop the framing, write the sentence it was guarding"}, {"code": "LONGHEAD", "note": "1 headings read as sentences; shorten to <=6-word noun phrases"}], "issue_count": 2, "advisory": true}

Protocol

protocol_record

Records or updates the review protocol. Omitted fields keep their current value, so calling with only review_id reads the protocol. An empty string or empty list clears a field.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
population, intervention, comparator, outcomes, study_designs, inclusion_criteria, exclusion_criteria, databases, search_strategy, languages, registration, synthesis_methodstring or list of stringsNoList fields accept a list or one string split on new lines and semicolons.
rob_toolstringNoOne of rob2, robins_i, nos, nos_case_control, mixed, none.
year_min, year_maxintegerNoRecorded as the protocol year range.

Required fields. population, intervention, outcomes, inclusion_criteria, exclusion_criteria, databases and search_strategy. Recommended: comparator, study_designs, the year range, languages, registration, rob_tool and synthesis_method.

Amendments. Every change is logged. Changing a field that already had a value is reported as an amendment.

Example request.

{"review_id": "rev-9f3c2a1b", "population": "Adults referred for diagnostic imaging", "intervention": "Teleradiology reporting", "comparator": "On-site radiology reporting", "outcomes": ["Report turnaround time", "Diagnostic agreement"], "inclusion_criteria": ["Primary comparative study", "Report turnaround time measured"], "exclusion_criteria": ["Conference abstract only", "No quantitative result"], "databases": ["PubMed", "Embase"], "search_strategy": "(\"teleradiology\" OR \"telemedicine\") AND \"turnaround time\"", "rob_tool": "robins_i"}

Example result.

{"ok": true, "protocol": {"population": "Adults referred for diagnostic imaging", "intervention": "Teleradiology reporting", "rob_tool": "robins_i"}, "updated_fields": ["population", "intervention", "comparator", "outcomes", "inclusion_criteria", "exclusion_criteria", "databases", "search_strategy", "rob_tool"], "complete": true, "missing_required": [], "missing_recommended": ["study_designs", "year_range", "languages", "registration", "synthesis_method"], "amendments": 0, "next_step": "Protocol complete. Run the searches and log each one with prisma_record_search."}

PRISMA and screening

Records one database search. The same source, query and run date replaces the hit count instead of adding a row, so a retried call cannot double-count.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
sourcestringYesDatabase name, matched case-insensitively.
querystringYesThe query as run.
date_runstringYesA real YYYY-MM-DD date. A future date is a warning.
hitsintegerYesRecords returned by this search.

Important. Adding a search or changing a hit count clears the review's deduplication record, because the old count belonged to a different set of records. The result says so in warnings. Re-sending the same search with the same hits changes nothing.

Example request.

{"review_id": "rev-9f3c2a1b", "source": "PubMed", "query": "teleradiology AND turnaround time", "date_run": "2026-10-20", "hits": 412}

Example result.

{"ok": true, "search_id": 1, "updated": false, "records_identified": 412, "records_by_source": {"PubMed": 412}, "searches_recorded": 1, "warnings": []}

dedup_papers

Detects duplicate records in an exported set. Same paper means the same normalised DOI, the same PMID, or the same normalised title of at least 20 characters with the same year and first-author surname. Matching is transitive.

ArgumentTypeRequiredNotes
papersarray of objectsYesUp to 10,000 exported records. Fields: id, doi, pmid, title, year, authors or first_author, abstract.
review_idstringNoRecords the count only when the call covers every exported record.

Recording rule. The count is saved only when review_id is given. A partial or batched call is saved too, with a warning that records_checked does not match the total hits from prisma_record_search. A count larger than the recorded hits is refused, and an earlier record is replaced.

What is kept. The record with the most complete metadata is kept. Records are not merged, so copy any field you need from a removed record before discarding it. A same-title record with a different year or author is listed in possible_duplicates instead of merged.

Example request.

{"review_id": "rev-9f3c2a1b", "papers": [{"id": "p1", "doi": "10.1000/example.2021", "title": "Teleradiology turnaround in rural hospitals", "year": 2021, "first_author": "Smith"}, {"id": "p2", "pmid": "12345678", "title": "Teleradiology turnaround in rural hospitals", "year": 2021, "first_author": "Smith"}, {"id": "p3", "doi": "10.1000/example.2023", "title": "Turnaround after overnight teleradiology", "year": 2023, "first_author": "Jones"}]}

Example result.

{"ok": true, "records_checked": 3, "unique_records": 2, "duplicates_removed": 1, "removed_indices": [1], "clusters": [{"kept_index": 0, "kept_id": "p1", "member_indices": [0, 1], "matched_on": ["title_year_author"], "conflicting_dois": false}], "possible_duplicates": [], "truncated": false, "recorded": true, "method": "dedup_papers: exact DOI, then PMID, then normalised title + year + first-author surname", "warnings": ["3 records were checked but the recorded searches total 412 hits; send every exported record so the PRISMA counts add up."]}

prisma_record_dedup

Records a whole-review duplicate count when deduplication was done elsewhere, for example in a reference manager. It replaces any existing dedup record.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
duplicates_removedintegerYesCannot exceed the recorded hits.
methodstringYesShort description of how duplicates were found.

Example request.

{"review_id": "rev-9f3c2a1b", "duplicates_removed": 87, "method": "Zotero duplicate merge, then manual title check"}

Example result.

{"ok": true, "duplicates_removed": 87, "records_identified": 412, "records_after_dedup": 325, "method": "Zotero duplicate merge, then manual title check"}

screening_record

Records one screening decision for one reviewer at one stage. Recording the same paper, stage and reviewer again updates the decision.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
paper_refstringYesDOI, pmid:<digits> or title:<title>|<year>.
stagestringYestitle_abstract or full_text.
decisionstringYesinclude or exclude; at full text also not_retrieved.
reasonstringFor excludeMaximum 300 characters.
reviewerstringNo1 to 40 characters, stored lower-case. Default primary.
titlestringNoOptional paper title for display.

Warnings. A full-text decision without a title/abstract include is flagged, and so is a title/abstract exclusion of a paper that already has a full-text decision.

Example request.

{"review_id": "rev-9f3c2a1b", "paper_ref": "10.1000/example.2021", "stage": "title_abstract", "decision": "include", "reviewer": "primary", "title": "Teleradiology turnaround in rural hospitals"}

Example result.

{"ok": true, "updated": false, "paper_ref": "10.1000/example.2021", "stage": "title_abstract", "reviewer": "primary", "decision": "include", "stage_counts": {"include": 48, "exclude": 277, "not_retrieved": 0}, "warnings": []}

screening_record_many

Records up to 500 screening decisions in one all-or-nothing call. An invalid item or a repeated paper, stage and reviewer returns an error with the item index, and nothing is written.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
decisionsarray of objectsYesUp to 500 items with the same fields as screening_record.

Limits. Repeated (paper_ref, stage, reviewer) triples are rejected instead of silently overwriting. Use screening_record to update one decision.

Example request.

{"review_id": "rev-9f3c2a1b", "decisions": [{"paper_ref": "10.1000/example.2023", "stage": "title_abstract", "decision": "exclude", "reason": "No turnaround time outcome", "reviewer": "secondary"}, {"paper_ref": "pmid:12345678", "stage": "title_abstract", "decision": "include", "reviewer": "secondary"}]}

Example result.

{"ok": true, "count": 2, "inserted_count": 2, "updated_count": 0, "warning_count": 0, "warnings": []}

screening_list

Lists screening decisions, newest first, with filters and offset paging.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
stagestringNotitle_abstract or full_text.
reviewerstringNoFilter by reviewer name.
decisionstringNoinclude, exclude or not_retrieved.
paper_refstringNoFilter by one paper.
limitintegerNoDefault 200, capped at 200.
offsetintegerNoDefault 0.

Example request.

{"review_id": "rev-9f3c2a1b", "stage": "full_text", "reviewer": "primary", "limit": 50}

Example result.

{"ok": true, "records": [{"paper_ref": "10.1000/example.2021", "stage": "full_text", "reviewer": "primary", "decision": "include", "reason": null, "title": "Teleradiology turnaround in rural hospitals", "updated_at": "2026-10-24T16:02:00Z"}], "count": 1, "total": 48, "truncated": false, "next_offset": 1}

screening_agreement

Computes Cohen's kappa between two reviewers at one stage. Only papers both reviewers decided with include or exclude enter the calculation; not_retrieved pairs are counted in not_judged.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
stagestringYestitle_abstract or full_text.
reviewer_astringYesFirst reviewer name.
reviewer_bstringYesSecond reviewer name.

Result notes. kappa is null and the interpretation is undefined when the reviewers share no decisions or expected agreement is 1. Interpretation uses the Landis and Koch bands.

Example request.

{"review_id": "rev-9f3c2a1b", "stage": "title_abstract", "reviewer_a": "primary", "reviewer_b": "secondary"}

Example result.

{"ok": true, "stage": "title_abstract", "reviewer_a": "primary", "reviewer_b": "secondary", "shared": 20, "agree": 17, "table": {"both_include": 6, "a_include_b_exclude": 1, "a_exclude_b_include": 2, "both_exclude": 11}, "po": 0.85, "pe": 0.53, "kappa": 0.681, "interpretation": "substantial", "disagreement_count": 3, "disagreements": [{"paper_ref": "10.1000/example.2023", "title": "Turnaround after overnight teleradiology", "a": "include", "b": "exclude", "reason_a": null, "reason_b": "No turnaround time outcome"}, {"paper_ref": "10.1000/example.2024", "title": "Diagnostic accuracy of remote reporting", "a": "exclude", "b": "include", "reason_a": "Wrong population", "reason_b": null}, {"paper_ref": "10.1000/example.2025", "title": "Cost of teleradiology in rural hospitals", "a": "exclude", "b": "include", "reason_a": "No turnaround time outcome", "reason_b": null}], "truncated": false, "only_a": 2, "only_b": 1, "not_judged": 4, "next_step": "Resolve the 3 disagreement(s) and record each consensus decision with reviewer='primary'."}

prisma_status

Computes PRISMA 2020 counts from the search log, the dedup record and one reviewer's decisions. Run it before writing the flow section and before export.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
reviewerstringNoDefaults to primary, else the only reviewer. Several reviewers with no primary is an error.

Counts. Reports sought are title/abstract includes. Reports not retrieved are full-text not_retrieved. Assessed is full-text include plus exclude. A report sought with no full-text decision is full_text_pending.

Invariants. The server checks that full-text decisions exist only for title/abstract includes, so sought equals assessed plus not retrieved plus pending. complete is true when searches and dedup are recorded, every record after dedup has a title/abstract decision, no full-text decision is pending and the invariants hold.

Example request.

{"review_id": "rev-9f3c2a1b", "reviewer": "primary"}

Example result.

{"ok": true, "reviewer_used": "primary", "records_identified": 412, "records_by_source": {"PubMed": 412}, "duplicates_removed": 87, "records_after_dedup": 325, "records_screened": 325, "excluded_title_abstract": 277, "full_text_requested": 48, "full_text_unavailable": 3, "full_text_assessed": 45, "excluded_full_text": 33, "studies_included": 12, "exclusion_reasons": {"Wrong population": 14, "No turnaround outcome": 11, "No comparator": 8}, "exclusion_reasons_title_abstract": {"Wrong population": 160, "No turnaround outcome": 117}, "full_text_pending": 0, "records_awaiting_screening": 0, "full_text_without_title_abstract_include": [], "searches_recorded": 1, "dedup_recorded": true, "dedup_method": "Zotero duplicate merge, then manual title check", "invariants_valid": true, "invariant_errors": [], "warnings": [], "complete": true, "next_steps": ["PRISMA counts are complete; render them with prisma_flow_diagram."]}

prisma_flow_diagram

Renders the recorded PRISMA counts as a flow diagram. Output is text only and agent-supplied text is escaped for the chosen format.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
formatstringNomermaid (default), svg or markdown.
reviewerstringNoReviewer whose counts are used.

Notes. The diagram shows the top full-text exclusion reasons and adds a pending box when decisions are incomplete. It is a rendering of recorded counts, not a new calculation.

Example request.

{"review_id": "rev-9f3c2a1b", "format": "mermaid", "reviewer": "primary"}

Example result.

{"ok": true, "format": "mermaid", "diagram": "flowchart TD\n    subgraph Identification\n        id1[\"Records identified from databases (n = 412)<br/>PubMed: 412\"]\n        id2[\"Duplicates removed (n = 87)\"]\n        id3[\"Records after deduplication (n = 325)\"]\n        id1 --> id2\n        id2 --> id3\n    end\n    subgraph Screening\n        sc1[\"Records screened (title/abstract) (n = 325)\"]\n        sc_exc[\"Records excluded (title/abstract) (n = 277)\"]\n        sc2[\"Reports sought for retrieval (n = 48)\"]\n        sc_unav[\"Reports not retrieved (n = 3)\"]\n        sc3[\"Reports assessed for eligibility (full-text) (n = 45)\"]\n        sc_ft_exc[\"Reports excluded (full-text) (n = 33)<br/>Wrong population: 14<br/>No turnaround outcome: 11<br/>No comparator: 8\"]\n        id3 --> sc1\n        sc1 --> sc_exc\n        sc1 --> sc2\n        sc2 --> sc_unav\n        sc2 --> sc3\n        sc3 --> sc_ft_exc\n    end\n    subgraph Included\n        inc[\"Studies included in review (n = 12)\"]\n        sc3 --> inc\n    end", "complete": true, "warnings": []}

prisma_checklist

Checks a draft against the 27 PRISMA 2020 items with a keyword match, and compares sentences that state PRISMA counts with the recorded counts. Nothing is saved.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
report_textstringYesThe draft to check.
reviewerstringNoReviewer whose counts are compared.

What it proves. The keyword check shows whether an item is mentioned, not whether it is reported well. Item 1 checks whether the first line contains “systematic review” or “meta-analysis”. Count statements are compared within tolerance and returned with a snippet.

Example request.

{"review_id": "rev-9f3c2a1b", "report_text": "This systematic review examined teleradiology. Of 412 records identified, 12 studies were included.", "reviewer": "primary"}

Example result.

{"ok": true, "found_count": 2, "total": 27, "items": [{"item": 1, "section": "Title", "topic": "Title identifies the report as a systematic review", "found": true, "matched": "systematic review"}, {"item": 2, "section": "Abstract", "topic": "Abstract", "found": false, "matched": null}, {"item": 3, "section": "Introduction", "topic": "Rationale", "found": false, "matched": null}, {"item": 4, "section": "Introduction", "topic": "Objectives", "found": false, "matched": null}, {"item": 5, "section": "Methods", "topic": "Eligibility criteria", "found": false, "matched": null}, {"item": 6, "section": "Methods", "topic": "Information sources", "found": false, "matched": null}, {"item": 7, "section": "Methods", "topic": "Search strategy", "found": false, "matched": null}, {"item": 8, "section": "Methods", "topic": "Selection process", "found": false, "matched": null}, {"item": 9, "section": "Methods", "topic": "Data collection process", "found": false, "matched": null}, {"item": 10, "section": "Methods", "topic": "Data items", "found": false, "matched": null}, {"item": 11, "section": "Methods", "topic": "Study risk of bias assessment", "found": false, "matched": null}, {"item": 12, "section": "Methods", "topic": "Effect measures", "found": false, "matched": null}, {"item": 13, "section": "Methods", "topic": "Synthesis methods", "found": false, "matched": null}, {"item": 14, "section": "Methods", "topic": "Reporting bias assessment", "found": false, "matched": null}, {"item": 15, "section": "Methods", "topic": "Certainty assessment", "found": false, "matched": null}, {"item": 16, "section": "Results", "topic": "Study selection", "found": true, "matched": "records identified"}, {"item": 17, "section": "Results", "topic": "Study characteristics", "found": false, "matched": null}, {"item": 18, "section": "Results", "topic": "Risk of bias in studies", "found": false, "matched": null}, {"item": 19, "section": "Results", "topic": "Results of individual studies", "found": false, "matched": null}, {"item": 20, "section": "Results", "topic": "Results of syntheses", "found": false, "matched": null}, {"item": 21, "section": "Results", "topic": "Reporting biases", "found": false, "matched": null}, {"item": 22, "section": "Results", "topic": "Certainty of evidence", "found": false, "matched": null}, {"item": 23, "section": "Discussion", "topic": "Discussion (interpretation, limitations, implications)", "found": false, "matched": null}, {"item": 24, "section": "Other information", "topic": "Registration and protocol", "found": false, "matched": null}, {"item": 25, "section": "Other information", "topic": "Support", "found": false, "matched": null}, {"item": 26, "section": "Other information", "topic": "Competing interests", "found": false, "matched": null}, {"item": 27, "section": "Other information", "topic": "Availability of data, code and other materials", "found": false, "matched": null}], "missing": ["Abstract", "Rationale", "Objectives", "Eligibility criteria", "Information sources", "Search strategy", "Selection process", "Data collection process", "Data items", "Study risk of bias assessment", "Effect measures", "Synthesis methods", "Reporting bias assessment", "Certainty assessment", "Study characteristics", "Risk of bias in studies", "Results of individual studies", "Results of syntheses", "Reporting biases", "Certainty of evidence", "Discussion (interpretation, limitations, implications)", "Registration and protocol", "Support", "Competing interests", "Availability of data, code and other materials"], "numbers": [{"field": "records_identified", "reported": 412, "recorded": 412, "matches": true, "snippet": "ew examined teleradiology. Of 412 records identified, 12 studies were included."}, {"field": "studies_included", "reported": 12, "recorded": 12, "matches": true, "snippet": "y. Of 412 records identified, 12 studies were included."}], "number_mismatches": 0, "numbers_note": null, "note": "Keyword check of the report text. It shows which items are mentioned, not whether they are reported well."}

Evidence extraction

evidence_record

Records one evidence row per paper and outcome. The server checks that the quote appears in source_text and that every number entered is written in the quote. Only the length and SHA-256 of source_text are stored.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
paper_refstringYesCanonical paper reference.
outcomestringYesOutcome name. One row per paper and outcome.
study_designstringYesDesign as reported.
quotestringYesPassage that contains the extracted numbers.
source_textstringYesText used to check the quote. Must not be empty.
sample_size, population, intervention, comparator, timepoint, effect_measure, effect_estimate, ci_lower, ci_upper, ci_level, notesvariesNoeffect_measure is rr, or, hr, irr, rom, rd, md, smd or other; names such as “risk ratio” are accepted.

Refused input. An estimate without a measure, only one CI limit, lower above upper, an estimate outside its CI, a ratio measure at or below zero, a non-finite number, or an empty source_text. A quote that does not verify is stored and flagged, not rejected.

Warnings. A paper that is not among the full-text included studies is flagged. A changed source-text hash is reported as source_changed.

Example request.

{"review_id": "rev-9f3c2a1b", "paper_ref": "10.1000/example.2021", "outcome": "Report turnaround time", "study_design": "Retrospective cohort", "quote": "Median turnaround time fell by 24 minutes (95% CI 31 to 17 minutes less; n=1,204).", "source_text": "Results: Median turnaround time fell by 24 minutes (95% CI 31 to 17 minutes less; n=1,204).", "sample_size": 1204, "effect_measure": "md", "effect_estimate": -24, "ci_lower": -31, "ci_upper": -17, "ci_level": 95}

Example result.

{"ok": true, "updated": false, "paper_ref": "10.1000/example.2021", "outcome": "Report turnaround time", "quote_verified": true, "quote_note": "Quote found in the supplied source text.", "numbers_not_in_quote": [], "effect": "MD -24 (95% CI -31 to -17)", "rows_for_paper": 1, "warnings": []}

evidence_table

Returns the whole evidence table as Markdown, CSV or JSON. Coverage counters show included studies with no row and rows whose quote or numbers did not verify.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
formatstringNomarkdown (default), csv or json.
paper_refstringNoLimit the table to one paper.

CSV safety. A text cell that starts with =, +, - or @ is prefixed with an apostrophe so a spreadsheet does not execute it.

Example request.

{"review_id": "rev-9f3c2a1b", "format": "markdown"}

Example result.

{"ok": true, "format": "markdown", "row_count": 1, "table": "| Study | Design | N | Population | Intervention | Comparator | Outcome | Effect | Source quote | Checks |\n|---|---|---|---|---|---|---|---|---|---|\n| 10.1000/example.2021 | Retrospective cohort | 1204 | Adults referred for imaging | Teleradiology | On-site reporting | Report turnaround time | MD -24 (95% CI -31 to -17) | Median turnaround time fell by 24 minutes | quote verified |", "truncated": false, "included_without_rows": ["10.1000/example.2024"], "included_without_rows_count": 1, "rows_quote_not_verified": 0, "rows_numbers_not_in_quote": 0}

Claims and risk of bias

claim_record

Records whether a key claim is supported by one paper. The agent supplies the label and reason; the server stores the judgement and checks the quote against the supplied source text. A claim is upserted on normalised claim text plus paper reference.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
claim_textstringYesThe sentence or claim being judged.
paper_refstringYesThe paper that should support it.
labelstringYessupported, partial or unsupported.
reasonstringYesWhy the label applies.
source_textstringFor supported and partialChecked, then stored only as length and SHA-256.
quotestringFor supported and partialMust appear in source_text to verify.

Note. quote_verified means the quote appears in the supplied text. It does not mean the passage supports the claim; that is the agent's recorded judgement.

Example request.

{"review_id": "rev-9f3c2a1b", "claim_text": "Teleradiology reduced median report turnaround time by 24 minutes.", "paper_ref": "10.1000/example.2021", "label": "supported", "reason": "The reported median difference matches the claim.", "quote": "Median turnaround time fell from 42 minutes to 18 minutes", "source_text": "Results: Median turnaround time fell from 42 minutes to 18 minutes (n=1,204)."}

Example result.

{"ok": true, "claim_id": 7, "updated": false, "quote_verified": true, "quote_note": "Quote found in the supplied source text.", "warnings": []}

claim_report

Summarises the claim log. With report_text, it also finds weak claims whose text appears verbatim in the draft.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
report_textstringNoThe draft in which to find weak claims.

Fields. suspicious lists supported or partial claims whose quote did not verify. unsupported lists unsupported claims. weak_claims_in_report is null when no report text is supplied.

Example request.

{"review_id": "rev-9f3c2a1b", "report_text": "Teleradiology reduced median report turnaround time by 24 minutes."}

Example result.

{"ok": true, "total": 9, "counts_by_label": {"supported": 7, "partial": 1, "unsupported": 1}, "quotes_not_verified": 1, "suspicious_count": 1, "suspicious": [{"claim_id": 8, "claim_text": "Teleradiology improved diagnostic accuracy.", "paper_ref": "10.1000/example.2024", "label": "partial", "reason": "Only sensitivity was reported; specificity was not."}], "unsupported_count": 1, "unsupported": [{"claim_id": 9, "claim_text": "Teleradiology is cost saving in every setting.", "paper_ref": "10.1000/example.2025", "label": "unsupported", "reason": "No cost outcome was reported."}], "weak_claims_in_report": [{"claim_id": 9, "claim_text": "Teleradiology is cost saving in every setting.", "paper_ref": "10.1000/example.2025", "label": "unsupported", "reason": "No cost outcome was reported."}], "truncated": false, "method": "Labels were assigned by the calling agent. The server checked only that each quote appears in the supplied source text. This is not independent verification.", "next_step": "Remove or rewrite the claims in weak_claims_in_report, or record a verified quote for them."}

rob_record

Records one risk-of-bias domain judgement for one paper. The tool and domain sets are fixed, a paper cannot mix tools, and a quote is required except for a few cases.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
paper_refstringYesIncluded study.
toolstringYesrob2, robins_i, nos (cohort) or nos_case_control.
domainstringYesRoB 2 D1–D5, ROBINS-I D1–D7 (aliases accepted), NOS selection / comparability / outcome or exposure, or overall for RoB 2 and ROBINS-I.
judgementstring or integerYesRoB 2: low, some_concerns, high. ROBINS-I: low, moderate, serious, critical, no_information. NOS: star counts, selection 0–4, comparability 0–2, outcome or exposure 0–3.
quotestringUsuallyRequired except for overall, ROBINS-I no_information and 0 stars.
source_textstringUsuallyText used to check the quote.
rationalestringFor overallRequired for an overall judgement.

Rule. Recording the same domain again updates it. domains_missing shows what remains before rob_summary can compute an overall judgement.

Example request.

{"review_id": "rev-9f3c2a1b", "paper_ref": "10.1000/example.2021", "tool": "robins_i", "domain": "D2", "judgement": "moderate", "quote": "Consecutive cases were identified from the radiology information system.", "source_text": "Methods: Consecutive cases were identified from the radiology information system."}

Example result.

{"ok": true, "updated": false, "paper_ref": "10.1000/example.2021", "tool": "robins_i", "domain": "D2", "judgement": "moderate", "quote_verified": true, "quote_note": "Quote found in the supplied source text.", "domains_recorded": 2, "domains_missing": ["D3", "D4", "D5", "D6", "D7"], "warnings": []}

rob_summary

Computes the overall risk-of-bias judgement for each paper from its recorded domains and the published rule, then returns a traffic-light table and counts by overall judgement.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.

Rules. RoB 2: any high gives high, else any some concerns gives some concerns, else low. ROBINS-I: any critical gives critical, else any serious gives serious, else any no information gives no information unless a recorded overall is used, else the worst of moderate and low. NOS uses the AHRQ thresholds: good, fair or poor. A paper is incomplete while a domain is missing.

Recorded overall. A reviewer's own overall is used only where the rule allows it. A recorded overall outside the rule is ignored with a note.

Example request.

{"review_id": "rev-9f3c2a1b"}

Example result.

{"ok": true, "papers": [{"paper_ref": "10.1000/example.2021", "tool": "robins_i", "domains": {"D1": "low", "D2": "moderate", "D3": "low", "D4": "low", "D5": "low", "D6": "low", "D7": "low"}, "missing_domains": [], "overall": "moderate", "overall_by_rule": "moderate", "overall_recorded": null, "notes": []}], "table": [{"paper_ref": "10.1000/example.2021", "D1": "low", "D2": "moderate", "overall": "moderate"}], "counts_by_overall": {"moderate": 1}, "papers_with_unverified_quotes": [], "overall_rule": "ROBINS-I: critical > serious > no_information > moderate > low", "truncated": false}

Whole-review views and export

review_status

Reports the current phase, what is complete and what is missing. It is read only and is the right first call when you resume a review.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
reviewerstringNoReviewer used for screening and PRISMA coverage.

Coverage checks. Included studies without evidence rows or risk-of-bias records, evidence rows for papers not included, included DOIs not yet checked, retracted or non-resolving DOIs, single-reviewer screening and source-text changes. Paper lists show the first 20 references.

Phase. The first unfinished step of protocol, searching, deduplication, title/abstract screening, full-text screening, data extraction, risk of bias, claim checking or reporting.

Example request.

{"review_id": "rev-9f3c2a1b", "reviewer": "primary"}

Example result.

{"ok": true, "review": {"review_id": "rev-9f3c2a1b", "title": "Teleradiology turnaround times: a systematic review", "question": "In adults, what is the effect of teleradiology on radiology report turnaround time?", "year_min": 2010, "year_max": 2026, "created_at": "2026-10-25T09:14:00Z"}, "phase": "reporting", "protocol": {"complete": true, "missing_required": [], "missing_recommended": []}, "prisma": {"reviewer_used": "primary", "records_identified": 412, "duplicates_removed": 87, "records_after_dedup": 325, "records_screened": 325, "records_awaiting_screening": 0, "full_text_requested": 48, "full_text_unavailable": 3, "full_text_pending": 0, "full_text_assessed": 45, "studies_included": 12, "invariants_valid": true, "complete": true}, "screening_reviewers": ["primary", "secondary"], "included_studies": 12, "extraction": {"rows": 12, "studies_with_rows": 12, "included_without_rows_count": 0, "included_without_rows": [], "rows_quote_not_verified": 0, "rows_numbers_not_in_quote": 0}, "risk_of_bias": {"papers_assessed": 12, "counts_by_overall": {"low": 3, "moderate": 7, "serious": 2}, "included_without_rob_count": 0, "included_without_rob": [], "incomplete": [], "papers_with_unverified_quotes": []}, "claims": {"total": 9, "counts_by_label": {"supported": 7, "partial": 1, "unsupported": 1}, "quotes_not_verified": 1, "suspicious_count": 1, "unsupported_count": 1}, "dois": {"checked": 12, "retracted": [], "not_found": [], "unverified": 0, "included_dois_unchecked": 0}, "source_texts": {"distinct_by_paper": 12, "changes_count": 0}, "warnings": ["Claim 9 is unsupported but appears in the draft."], "next_steps": ["Revise the draft claim flagged by claim_report.", "Export the audit bundle."]}

export_bundle

Returns one document with the review record: metadata, protocol and amendments, search log, dedup, PRISMA counts and invariants with a diagram, screening decisions, agreement, evidence, risk of bias, claims, DOI checks and source-text changes.

ArgumentTypeRequiredNotes
review_idstringYesExisting review id.
formatstringNomarkdown (default) or json.
reviewerstringNoReviewer used for agreement and PRISMA coverage.

Limits. At most 5,000 screening decisions and 5,000 claims. Source texts are never included. Nothing is written to disk; the client receives the text and may save it.

Example request.

{"review_id": "rev-9f3c2a1b", "format": "markdown", "reviewer": "primary"}

Example result.

{"ok": true, "format": "markdown", "content": "# Teleradiology turnaround times: a systematic review\n\n## Protocol\n...\n\n## PRISMA 2020 flow\n...", "chars": 28410, "suggested_filename": "rev-9f3c2a1b-audit-bundle.md", "truncated": false, "phase": "reporting"}

Limits and validation rules

Paper identity

Every paper_ref is stored in a canonical form. Accepted inputs are a DOI (lower-cased, with any doi: or doi.org prefix removed), pmid:<digits>, or title:<normalised title>|<year or nd>. Title matching folds accents and removes punctuation while keeping letters of every script. Anything else is refused. Use the same form for a paper in every tool, or later tools will treat it as a different paper.

Input and list caps

ItemCap or rule
List results200 items, with truncated: true when cut.
review_id^[a-z0-9_-]{6,40}$, validated before it becomes a file name.
review_create title / question500 / 2,000 characters.
verify_dois100 DOIs per call.
resolve_citations papers2,000 papers.
dedup_papers10,000 records; more is refused so cross-call duplicates are not missed.
screening_record_many500 decisions per call, all or nothing.
Screening exclusion reason300 characters; required for exclude.
Reviewer name1 to 40 characters, stored lower-case.
export_bundle5,000 screening decisions and 5,000 claims.
Tool text input400,000 characters for a single text field.

How quote checks work

Quote matching ignores case, whitespace, curly quotes, dash variants, zero-width characters, line-break hyphenation and hyphens inside words. It needs at least 12 normalised characters and matches on word boundaries for scripts written with spaces.

An ellipsis quote (a ... b or a [...] b) verifies only when every part is found in order and the parts are at most 1,500 characters apart. In an evidence row, every number entered must also be written in the quote; missing numbers are reported in numbers_not_in_quote.

A failed check is stored and reported. It is never silently accepted, and it is never described as verified.

Data handling and privacy

Local storage

State lives in SQLite files under CITEPROOF_MCP_HOME, which defaults to ~/.citeproof-mcp. Each review is <home>/reviews/<review_id>.db. The server opens one file per review, applies its schema on first open, and uses WAL plus a 30 second busy timeout. Concurrent calls wait rather than fail as locked.

Source text is never stored in full. The server stores its length and SHA-256, plus observations and hash changes. Exports are returned as text; nothing is written outside the home folder. Removing or moving the folder moves the review data with it.

Network calls

The only network calls are DOI checks in verify_dois, to api.crossref.org and doi.org. Hosts are fixed, redirects are not followed, the timeout is 15 seconds, and a value that is not DOI-shaped is never sent. No review data is uploaded. Metrics, accounts and telemetry are not part of the server.

What stays on your machine

Review files, screening decisions, extracted evidence, claims, risk-of-bias records and source-text hashes stay in the local SQLite database. CiteProof does not receive them. The client can read tool results and may send them to its own model provider under that provider's terms; that is outside the MCP server's control.

Handling ok:false

Every handled failure looks like this:

{"ok": false, "error": "stage must be one of: title_abstract, full_text; got 'full_pdf'"}

Read error and change the argument. Common cases:

  • Invalid paper reference. Use a DOI, pmid:<digits> or title:<title>|<year>. Do not switch forms for the same paper.
  • Missing required field. An exclusion needs a reason; a supported or partial claim needs a quote and source text; an overall risk-of-bias judgement needs a rationale.
  • Wrong JSON type. The MCP SDK rejects the argument before the tool runs. That is a transport-level tool error, not an ok:false result.
  • Busy database. Retry the call. The failed attempt saved nothing.
  • Internal error. The message names the tool and exception type, with no stack trace or file path. Check the arguments, retry once, then report the tool name and a redacted request.

Read-only calls are safe to repeat. Do not blindly retry a write after an error that may have partially applied; read review_status first.

Client compatibility

ClientInstall pathStatus
Claude ScienceLocal command connector with the built bundleTested Windows 11, Claude Science 0.1.67
Claude Desktopciteproof.mcpb extensionNew Extension path, not yet broadly tested
Claude Desktopnpx with a JSON mcpServers entryNew Not yet tested for this release
Claude Codeclaude mcp add citeproof -- npx -y citeproof-mcpNew Not yet tested for this release
Cursor, VS Code, WindsurfAny stdio launcher, or npxNot yet tested
claude.ai web custom connectorsCannot start a local stdio commandUnsupported

The server follows the standard MCP stdio protocol and was tested against mcp 1.27 and mcp 2.x. A client that can start a stdio server should work, but “should” is not “tested”.

Troubleshooting

SymptomWhat to check
Only 18 tools appear instead of 24An old server process is still running. Remove the connector and add it again with the same settings.
this kernel's Python interpreter ... is not readable inside the sandboxThe command points outside the connector workspace. Use the bundle path from the install steps.
Set "command" to node, npx or python3 ...You gave an absolute path to a Python that Claude Science does not provide. Use python3.
can't open file ... Permission deniedThe bundle is outside the connector workspace. Build it into .../workspaces/_mcp-citeproof/bundle.
Connector name rejectedUse lowercase letters, digits and hyphens only. Use citeproof.
The local process exits immediatelyCheck the command path, CITEPROOF_MCP_HOME and the connector log. The command must be readable inside the sandbox.
npx does not startCheck node --version. Node 18 or newer is required. If auto-install is disabled, install uv yourself; uv fetches Python 3.12 on first run.
A DOI returns unverifiedThe registry was unreachable, so there is no verdict. It is not “not found”. Retry when the network is available.
Deduplication will not recordThe call did not cover every exported record. records_checked must equal the total hits recorded by prisma_record_search, or record the whole count with prisma_record_dedup.
An export is empty or cut shortCheck review_status for missing records and truncated in the export result. The 5,000-decision and 5,000-claim caps are the only truncation points.

For connector-specific errors and the research-assistant failures, see Troubleshooting.

Keeping these docs accurate

This page describes CiteProof MCP 0.1.0. When the code and this page disagree, the code wins. The authoritative sources are:

To update this page, change the tool schema and the SPEC together, then revise the matching entry here. The sidebar, search index and in-page outline are generated from the heading ids, so keep each tool heading id in the form tool-<name-with-hyphens>.