Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

io.github.lesofi/handinloop-mcp-server

NPM · HANDINLOOP-MCP-SERVER

Human-in-the-loop document extraction: submit a doc, get validated fields and an audit trail.

0 this week 71 Trust /100

Last scanned (4 hours ago)

Scores higher than 40% of npm servers

Category Documents and Files

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security81
  • No malware found by supply-chain analysis.Pass
  • CVE check failed: a known high-severity CVE affects zod 3.25.76, a direct dependency. A fixed version is available. View diagnostics → Fail
  • No install/post-install scripts declared.Pass
  • 30 of 94 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency19
  • Repository check failed: the declared repository URL returned HTTP 404. See how to fix → View diagnostics → Fail
  • Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 8 days ago).Pass
  • Security-disclosure policy not yet verified: we couldn't inspect the source repository.Unverified
Schema Quality & AI Usability63
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 3506 tokens (~350/item across 10 items; 10 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
  • No destabilizing schema changes in the last 30 days.Pass
Tool Coverage99
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 97% of tool parameters carry a description.Partial
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • We read all 10 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
  • An AI judge read all 10 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 2 Nov 26 0
    • Stability: 0.97 → pass security
  • 1 Nov 26 0
    • Stability: pass → 0.97 functional
  • 26 Oct 26 0
    • Stability: 0.97 → pass security
  • 25 Oct 26 0
    • Stability: pass → 0.97 functional
  • 24 Oct 26 −5
    • CVE-2023-54404 affects this package: high ▼ security
    • Known CVEs: pass → fail ▼ security
  • 19 Oct 26 0
    • Stability: 0.97 → pass security
  • 18 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 93 to 97. That category is still filling its 30-day observation window: 28 days of observed history at the previous scan, 29 at this one. The score rises as the window fills, whether or not the server changes.

  • 15 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 83 to 87. That category is still filling its 30-day observation window: 25 days of observed history at the previous scan, 26 at this one. The score rises as the window fills, whether or not the server changes.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 5 Nov 2026 · Analysed npm/handinloop-mcp-server@0.5.0

Provenance No attestation

The registry publishes no build provenance for this version, so there is nothing to verify.

Result No attestation
Ecosystem npm

Background: How many MCP packages publish verified provenance →

Vulnerabilities 1 finding
ID CVE Severity Vector Fix available
GHSA-mrhx-c7xc-m3w5 CVE-2023-54404 high CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H yes

Background: What a vulnerability scan can and cannot prove →

Dependencies 94 packages
Packages resolved 94
Stale 30
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 10 exposed · ~3,506 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
handinloop_estimate_cost ~414

Price a batch of documents BEFORE submitting it (#788). No side effect: nothing is stored, charged, or counted against the free tier. A document costs ceil(pages x the task type's credits_per_page x its line-item multiplier), at least one credit; the multiplier applies when the task type declares a line-item table. The submit charges with the same function, so charged_credits is what the batch costs when every document succeeds and it is submitted in this order this month. A document HandInLoop fails to process (system_error, including after its retries) costs nothing. Args: - task_type: a task type id from handinloop_list_task_types, OR - fields: custom inline fields (priced as a custom extraction). Provide task_type OR fields. - documents: 1..500, each exactly one of: pages (your own page count — cheapest, sends no file), document_base64 (the API counts the pages), or document_url (fetched here, then counted by the API). At most 25 documents may be files (base64 or URL); give pages for the rest. file_name is optional on each. Returns: { task_type, line_items, rate: { credits_per_page, line_item_multiplier }, documents: [{ index, file_name?, pages, credits, free, error? }], pages, credits, free_documents, charged_credits, available_credits, covered, spend: { spent_this_month, cap, overage, overage_credits, blocked }, refused? }. covered false or spend.blocked true means the submit would be refused (402). A file the API could not read is listed under refused, with why, and left out of the totals.

NameTypeReqDescription
documentsarrayyes–
fieldsarray–Custom extraction fields. Provide task_type OR fields.
task_typestring–Task type id, e.g. 'invoice'. Provide this OR fields.

No output schema declared.

No examples provided.

handinloop_get_job_result ~352

Fetch the validated extraction result for a completed job. Only call once handinloop_get_job_status reports status 'completed' (calling earlier returns an error with the remaining time). Returns: { job_id, task_type, status, fields: [{ name, value, confidence (0..1), human_verified }], line_items?: [...], // for invoice-like documents audit_trail: [{ at, actor: system|ai|human, action }], discrepancies?: [{ field, expected, actual, delta, kind }], // freight audit (#157) proof?: { // the signed Proof Object (#147) job_id, task_type, status, issued_at, fields: [{ name, value, confidence, verified_by: human|ai, verified_at? }], audit_trail: [...], signature?: { algorithm, key_id, value } // absent if signing not configured } } Fields with human_verified=true were confirmed or corrected by a person on your own team, not the AI — treat confidence 1.0 as authoritative. The audit_trail documents every step for compliance purposes; preserve it when storing results. The 'proof' is a portable, verifiable record: pass it downstream so another party can confirm this data's provenance by verifying the Ed25519 signature against HandInLoop's published public key (GET /v1/proof/public-key) — no callback needed. Preserve it intact; verified_by distinguishes human-signed fields from AI-verified ones. It's omitted only if the proof could not be retrieved.

NameTypeReqDescription
job_idstringyesJob id returned by handinloop_submit_extraction_job

No output schema declared.

No examples provided.

handinloop_get_job_status ~157

Check the status of a previously submitted extraction job. Statuses: 'queued' (waiting for a worker) -> 'in_review' (being processed: the worker extracting and checking it, then a person if it needs one) -> 'completed' (result ready) | 'rejected' (invalid document). Use estimated_seconds_remaining to pick a sensible polling interval; for scheduled routines, checking on the next run is usually enough. Args: - job_id: id returned by handinloop_submit_extraction_job Returns: { job_id, task_type, status, submitted_at, finished_at?, estimated_seconds_remaining? }

NameTypeReqDescription
job_idstringyesJob id returned by handinloop_submit_extraction_job

No output schema declared.

No examples provided.

handinloop_get_pilot_run ~221

Get a pilot run's live status board — its per-document status and run-level counts (#252). Use after handinloop_submit_pilot_batch to watch the batch clear: documents move queued -> in_review -> completed | rejected. The run is done when counts.completed + counts.rejected == counts.total. in_review covers two stages: the worker still extracting and checking a document, then a person reviewing it. counts.awaiting_human is how many of the in_review documents a person has; the rest (in_review - awaiting_human) are still with the worker. Args: - pilot_run_id: the run to check (must belong to your account). Returns: { pilot_run: { id, name, task_type, status }, items: [{ job_id, file_name?, status, submitted_at, finished_at? }], counts: { total, queued, in_review, awaiting_human, completed, rejected } }

NameTypeReqDescription
pilot_run_idstringyesThe pilot run to check (must be yours)

No output schema declared.

No examples provided.

handinloop_get_task_type ~106

Read one of your saved task types (#583), including its prompt_template, gate and review_policy, which handinloop_list_task_types does not show. Args: - id: the saved task type's id. Returns { id, name, description, output_fields, prompt_template?, gate?, review_policy? }. A built-in type, or an id you have not saved, is not found.

NameTypeReqDescription
idstringyesThe saved task type's id

No output schema declared.

No examples provided.

handinloop_list_task_types ~96

List the document extraction task types the HandInLoop human-in-the-loop platform supports. Call this first to discover valid 'task_type' values for handinloop_submit_extraction_job, and to see which fields each task type returns. Returns: { task_types: [{ id, name, description, output_fields[], hidden? }] }. A type marked hidden: true is retired: do not choose it for new work.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

handinloop_propose_fields ~217

Ask HandInLoop to propose the fields worth extracting from a document — the "what should I extract?" assist. Given a document (and an optional goal), the model suggests a field set you can then pass as 'fields' to handinloop_submit_extraction_job for a custom, human-verified extraction. Synchronous: returns immediately, no job, no human review. Args: - document_url OR document_base64: the document (PDF/image). Exactly one required. - file_name (optional) - goal (optional): focus, e.g. "accounts payable" Returns: { fields: [{ name, description }] }

NameTypeReqDescription
document_base64string–Base64-encoded document content (alternative to document_url)
document_urlstring–Publicly fetchable URL of the document (PDF or image)
file_namestring–Original filename, e.g. 'do-123.pdf'
goalstring–Optional focus, e.g. 'accounts payable'

No output schema declared.

No examples provided.

handinloop_save_task_type ~525

Save a named custom field set as a reusable task type (#103 Phase B). Once saved, submit against it by passing its returned id as 'task_type' to handinloop_submit_extraction_job — no need to re-send the fields each time. Saved types also appear in handinloop_list_task_types. Saving an existing id updates it. Needs an API key with the 'workflows' scope (#951), which no key has unless an organisation admin or engineer ticked it when making the key: a saved type changes what every later job of the account extracts. Without it the call fails with the missing scope named; ask a person to issue a key with 'workflows' rather than retrying. Args: - fields: [{ name, description? }] — the field set (required, at least one). - name (optional): human name; the id is derived from it if 'id' is omitted. - id (optional): stable handle (lowercase letter then letters/digits/underscores). Must not collide with a built-in. - description (optional). - prompt_template (optional): instructions sent to the extraction model with every document of this type, e.g. "Dates are day-first; ignore the remittance slip." Up to 4000 characters. Omit to keep the saved one; "" clears it. - gate (optional): { critical_fields?: string[], min_confidence?: number } — fields a person must sign off on every document of this type (each must be one of 'fields'), and a confidence floor. A submit's own 'verify' is merged with it, stricter wins. Omit to keep the saved one; {} clears it. Returns the saved TaskType { id, name, description, output_fields, prompt_template?, gate?, review_policy? }. review_policy (#585: the type's confidence threshold and QA sample rate) is read-only here: an organisation admin or engineer sets it in the portal, and a save keeps it.

NameTypeReqDescription
descriptionstring–Optional description of the type
fieldsarrayyesThe field set to save (at least one)
gateobject–Fields a person must sign off on every document of this type; {} clears
idstring–Stable handle; derived from name if omitted
namestring–Human name, e.g. 'Delivery Order'
prompt_templatestring–Instructions to the extraction model for every document of this type; "" clears

No output schema declared.

No examples provided.

handinloop_submit_extraction_job ~950

Submit a document to HandInLoop for extraction with human-in-the-loop validation. AI reads the document and scores every field for confidence first; low-confidence fields are reviewed and corrected by your own team, in a review screen built for it, before delivery. Every decision is signed and recorded. The result is validated data with per-field confidence and a complete audit trail. ASYNC: returns immediately with a job_id and status 'queued'. Human turnaround is minutes to hours in production — poll handinloop_get_job_status (respect estimated_seconds_remaining), then call handinloop_get_job_result once status is 'completed'. Ideal for scheduled/recurring workflows. VERIFIED-ANSWER LOOP (trust contract): declare your bar with 'verify' and hand off with 'callback_url'. - verify.critical_fields: names that MUST be human-verified before you get them back — a critical field the AI returns unverified (or omits) always goes to a human, even at confidence 1.0. Use this for anything you must not act on unchecked (e.g. "total", "bank_account"). - verify.min_confidence (0..1): a stricter per-job bar; any field below it is routed to a human. - callback_url: an https endpoint HandInLoop POSTs the finished result to (with the signed proof embedded), so you can submit and walk away instead of polling. Verify the POST offline via the proof's signature against GET /v1/proof/public-key. Delivery status shows on handinloop_get_job_status under 'callback'. Args: - task_type: one of the ids from handinloop_list_task_types (e.g. "invoice"), OR - fields: for CUSTOM extraction, describe the fields to extract yourself — [{ name, description? }]. Works on ANY document, not just the built-in task types. Provide task_type OR fields. - document_url OR document_base64: the document (PDF/image). Exactly one required. - file_name (optional): original filename for routing and audit - instructions (optional): note for the human reviewer - verify (optional): { critical_fiel…

NameTypeReqDescription
callback_urlstring–https endpoint the result + signed proof is POSTed to on completion (submit and walk away)
document_base64string–Base64-encoded document content (alternative to document_url)
document_urlstring–Publicly fetchable URL of the document (PDF or image)
expectedobject–Freight-invoice audit (#157): your agreed values keyed by field name (e.g. { ocean_freight: 1800, container_count: 5 }). Extracted fields that don't match are flagged as discrepancies (overcharge/und…
fieldsarray–Custom extraction: define the fields to extract instead of a built-in task_type. Provide task_type OR fields.
file_namestring–Original filename, e.g. 'inv-04187.pdf'
instructionsstring–Free-form note passed to the human reviewer
task_typestring–Built-in task type id from handinloop_list_task_types, e.g. 'invoice'. Provide this OR fields.
tolerancesobject–Freight-invoice audit per-field tolerance (#157): allowed slack keyed by field name, an absolute amount ('50') or a percentage of the expected value ('5%') — e.g. { ocean_freight: '50', documentation…
verifyobject–Verified-Answer Loop trust gate (#155): forces human review, never skips it

No output schema declared.

No examples provided.

handinloop_submit_pilot_batch ~468

Submit a batch of documents to an existing HandInLoop pilot run — the agent/API intake for a Shadow-Pilot (#257). A pilot run groups a client's documents for a side-by-side accuracy/turnaround/savings report. Create the run in the portal (app.handinloop.com/pilots) or have a human create it, then pass its 'pilot_run_id' here; every document is stamped with it and joins the run's status board and report. All documents use the run's task type — you don't repeat it. ASYNC and per-document: each document becomes its own extraction job (returns a job_id). One bad document (unfetchable URL, etc.) is reported as a per-item error and never fails the rest of the batch. Poll progress with handinloop_get_pilot_run. Args: - pilot_run_id: the run to submit into (from the portal; must belong to your account). - documents: [{ document_url OR document_base64, source_ref?, file_name? }] (1..200). - document_url is fetched here and sent as content; source_ref is your own id/filename for the doc, used to match it to a ground-truth row for accuracy scoring — set it to the filename you used in your ground-truth CSV. - verification_gate (optional): { critical_fields: string[], min_confidence?: number }. Applied to the run before submitting, so every document in the batch inherits it — critical fields must be human-verified before any result comes back. Only ever makes review stricter. Returns: { pilot_run_id, task_type, accepted, rejected, submitted: [{ source_ref?, file_name?, job_id? , status?, error? }] }

NameTypeReqDescription
documentsarrayyesThe documents to submit (1..200); each becomes its own extraction job
pilot_run_idstringyesThe pilot run to submit into (created in the portal; must be yours)
verification_gateobject–Trust bar applied to the whole batch (#258): set the run's verification gate before submitting, so every document inherits it. Only ever makes review stricter — it never skips human review. Persists…

No output schema declared.

No examples provided.

Install

How do I install the io.github.lesofi/handinloop-mcp-server server?

io.github.lesofi/handinloop-mcp-server runs locally as an npm package, launched with npx -y handinloop-mcp-server. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

npm · handinloop-mcp-server

# add to Claude Code
claude mcp add lesofi-handinloop-mcp-server -- npx -y handinloop-mcp-server
Common questions

What is the io.github.lesofi/handinloop-mcp-server server?

io.github.lesofi/handinloop-mcp-server is listed in the public MCP registry as io.github.lesofi/handinloop-mcp-server. Human-in-the-loop document extraction: submit a doc, get validated fields and an audit trail. This page covers its npm package (handinloop-mcp-server).

Is the io.github.lesofi/handinloop-mcp-server server safe to use?

io.github.lesofi/handinloop-mcp-server scores 71 out of 100 on VerifyMCP. We recorded 1 known advisory against it as of 5 November 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the io.github.lesofi/handinloop-mcp-server server expose?

io.github.lesofi/handinloop-mcp-server exposes 10 tools: handinloop_list_task_types, handinloop_propose_fields, handinloop_save_task_type, handinloop_get_task_type, handinloop_estimate_cost, and 5 more. Their descriptions and schemas cost roughly 3,506 tokens of context every time the server is loaded.

Is the io.github.lesofi/handinloop-mcp-server server still maintained?

io.github.lesofi/handinloop-mcp-server is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the io.github.lesofi/handinloop-mcp-server server under?

io.github.lesofi/handinloop-mcp-server declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.