# CiteProof-AI-MCP [Health: Active]

**Category:** 🔬 Research  
**Repository:** https://github.com/Aryan-Pardeshi/CiteProof-AI-MCP  
**GitHub Stars:** 110  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/citeproof-ai-mcp

## Description
Open-source research assistant and MCP audit toolkit for systematic reviews: cited research reports, PRISMA tracking, evidence and claim checks, and reproducible exports with human oversight.

## Tools
Capabilities this server exposes over MCP:

- **review_create** — Start a new review and get the review_id every other review tool needs. Call this first.

    Returns: review_id, next_step.
    
- **review_list** — List existing reviews, newest first, to recover a review_id.

    Returns: reviews (review_id, title, question, created_at, year_min, year_max), count.
    
- **verify_dois** — Check that DOIs exist in a registry (Crossref, then doi.org) and are not retracted.

    This is the only tool that uses the network. Statuses per DOI:
    'resolved' (registry has it), 'not_found' (doi.org says it does not exist:
    likely a typo or a fabricated citation), 'unverified' (the registry could not be
    reached or timed out: no verdict, retry later; never treat as fabricated),
    'invalid' (not DOI-shaped; not sent to any registry). retracted is true/false
    only when Crossref holds the record, else null.

    Returns: results (doi, input, status, title, year, journal, authors, retracted,
    registry), summary (checked, resolved, not_found, unverified, invalid, retracted),
    offline (true when no DOI could be checked), saved (true when stored in review_id),
    note.

    Does NOT check that a paper supports any claim, only that the DOI is real.
    
- **resolve_citations** — Match the inline citations in a text against your reference list, and find references never cited.

    Recognises DOIs and author-year citations: '(Smith, 2020)', '(Smith 2020)',
    'Smith et al. (2020)', '(Smith and Lee, 2020; Jones, 2021)', '(Smith, 2020a)'.
    A citation resolves when its DOI, or first-author surname + year, matches one
    reference (authorless references match on the first title words + year).

    Returns: citations_found, resolved (citations matching exactly one reference),
    ambiguous (citations matching several references), unresolved (citations
    matching none: check them), orphan_papers (titles of references nothing cites),
    doi_citations_checked, numeric_citations_found ('[1]'-style citations, which
    this tool cannot resolve), truncated (a list was cut at 200), note.

    Does NOT check that a cited paper supports the sentence, and does not use the network.
    
- **lint_prose** — Advisory style check of report prose with fixed rules.

    Codes: EMDASH (dense em-dash use), HONEST (hedged framing such as 'the honest
    answer'), PROCNOTE (narration about how the report was made), PARENDOI
    (unencoded parentheses in DOI links), LONGHEAD (sentence-like headings),
    FLATSTRUCT (flat heading structure).

    Returns: issues (code, note), issue_count, advisory (always true: findings never
    block anything).
    
- **protocol_record** — Record or update the review protocol and check that it is complete. Call right after review_create.

    Send only the fields you want to set; omitted fields keep their stored value, so
    calling with just review_id reads the protocol back. List fields accept a list,
    or one string split on new lines and semicolons. Every change is logged; changes
    to a field that already had a value count as amendments (report them, PRISMA
    item 24c).

    Returns: protocol (every field), updated_fields, complete (all required fields
    set), missing_required (population, intervention, outcomes, inclusion_criteria,
    exclusion_criteria, databases, search_strategy), missing_recommended
    (comparator, study_designs, year_range, languages, registration, rob_tool,
    synthesis_method), amendments (changes to fields that already had a value), next_step.

    Does NOT judge whether the criteria are sensible; it checks they are written down.
    
- **prisma_record_search** — Log one database or register search for the PRISMA identification box.

    Call once per database search, right after running it. Re-sending the same
    source + query + date_run replaces the hit count instead of adding a second row,
    so a retried call cannot double-count records. Source names are matched
    case-insensitively ('pubmed' joins 'PubMed').

    Adding a search, or changing a search's hit count, clears the review's
    deduplication record, because that count belonged to the old set of records.
    Run dedup_papers (or prisma_record_dedup) again afterwards. Re-sending a
    search with the same hit count changes nothing.

    Returns: search_id, updated (true when an existing search was replaced),
    records_identified (sum of hits over all searches), records_by_source,
    searches_recorded, dedup_cleared (true when an earlier dedup record was
    cleared), warnings.

    Does NOT run the search or check the hit count; it records what you report.
    
- **dedup_papers** — Find duplicate records deterministically so the PRISMA duplicate count is computed, not guessed.

    Two records are the same paper when they share a DOI (case-insensitive, URL or
    'doi:' prefix ignored), a PMID, or the same normalised title (20+ characters)
    with the same year and first-author surname. Matching is transitive. Records
    with the same title but a different year or first author are NOT merged; they
    are listed in possible_duplicates for you to decide. In each cluster the record
    with the most complete metadata is kept (ties: earliest).

    Returns: records_checked, unique_records, duplicates_removed, removed_indices
    (0-based positions to drop), clusters (kept_index, kept_id, member_indices,
    matched_on, conflicting_dois; capped at 200), possible_duplicates (capped),
    truncated, recorded (true when saved to the review), warnings, note.

    A review has one dedup count, so it is recorded only when the call covers
    every exported record (records_checked equals the recorded hits); otherwise
    recorded is false and the previous record is kept.

    Does NOT fetch or merge metadata, and does not use fuzzy title matching.
    Before you discard the records at removed_indices, copy any field you still
    need (an abstract, a PMID or DOI, a full-text link) onto the kept record.
    
- **prisma_record_dedup** — Record a duplicate count you computed elsewhere (replaces any earlier count).

    Prefer dedup_papers, which computes and records the count from the records
    themselves. Use this tool only when deduplication was done outside this server.
    duplicates_removed cannot exceed the total hits recorded with prisma_record_search.

    Returns: duplicates_removed, records_identified, records_after_dedup, method.
    
- **screening_record** — Record one screening decision for one paper. Re-sending the same paper_ref + stage + reviewer replaces it.

    Use for single decisions; use screening_record_many for batches. PRISMA counts
    use the reviewer named 'primary' (or the only reviewer). With two independent
    reviewers, record each under their own name, compare with screening_agreement,
    then record the consensus under 'primary'. Reviewer 'primary' cannot record
    consensus while a stage is in open blind mode (consensus is recorded after the
    stage is closed).

    Returns: updated, paper_ref (canonical form), stage, reviewer, decision,
    stage_counts (this reviewer's decisions so far at this stage), warnings
    (e.g. a full_text decision with no title_abstract include).

    Does NOT read the paper; the decision is yours.
    
- **screening_record_many** — Record up to 500 screening decisions in one all-or-nothing transaction.

    Same rules as screening_record. If any item is invalid, or the same
    paper_ref + stage + reviewer appears twice, nothing is written and the result
    names the item: {ok: false, error, index}. Reviewer 'primary' cannot record
    consensus while a stage is in open blind mode.

    Returns: count, inserted_count, updated_count, warning_count, warnings (first 50).
    
- **screening_list** — List recorded screening decisions, newest first, one page at a time.

    At an open blind stage, rows are returned only when reviewer == as_reviewer.
    Rows of other reviewers at that stage are not returned and not counted in total;
    without as_reviewer, every open-blind-stage row is hidden.

    Returns: records (paper_ref, stage, reviewer, decision, reason, title,
    updated_at, reviewer_type, model_id, run_ref), count (rows in this page),
    total (rows matching the filters and visibility), truncated (more rows after
    this page), next_offset (pass it as offset to get the next page, or null),
    hidden_blind_rows (count of hidden peer rows), blind_note.

    Does NOT reveal peer decisions during an open blind stage.
    
- **screening_agreement** — Cohen's kappa between two reviewers' include/exclude decisions at one stage.

    Always pass warnings (such as human screening caution and same-model warnings)
    to the user.

    Uses only papers both reviewers decided with include or exclude
    ('not_retrieved' pairs are counted in not_judged). kappa = (po - pe) / (1 - pe);
    it is null with interpretation 'undefined' when nothing is shared or both
    reviewers put every paper in the same category (pe = 1).

    At an open blind stage, agreement figures (kappa, table, disagreements) are hidden
    until the stage is closed with screening_stage_close.

    Returns: reviewer_a_type, reviewer_b_type, reviewer_a_model_id, reviewer_b_model_id,
    warnings, plus (when unblinded): shared, agree, table (2x2 counts), po, pe, kappa,
    interpretation (Landis and Koch bands), disagreement_count, disagreements (capped),
    truncated, only_a, only_b, not_judged, next_step; or (when blinded): blinded=True,
    next_step.

    Does NOT resolve disagreements: decide each one and record it under 'primary'.
    
- **reviewer_record** — Record reviewer type ('human', 'model', or 'unknown') and model identity.

    The MCP server has no user login and cannot verify caller identity. Blinding
    and reviewer types are by convention, with an audit trail, not a guarantee.
    One agent can still call tools under another reviewer's name, and two runs of
    the same model are not independent reviewers. Reviewer type is self-declared;
    no output may call a review verified or independent because of it.

    model_id is only allowed when reviewer_type is 'model'. For model reviewers
    without a model_id, the record is saved with a warning that same-model checks
    cannot run. Reviewer 'primary' holds consensus decisions; typing it 'human'
    records a human adjudicator, which clears the AI-only screening warning.

    Returns: name, reviewer, reviewer_type, model_id, run_ref, updated_at, warnings.

    Does NOT verify caller identity or authenticate models.
    
- **screening_stage_set** — Configure a screening stage mode ('blind' or 'unblinded') and its expected reviewers.

    The MCP server has no model or user login; reviewer names are supplied by the
    caller. Blinding is by convention, with an audit trail, not a guarantee.
    One agent can still call tools under another reviewer's name, and two runs of
    the same model are not independent reviewers. At an open blind stage, peer
    decisions and agreement are hidden until the stage is closed with
    screening_stage_close.

    Setting a stage to 'blind' requires at least 2 distinct reviewer names, none
    'primary'. Changing an already closed blind stage back to blind fails, and so does
    making a stage blind after decisions are recorded at it.

    Returns: stage, mode, reviewers, closed_at, updated_at.

    Does NOT enforce physical isolation between screening processes.
    
- **screening_stage_close** — Close an open blind screening stage and unblind peer decisions and agreement.

    The explicit close rule requires:
    1. At least one paper exists with decisions recorded by expected reviewers.
    2. Every expected reviewer has recorded a decision for every paper that any
       expected reviewer recorded at this stage.

    If these conditions are not met, the call fails and lists (capped) the missing
    (reviewer, paper_ref) pairs and count. On success, closed_at is set, the stage
    becomes unblinded, agreement (including kappa and disagreements) becomes visible,
    and consensus/adjudication decisions may be recorded under reviewer 'primary'.

    Returns: stage, closed_at, papers_count, decisions_count, reviewer_counts.

    Does NOT resolve disagreements or verify consensus.
    
- **prisma_status** — Compute the PRISMA 2020 flow counts from the recorded searches, dedup and screening decisions.

    Counting reviewer: the one you name, else 'primary', else the only reviewer;
    with several reviewers and no 'primary' the call fails and says so.
    'Reports not retrieved' counts full_text decisions 'not_retrieved'. Papers
    included at title_abstract with no full_text decision yet are full_text_pending,
    not 'not retrieved'.

    Returns: reviewer_used, the PRISMA counts (records_identified, records_by_source,
    duplicates_removed, records_after_dedup, records_screened, excluded_title_abstract,
    full_text_requested, full_text_unavailable, full_text_assessed, excluded_full_text,
    studies_included, which counts reports), reports_included, study_count (reports
    linked to one study with study_link count once), exclusion_reasons (full-text
    reasons, as PRISMA reports them),
    exclusion_reasons_title_abstract, full_text_pending, records_awaiting_screening,
    searches_recorded, dedup_recorded, dedup_method, invariants_valid,
    invariant_errors (arithmetic that does not add up), warnings, complete (true when
    every record has a final decision and the arithmetic holds), next_steps.

    Does NOT change anything or guess missing numbers.
    
- **prisma_flow_diagram** — Render the PRISMA 2020 flow diagram from the counts prisma_status computes.

    Text output only; save or embed the `diagram` string yourself. Agent-supplied
    text (sources, exclusion reasons) is escaped for the chosen format. Shows the
    top full-text exclusion reasons.

    Returns: format, diagram, complete (false means the counts are still in progress
    or do not add up), warnings.
    
- **prisma_checklist** — Keyword check of a report against the 27 PRISMA 2020 items, plus a check of the PRISMA numbers it states.

    Items: each is 'found' when one of its fixed phrases appears (item 1: the first
    line names a systematic review or meta-analysis). Numbers: sentences such as
    '1,234 records were identified' or '12 studies were included' are compared with
    the recorded counts; a mismatch may be a typo, or a sentence about a subset.

    Returns: found_count, total (27), items (item, section, topic, found, matched),
    missing (topics not found), numbers (field, reported, recorded, matches, snippet),
    number_mismatches, numbers_note, note.

    This is a keyword check, not a quality judgement: it shows which items are
    mentioned, not whether they are reported well. Nothing is saved.
    
- **evidence_record** — Record one evidence-table row (one study, one outcome) with its source quote checked.

    Call during data extraction for each included study and outcome. Re-sending
    the same paper_ref + outcome replaces the row. Checks: the quote must appear in
    source_text (quote_verified); every number you enter (sample_size,
    effect_estimate, ci_lower, ci_upper) must be written in the quote
    (numbers_not_in_quote lists those that are not); the CI must contain the
    estimate; ratio measures must be positive. Arithmetic errors are refused;
    quote and number mismatches are stored and flagged.

    Returns: updated, paper_ref, outcome, quote_verified, quote_note,
    numbers_not_in_quote, effect (formatted, e.g. 'RR 0.82 (95% CI 0.7 to 0.96)'),
    rows_for_paper, warnings.

    Does NOT extract anything itself: every value is yours.
    
- **evidence_table** — Export the evidence table (all rows recorded with evidence_record) and report extraction gaps.

    markdown and csv return the whole table as text in `table` (save it yourself);
    json returns `rows` (capped at 200, see truncated). Text cells are escaped for
    the format; CSV text cells starting with = + - @ are prefixed with ' so a
    spreadsheet does not run them as formulas.

    Returns: format, row_count, table or rows, truncated, included_without_rows
    (included studies with no row yet, first 50) and its count
    included_without_rows_count, rows_quote_not_verified, rows_numbers_not_in_quote.
    
- **paper_resolve** — Resolve paper refs through the canonical alias map.

    Looks up every ref recorded by dedup_papers or paper_alias_record. Status is
    'resolved' when the ref has an alias, 'conflict' when alias_conflicts holds a
    disagreeing proposal for it, and 'unknown' when no alias exists (the ref is
    returned unchanged). Only an exact stored mapping is used; nothing is guessed.

    Returns: refs (per ref: input, canonical_ref, status, aliases of the canonical
    record, study_id, conflicts), count, truncated, note.

    Does NOT merge conflicting mappings and does not add aliases; use
    paper_alias_record for a manual mapping.
    
- **paper_alias_record** — Record one manual alias, for example a preprint DOI that belongs to a published paper.

    The alias and canonical_ref are canonicalised like every paper_ref. An existing
    mapping to another canonical ref is refused unless replace=true; a replacement
    updates the mapping and saves the previous canonical ref in alias_conflicts for
    provenance. Sending the same mapping again changes nothing.

    Returns: alias, canonical_ref, previous_canonical, recorded (true when a new
    alias was inserted), replaced (true when an existing mapping was changed), kind,
    origin.

    Does NOT validate the papers against an external registry.
    
- **study_link** — Link one or more reports to a study so reports and studies can be counted separately.

    Refs are canonicalised and resolved through the alias map before linking. A report
    already linked to a different study is refused unless replace=true, so a corrected
    link is explicit. Re-sending the same link changes nothing; the note is updated
    only when one is supplied.

    Returns: study_id, linked (newly linked refs), unchanged (already linked to this
    study), moved (paper_ref, from_study, to_study), reports_in_study (all reports now
    linked to study_id), count (refs in this call), note.

    Does NOT merge study records, combine sample sizes or decide whether two reports
    are the same study; use study_overview to see the grouping.
    
- **study_unlink** — Remove the study link from one or more reports, leaving the reports themselves intact.

    Refs are resolved through the alias map, so a link stored under an earlier form of
    the key is removed too.

    Returns: removed (refs that had a link), not_linked (refs with no link), count.

    Does NOT delete screening decisions, evidence rows or any other report record.
    
- **study_overview** — Count included reports separately from studies and flag outcomes one study reports twice.

    Included reports come from the PRISMA full_text include decisions and are resolved
    through the alias map. Each distinct study is one group; an included report with
    no study link counts as its own study and is flagged unlinked.
    duplicate_participant_risk lists an outcome recorded from two or more reports of
    the same linked study: pooling both rows would count its participants twice.

    Returns: report_count, canonical_report_count, study_count, groups (study_id,
    unlinked, reports), unlinked_reports, duplicate_participant_risk (study_id,
    outcome_key, outcome, reports), truncated, note.

    Does NOT prove that two reports share participants, decide whether pooling is
    appropriate, or treat an unlinked report as anything other than its own study.
    
- **recall_seed_record** — Record a small seed set of known eligible papers for a known-item recall check.

    Seeds are stored as canonical refs, so a later alias mapping is applied when
    recall_check runs. With replace=true the previous seed set is removed first.
    Re-adding an existing seed keeps its label unless a new label is supplied.

    Returns: added, updated, unchanged, removed (seeds cleared by replace), count,
    seeds (paper_ref, label, added_at), truncated.

    Does NOT search for the seeds or decide eligibility; it records what you send.
    
- **recall_check** — Compare the recorded seed set with the retrieved records of the last full dedup.

    Alias resolution runs first. A seed is 'found' when a retrieved record has the same
    canonical ref, 'not_found' when retrieved records exist but none matches, and
    'unresolved' when no full dedup has been recorded, when the seed has an alias
    conflict, or when a title seed's only candidate records have no year. Each found
    seed lists the sources that retrieved it; per-source counts separate found, missed
    and unresolved seeds.

    Returns: seeds (paper_ref, label, added_at, canonical_ref, status, sources,
    matched_records, truncated, reason), counts (found, not_found, unresolved),
    recall (found / (found + not_found), null
    when that denominator is 0), per_source (source, records, found, missed,
    unresolved), records_checked, retrieval_recorded_at, check_id, checked_at,
    truncated, note.

    Does NOT prove the search was exhaustive: it only says whether this seed set was
    in the recorded export.
    
- **claim_record** — Record your judgement of whether one paper supports one claim, and check the quote you rely on.

    Call once per (claim, paper) pair after reading the paper. 'supported' and
    'partial' need a quote and the source_text it comes from; the server checks the
    quote appears in that text (case, whitespace, curly quotes, dashes and line-break
    hyphens are ignored; at least 12 characters; matched on word boundaries) and stores
    quote_verified. A claim recorded again for the same paper (same normalised text)
    replaces the earlier record.

    Returns: claim_id, updated, quote_verified, quote_note (why the quote did not
    verify), warnings.

    Does NOT judge support itself: the label is yours, the server only checks the quote.
    
- **claim_report** — Summarise the recorded claim judgements and list the ones that need attention.

    Returns: total, counts_by_label, quotes_not_verified (claims with a quote that
    was not found in its source text), suspicious_count and suspicious ('supported'
    or 'partial' claims whose quote did not verify), unsupported_count and
    unsupported, weak_claims_in_report (suspicious or unsupported claims whose text
    appears verbatim in report_text; null when no report_text), truncated (a list
    was cut at 200), method, next_step.

    The 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.
    
- **rob_record** — Record one risk-of-bias domain judgement for one paper and check its supporting quote.

    Call once per domain. Domains and judgements are fixed per tool and anything
    else is refused; case, spaces and hyphens are forgiven ('Some concerns').
    A paper is assessed with one tool only. Re-sending the same paper + domain
    replaces the judgement. rob_summary computes the overall judgement.

    Returns: updated, tool, domain, judgement (canonical), quote_verified,
    quote_note, domains_recorded, domains_missing (for this paper), warnings.

    Does NOT assess bias itself: the judgement is yours.
    
- **rob_summary** — Overall risk-of-bias judgement per paper by the tool's published rule, plus traffic-light table rows.

    Rules: RoB 2 (Sterne et al. 2019), ROBINS-I (Sterne et al. 2016) and the AHRQ
    thresholds for Newcastle-Ottawa stars; see overall_rule in the result. Where the
    guidance leaves room for reviewer judgement (RoB 2 with several 'some concerns'
    domains, ROBINS-I with 'no information' domains) the result says so in notes, and
    an 'overall' judgement you recorded with rob_record is used when the rule allows it.

    Returns: papers (paper_ref, tool, domains, missing_domains, overall,
    overall_by_rule, overall_recorded, notes, and total_stars for NOS or
    no_information_domains for ROBINS-I), table (one row per paper with each domain
    and overall, for a traffic-light plot), counts_by_overall,
    papers_with_unverified_quotes, overall_rule, truncated (lists cut at 200).

    Does NOT assess bias; it applies fixed rules to your recorded judgements.
    
- **stats_check_ratio_ci** — Check whether a ratio estimate is consistent with its confidence interval and optional p-value.

    For RR, OR, HR, IRR and ratio of means, a symmetric interval on the log
    scale has the point estimate near the geometric midpoint of its limits.
    The log-scale SE is back-calculated as (ln upper - ln lower) / (2 z), and an
    optional reported p-value is compared with the two-sided p implied by that SE.
    The rounding-aware tolerance is h + rel_tol * |computed| with
    h = 0.5 * 10^-decimals.

    Returns: status ('consistent', 'inconsistent' or 'invalid'), measure,
    estimate, ci_lower, ci_upper, ci_level, decimals, rel_tol, half_unit, checks
    (check, passed, detail), geometric_midpoint, geometric_midpoint_range (low,
    high), se_log, z, p_back_calculated, p_reported, p_half_unit (the rounding allowance used for the
    reported p), assumptions, warnings, saved,
    check_id.

    An 'inconsistent' status means the numbers do not agree under the stated
    rounding; it does not prove the paper is wrong. Invalid numbers are reported
    with status 'invalid' and the reasons in warnings.

    Does NOT read the paper, infer the analysis model, or change stored data.
    
- **stats_recompute_2x2** — Recompute RR, OR and RD from arm-level events and totals, optionally comparing a reported result.

    Arm A is the intervention and arm B the comparator; ratios are A vs B. RR
    and OR use log-scale Wald intervals (Woolf for OR); RD uses a Wald interval.
    A zero cell makes the affected ratio not estimable under
    continuity_correction='none'. With 'add_0.5_if_zero' 0.5 is added to each
    of the four cells when any cell is zero, and the output states that the
    correction was applied. Both arms zero events always leave RR and OR not
    estimable; RD is then 0 with its interval. RD always uses the raw counts.

    A reported object {measure, estimate, ci_lower?, ci_upper?} is compared with
    the recomputed measure using h + rel_tol * |recomputed|, where
    h = 0.5 * 10^-decimals.

    Returns: events_a, total_a, events_b, total_b, arm_a, arm_b,
    continuity_correction, correction_applied, cells_used_for_ratios,
    rr, or, rd (each with estimate, ci_lower, ci_upper, se, estimable, reason),
    reported, comparison (measure, estimable, values, matches, mismatches, note),
    status, assumptions, warnings, saved, check_id.

    Impossible counts are refused with a message naming the field. A comparison
    match is arithmetic agreement under the stated rounding, not proof that the
    paper is correct.

    Does NOT read the paper, pool studies, or adjust for strata or clusters.
    
- **stats_check_evidence** — Run the ratio-CI consistency check over every stored evidence row that has a ratio measure.

    Evidence rows with a non-ratio measure, a missing estimate or a missing
    limit are listed with status 'skipped' and the reason. A stored ci_level is
    a percentage (95 means 95%) and is converted to a fraction. The same
    rounding-aware tolerance as stats_check_ratio_ci is used.

    Returns: rows (paper_ref, outcome, measure, estimate, ci_lower, ci_upper,
    ci_level, status, warnings; capped at 200), truncated, checked, skipped,
    counts (consistent, inconsistent, invalid, skipped), assumptions, note.

    Does NOT save anything, edit evidence rows, or judge the paper's analysis.
    
- **prisma_excluded_studies** — Table of full-text excluded studies, their citations and recorded exclusion reasons.

    Reads full-text 'exclude' decisions for the counting reviewer, normalises exclusion
    reasons consistently with PRISMA flow counts, and checks reconciliation against
    compute_status's excluded_full_text count.

    Returns: ok, format, papers (count), by_reason (the same counts as prisma_status exclusion_reasons), reconciliation
    (rows, excluded_full_text, reconciles, explanation; always over every row), truncated,
    next_offset (pass as offset for the next page of up to 200 rows), and table (when markdown)
    or rows (when json). Each row in rows has paper_ref, citation, reasons, reason_missing.

    Does NOT verify the scientific validity of exclusion decisions or reasons; reports
    recorded audit data only.
    
- **manuscript_check** — Check manuscript sections against recorded review audit data.

    Compares stated PRISMA counts, cross-section count consistency, effect estimates
    and confidence intervals, search databases, search dates, reviewer counts, risk of
    bias tools, and synthesis methods against the audit trail.

    The manuscript side is read with text patterns (database names, dates, tools,
    methods, counts), so every finding is a lead to check by hand: a 'mismatch' means
    the pattern read a value that differs from the record, not proof of an error.

    Returns: ok, method ('pattern'), findings (each: kind, severity 'mismatch'|'not_in_record'|'unknown'|'omitted',
    section, line, excerpt, stated, recorded, field, message; capped at 200), truncated,
    quantity_map (includes reports_included and study_count), counts_by_kind,
    counts_by_severity, checked, not_checked, note.

    Does NOT judge the truth of scientific claims, check semantic entailment, or evaluate
    methodological quality; compares record-backed quantities and factual statements only.
    
- **review_status** — One-call overview of a review: what is recorded, what is missing, warnings and the next steps in order.

    Always pass warnings (such as human screening caution and same-model warnings)
    to the user.

    Call at the start of a session (to pick up where the review stopped) and before
    writing the report. It reads every record; it never changes anything.

    Returns: review (title, question, years), phase (first unfinished step:
    protocol, searching, deduplication, title_abstract_screening,
    full_text_screening, data_extraction, risk_of_bias, claim_checking, reporting),
    protocol (complete, missing fields), prisma (key counts, complete, or error),
    screening_reviewers (per stage), screening_stages, reviewers, included_studies,
    extraction (rows and gaps), risk_of_bias (coverage of included studies),
    claims (counts), dois (checked, retracted, not_found, included DOIs not yet
    checked), warnings, next_steps (at most 10, in workflow order). Lists of
    paper_refs show the first 20.
    
- **export_bundle** — Export the whole audit trail as one text document for the review's supplementary material.

    Always pass warnings (such as human screening caution and same-model warnings)
    to the user.

    Contains: review metadata, protocol and amendments, search log, deduplication,
    PRISMA counts and invariants with a Mermaid flow diagram, every screening
    decision (up to 5000), reviewer agreement for each reviewer pair, evidence
    table, risk-of-bias judgements with the overall rules, claim checks, saved DOI
    checks, reports-to-studies grouping and aliases, the latest known-item recall
    check, saved statistical checks, the change-history summary, and the open
    warnings and next steps. Source texts are not included (only their lengths and
    hashes, in json).

    Returns: format, content (the document), chars, sha256 (of the UTF-8 content),
    suggested_filename, saved_path (with save=true, else null; an existing file of
    the same name is replaced), truncated (more than 5000 screening decisions,
    claims, paper aliases or stats checks), phase.
    
- **review_history** — Query the append-only event history for a review, oldest first.

    Reads recorded lifecycle events (baseline, insert, update, delete) captured
    by SQLite triggers across tracked tables. Filters by table name, paper_ref,
    or row_key.

    Returns: events (list of events with seq, at, table_name, op, row_key, old_row,
    new_row, changed_fields), total (matching events count), next_offset (offset for
    the next page, or null).

    Screening events of a stage that is still open blind are left out until
    screening_stage_close.

    Does NOT provide cryptographic tamper-proofing or hash chaining: records are
    append-only by convention and SQLite triggers within the review file; someone with
    direct file access can modify the database file directly.
    

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "citeproof-ai-mcp": {
    "command": "npx",
    "args": ["-y","citeproof-mcp"],
    "env": {
      "CITEPROOF_MCP_HOME": "",
      "CITEPROOF_NO_AUTO_INSTALL": "",
      "CITEPROOF_UV_HOME": ""
    }
  }
}
```

**Requires environment variables:** `CITEPROOF_MCP_HOME`, `CITEPROOF_NO_AUTO_INSTALL`, `CITEPROOF_UV_HOME` — the values above are empty placeholders; fill in real credentials before running (see the repository for what each one is for).

## Documentation

## What CiteProof-AI-MCP does

CiteProof-AI-MCP adds validation and record-keeping to research agents working on systematic reviews. Its 40 tools cover evidence checks, protocol data, screening records, PRISMA accounting, evidence tables, claim checks, risk-of-bias records, and audit-oriented exports.

The server checks whether a submitted quote occurs in supplied source text, whether evidence-table numbers are present in their supporting quote, and whether estimates fall within their stated confidence limits. It also checks DOI records, citation-to-reference matching, duplicate studies, reviewer agreement, and selected risk-of-bias frameworks. Results are recorded so an agent can preserve the reasoning and evidence behind a review.

## How it works

A connected agent searches for papers, reads them, makes research decisions, and submits the relevant text and records through MCP. CiteProof performs deterministic checks around those inputs rather than generating research conclusions. Quote matching normalizes case, whitespace, quotation marks, dashes, and line-break hyphens while respecting word boundaries.

PRISMA values are derived from recorded searches, deduplication, and screening decisions. Reviewer agreement is calculated with Cohen's kappa for studies assessed by both reviewers, with disagreements listed. DOI and retraction checks use Crossref and doi.org. Citation matching can use DOI, author and year, or title; a resolved citation means that it matched a reference, not that the source supports the claim.

Risk-of-bias validation covers RoB 2, ROBINS-I, and Newcastle-Ottawa using the stated published rules and AHRQ thresholds. Duplicate clustering uses DOI, PMID, or a combination of title, year, and first author.

## Setup and configuration

The npm launcher requires Node.js 18 or newer:

```bash
npx -y citeproof-mcp
```

It locates `uv`, or installs it unless `CITEPROOF_NO_AUTO_INSTALL=1`, then runs the Python server from the wheel associated with the matching GitHub release. Python and Git are not required; when necessary, uv obtains Python 3.12. A local MCP client should launch the command as a stdio server. Claude Desktop can also use the downloadable `.mcpb` bundle, and Claude Code can register it with `claude mcp add citeproof -- npx -y citeproof-mcp`.

Review data is stored under `CITEPROOF_MCP_HOME`, or `~/.citeproof-mcp` when that variable is unset. `CITEPROOF_UV_HOME` can place uv's cache and Python environment inside a Claude Science connector workspace when sandbox file access requires it. Source installation is also possible with `pip install ./MCP`, followed by configuring the client to run `citeproof-mcp`.

## Tools and capabilities

- Verify recorded quotes against supplied source text.
- Check evidence-table numbers, estimates, and confidence limits.
- Validate PRISMA flow counts and screening records.
- Look up DOIs and retraction status through Crossref and doi.org.
- Match author-year, DOI, or title citations to a reference list.
- Track claims, risk-of-bias judgements, duplicates, reviewer agreement, and audit exports.

## Limitations and notes

CiteProof does not contain a language model, search for literature, decide whether a study is correct, or determine whether a matched citation actually supports a claim. Numeric in-text citations such as `[1]` are counted but not resolved to references. If a registry cannot be reached, the DOI result is marked unverified rather than not found.

The local server's network activity is limited to DOI and retraction lookups, aside from first-run downloads by the launcher. Remote custom connectors on claude.ai are not supported; the documented Claude Science connection is a local connector. Files remain on the computer running the server, subject to the configured review-data location.

_Full upstream README: https://allmcps.com/mcp/citeproof-ai-mcp/readme_

