Check a set of values against the paper's identities
Send the values you captured (any source: a model, a keyer, another system). Get back every identity, the failing fields, and the verdict. Needs the gate token (Authorization: Bearer).
Queue a live read on AMD and follow it
One live read runs at a time; a job waits in a short queue and reports its place, stages and elapsed time. The same events stream as server-sent events at /api/live/events/{job}.
Without a key, read the stored verdict of any form: curl -s https://twohands.pytr.dev/api/form/211294C0100
Export the captured records
One record per form: status, fields to key, reason, and every value. Filter with ?status=accepted,resolved to take only what is final.
Any polling station
What I have for one station: a measured read with its receipts, the live audit's read, or "not audited yet"; queue a live read and get its place. Search ids with /api/station/search?q=2024; the live strip's numbers at /api/live-strip.
CLI
pip install -e ".[mcp]" (from the repo) gives the twohands command (also python -m twohands). It reuses the core and the web app's audit module, so it gives the same disputes, order, CSV, fingerprint and Merkle root as Audit your capture.
audit masks each scan in memory, reads only the forms without a read through the configured OpenAI-compatible endpoint, and writes report.html, report.csv, merkle_root.txt, summary.json and disputes.json. --from-stored uses the stored pre-registered reads only, and reproduces the published sample root.
MCP
An MCP server on the official Python SDK (twohands/mcp_server.py) with four tools: read_form, gate, audit_capture and verify_receipt.
File paths must lie under the repo, the working directory or TWOHANDS_MCP_ROOTS; over HTTP, tools that would call the model are refused unless started with --allow-reads.