Research Scan
Type to search documentation.

MCP tools

Four tools, one per decision the pipeline needs from a model, and the phase machine that sequences them.

The MCP server exposes four tools. Each corresponds to a point where the pipeline needs a judgement it cannot make itself.

The server retrieves, expands, counts coverage, shortlists, verifies and emits. It never writes queries, never scores a paper and never composes prose. You supply every judgement, using the skill’s rubrics.

How MCP clients reach the research-scan pipelineClaude Code, Claude Desktop, Cursor and custom agents all launch research-scan mcp over stdio. The server exposes four tools — scan_start, scan_continue, scan_verify and scan_result — one per decision the pipeline needs from a model. Behind them runs the same pipeline, writing the same run-directory artifacts with the same DOI verification.Claude CodeClaude DesktopCursorAny MCP clientresearch-scan mcpstdio · your client launches it · reads no token and needs nonescan_startscan_continuescan_verifyscan_resultTHE SAME PIPELINEretrieve · expand · dedupe · coverage · shortlist · verify · emitthe same run-directory artifacts, the same DOI verificationEVIDENCE OBJECTSEvidencePacket JSON + Markdown, identical to a skill-driven run
Four tools, one per decision the pipeline needs from a model. They are not a chat endpoint over the pipeline — the client's model supplies exactly the cognition the skill would, in the same stage order.

The response envelope

Every call returns the same shape:

json
{
"scan_id": "…",
"phase": "screen",
"status": "ok",
"next_action": "screen_candidates",
"progress": { },
"payload": { }
}

Follow next_action on every response. It tells you what the pipeline needs next, and the payload carries what you need to decide it.

next_actionWhat to send back
screen_candidatesscan_continue with screen_scores for the batch in the payload.
write_gap_queriesscan_continue with gap_queries. An empty list skips the gap round.
rank_shortlistscan_continue with ranked_entries for the page in the payload.
verify_rankedscan_verify.
completescan_result.

Phases are screen, gap, rank and complete.

Never issue two mutating calls for the same scan_id at once. A call that arrives while another is running is answered in_progress — do not resubmit; poll scan_result, which is read-only and never blocked.

scan_start

Open a scan and run retrieval. Returns the first screening batch.

ParameterTypeNotes
scan_idstringYou generate it: a fresh canonical lowercase UUIDv4, one per brief.
briefstringThe project brief in Markdown, or the question.
queriesQueryPlanThe full query plan you wrote under the plan rubric. The server never writes queries for you.
profilequick/standard/deepDefault standard.
topintPapers to emit. Default 10.
foundationalintOut-of-window slots within top. Default 2.
since, untilstringWindow bounds, YYYY-MM.
slugstringRun name.
max_candidates, per_queryintOverride the profile’s depth and cap.
force_gap_roundboolRun the gap round whatever the profile says.

Retrieval is the longest call in a scan. If it fails or times out, call it again with the same scan_id and the same arguments — the server resumes the run it already has instead of starting a second one.

The same arguments means the same. A changed brief or plan under an id already in use is refused with scan_id_conflict rather than silently applied, and the error names which fields differ.

scan_continue

Submit the artifact the current phase asked for, and get the next decision.

ParameterTypeWhen
scan_idstringAlways.
screen_scoreslistnext_action is screen_candidates. Score every item in the batch.
gap_querieslistnext_action is write_gap_queries.
ranked_entrieslistnext_action is rank_shortlist.

Send exactly one of the three. Send none of them to poll the current phase.

An empty gap_queries list is a meaningful answer: it means you found nothing worth reformulating, and the gap round is skipped.

The shortlist is handed to you a page at a time; the payload carries the records for the page you are on.

scan_verify

Verify every ranked paper against the live record, then emit the evidence packet.

ParameterTypeNotes
scan_idstringAlways.
ranked_entrieslistOptional. Any final entries you still hold are merged first.

Call it once next_action is verify_ranked.

Verification is the engine’s. DOIs and titles are checked, never repaired — the same rule that governs the CLI stage.

scan_result

Read a scan’s result. Read-only, never blocked, safe to poll while a call is running.

Takes scan_id only.

On a finished scan the payload carries the evidence packets’ summary rows, the unverified list, the counts, coverage.json and the rendered evidence.md.

Because it is read-only, it is also the correct way to check on a scan whose mutating call is still in flight.

The narrative parts of a report — why these papers, what the coverage risks are — are yours to write. The server does not compose prose.

Where runs live

The adapter keeps one directory per scan_id under $RESEARCH_SCAN_MCP_DATA, defaulting to ~/.local/share/research-scan-mcp/runs/. Inside it is an ordinary run directory with the same files a CLI-driven scan produces, so everything in File formats applies unchanged.

The adapter drives the CLI as a subprocess and reads its exit codes. It never imports a stage’s internals, and it makes no judgement about papers.

Errors

Failures come back as a refusal you can act on, carrying a reason code — a bad artifact, the wrong phase for the call, or a stage that failed — with the CLI’s own structured error rather than a stack trace.

scan_id_conflict is the one worth handling explicitly: it means the id is in use with different inputs. Use a fresh id for a different brief.

Last updated Aug 21, 2026