Documents in, structured data out, styled documents back
Until today, Inkrun did one thing: your agent handed it Markdown, and it handed back a PDF locked to your templates. That's half of a document workflow.
The other half fires first. An invoice lands in an inbox. A contract arrives for review. A stack of receipts needs to become an expense report. Before your agent can act on any of it — let alone render something back — it needs the data out of the document. Reliably. Without hallucinating a total.
That half ships today. Inkrun now extracts structured data from PDFs, through the same MCP server and the same API key your agent already uses to create them:
inspect_document— free triage: page count, which pages are scanned, what extraction will cost — before you spend anything.extract— structured data out, using a built-in preset (invoice,receipt,contract_terms,table_dump,full_text) or your own JSON Schema.extract_tables— every recoverable table as rows + CSV, tagged with the page it came from.
One MCP server, both directions. That's the whole announcement; the rest of this post is why the extraction is trustworthy enough to automate on, and a worked example.
Grounded, or null — never a guess
The failure mode of "just ask a model to read the invoice" is well known: it works in the demo, then one day the model pads a missing PO number with a plausible one, and your pipeline books it.
Inkrun's extraction is built around one rule: every returned value must be grounded at a concrete position in the document. Extraction runs deterministic, positioned-text rules first — no model involved, reproducible run-to-run. Fields the rules can't ground can escalate to a model tier, but a model's answer is only trusted after it's verified against the document's actual text.
And when a value genuinely isn't there? You get null plus a warning naming the field. Not a guess. Ever.
Every field also carries provenance you can act on programmatically:
{
"data": {
"vendor": "Acme Co",
"total": 1240.50,
"due_date": null
},
"fields": {
"vendor": { "confidence": 0.98, "method": "deterministic", "page": 1 },
"total": { "confidence": 0.99, "method": "deterministic", "page": 2 }
},
"warnings": ["due_date could not be grounded in the document and was returned as null."],
"extraction_method": "deterministic",
"credits_charged": 1
}
The confidence score is computed by Inkrun from where and how the value was found — never a model's self-reported confidence. Values read off scanned pages by the opt-in OCR tier are labelled method: "ocr" and capped at 0.8, so your pipeline can always tell a pixel-read value from a text-verified one.
The round trip, worked: invoice in, summary out
Here's the shape of a real agent workflow, end to end, against one MCP server.
1. Inspect (free). The agent receives invoice-0042.pdf and asks what it's dealing with:
inspect_document→ 2 pages, all digital, deterministic extraction will cost 1 credit.
2. Extract. One call, one preset:
extractwithpreset: "invoice"→ vendor, invoice number, dates, subtotal, tax, total, and line items — each grounded to a page, ungrounded fields null with a warning.
3. Act on the data. The agent checks fields.total.confidence, matches the PO in your system, flags the missing due_date for a human — ordinary code over trustworthy JSON.
4. Render the result back. The same server turns the outcome into a document a human actually wants to read:
create_pdfwithtemplate: "invoice-summary"→ a themed, on-brand PDF summarizing the invoice and its approval status, as a download link.
Documents in, structured data out, styled documents back. Your agent never left one connector.
What happens to your documents
This is the first question anyone should ask a document-extraction vendor, so here's ours up front:
- Processing-only by default. Your document is processed in memory and the result returned inline. Source bytes are never written to storage. (A debug window for result JSON is opt-in and bounded; the default keeps nothing.)
- No training on your documents — ours or anyone else's.
- The deterministic tier never leaves our servers. The optional model tier sends extracted text and layout — never your file — and the opt-in OCR tier sends rasterized images of scanned pages only, both routed with data-collection denied and zero-data-retention flags on every call.
The full posture, including exactly what each tier sends where, is published at inkrun.dev/docs/data-handling — precisely worded, traceable to the code that enforces it.
Pricing: one meter, both directions
Extraction bills in the same credits your renders already use — 1 PDF render = 1 credit, exactly as before, and inspection is free. Deterministic extraction starts at 1 credit per document, with the model and OCR tiers costing more and only ever charged when they actually run. The current numbers for every tier live on the pricing page, rendered from the same constants the API charges from.
Try it
If Inkrun is already connected to your agent, there's nothing to set up — extract and inspect_document are in its tool list right now. If it isn't:
- Create a free account — the free tier's monthly credits cover both directions.
- Add
https://inkrun.dev/api/mcpas a custom connector in Claude (or any MCP client — setup guides here). - Hand your agent a PDF and ask it what's inside.
The docs cover the details: extract, inspect, and extract tables.