Skip to main content
Glama

Stipple — Document Verification & Extraction

Extract fields from a document

extract_fields
Read-only

Extract structured FIELDS from a document (PDF or image) with a vision model.

USE THIS WHEN you need specific values OUT of a document — a payslip's gross/net, an invoice's
total/ABN, a form's checkboxes, a table's cells — rather than a yes/no about the document. (For
"is this genuine?" use verify_document; "what kind of document is this?" is
`options={"classify": true}` right here.)

Say WHAT to pull, four ways:
  - `fields`: an ad-hoc list — names like ["gross_pay","abn"], or objects
    {"name":..., "type":"text|amount|date|boolean", "description":...}. THE general case: ask
    for exactly the fields your task needs. Use type "boolean" for a checkbox/tickbox.
    `"question"` works instead of `"description"` if you would rather just ask:
    {"name":"customer_name", "question":"What is the customer name?"}.
  - `template`: a named preset — "payslip", "tax_invoice", "bank_statement", "receipt".
  - NEITHER: AUTO — the document is classified and that type's fields are used.
  - auto on an unrecognised type: schema-free — every labelled field is returned.

Provide the document ONE way: `url` (a public http(s) link — fetched server-side, the cheapest
call) OR `bytes_b64` (inline base64, plus `filename` for PDF-vs-image routing). `country` is an
optional hint; `max_pages` caps how many pages are read (default a few; hard ceiling 10).

`options` turns on extra capabilities. Every one defaults OFF, and asking for one that this
server does not support is an ERROR naming it — never a silent no-op, so you can always tell
"asked wrongly" from "nothing found". Available today:
  - `{"grounding": true}` — every value gains `bbox` (the rectangle it was read from, in PDF
    points, origin top-left) and `text_layer_match`. Use it to CITE a value back to the page.
    Born-digital PDFs only for now; a scan returns `bbox: null` and `grounding: "none"`.
  - `{"flag_below": 0.7}` — adds `needs_review`, the fields under that confidence, weakest
    first. Use it to route the doubtful ones to a human instead of checking everything.
  - `{"tables": true}` — adds `tables`: whole tables with their rows. On a PDF these are
    read from the document's own rules and coordinates (exact cells, merged-cell colspans,
    no model call and NO CREDIT for the table pass); on a scan the model reads the rows and
    the table says `source: "vlm"` with no cell geometry. `{"tables": {"formats":
    ["json","markdown","html"], "borderless": true, "cells": true}}` to tune it.
  - `{"classify": true}` — adds `classification`: the full verdict (type, country,
    confidence, evidence), not just the routing. Free in auto mode.
  - `{"redact": true}` — adds `pii` (a MASKED inventory) and `redacted_text`, so you can
    extract and check for personal data in ONE call. A field you NAMED is still returned in
    full; the inventory never is. Two things to know before turning it on: `redacted_text`
    is the document's WHOLE text body with detected PII replaced — for a PDF that means
    every page, not just the ones `max_pages` covers — and redaction is best-effort
    coverage, so anything it failed to detect stays in that text verbatim. It also costs
    an extra page-equivalent per page, because it is a second model pass.
  - `{"layout": true}` — adds `layout.blocks`: every text block with its role
    (heading/body), font, size, column and reading order. Born-digital PDFs only; free.
  - `{"links": true}` — adds `links`: the PDF's own link annotations with uri, anchor
    text and bbox. Free. A URL merely PRINTED on the page is not an annotation.
  - `{"figures": true}` — adds `figures`: where the embedded images sit (bbox and pixel
    size), never the bytes. Free.
  - `{"chunks": true}` — adds `chunks`: retrieval-ready pieces that carry provenance a
    text splitter cannot give you — `heading_path` (where in the document), `bbox` and
    page range (citable back to the page), tables never sliced. Six strategies via
    `{"chunks": {"strategy": "section|page|chars|recursive|element|hierarchical",
    "max_chars": 1500, "min_chars": 200, "overlap": 100, "include_headings": true}}`.
    `hierarchical` adds parent context chunks for small-to-big retrieval. Born-digital
    PDFs only; free.
  - `{"split": true}` — adds `documents`: the page ranges of the distinct documents in
    one file (a bundle of 3 stapled PDFs -> 3 entries with types). One classifier call
    per page, so it costs +1 page-equivalent per page read.
`render_scale` (one of 1.0, 1.5, 2.0, 3.0, 4.0; default 2.0) raises rasterisation for small or
dense print. Call `GET /v1/extract/capabilities` for the full machine-readable list.

COST: 1 credit per page read, minimum 1 — with `fields` or a `template` given, a one-page
receipt costs 1 and a ten-page statement costs 10; AUTO mode adds 1 for the routing
classification. Options that add model reads add page-equivalents (`redact` +pages, `split`
+pages replacing the auto/classify +1, `tables` +pages only on a scan); deterministic work
is free, and an encrypted PDF is charged the one-page floor only. Pages charged is
min(`max_pages`, the document's real length), resolved before the call runs, so you can
predict the price. Set `max_pages` to cap your spend on a long document.
CAPABILITY-ONLY: `options.classify` and/or `options.redact` with no `fields`, no
`template` and no other option skips field extraction entirely — classify-only costs
1 credit and redact-only 1 per page, exactly what the retired classify_document and
redact_pii tools charged.

Returns `{mode, document_type, fields{name:{value,confidence,page}}, not_found, pages_read,
page_limit, page_count}`. `page_count` is the document's real length, so you can see when
`max_pages` truncated it. EXTRACTION, not verification — values are what the document SHOWS,
not proof it is genuine. A field that isn't clearly present comes back in `not_found` (it
abstains rather than guessing).

`text_layer_match` is `exact` / `normalised` when the printed value was located on the page,
`multiple` when the same string appears more than once (no box — we will not guess which), and
`absent` when it is not there. It reports whether the string was FOUND, not that the value is
correct. The document is never stored.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlNo
fieldsNo
countryNo
optionsNo
filenameNodocument.pdf
templateNo
bytes_b64No
max_pagesNo
render_scaleNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedInput schema / properties / options
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Options"
      +}
    • addedInput schema / properties / render_scale
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "number"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Render Scale"
      +}
  2. Added

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses far beyond the single readOnlyHint annotation: the full credit model ('1 credit per page read, minimum 1... Pages charged is min(max_pages, the document's real length), resolved before the call runs'), error semantics ('asking for one that this server does not support is an ERROR naming it — never a silent no-op'), abstention behavior (not_found), non-verification ('values are what the document SHOWS, not proof it is genuine'), per-option caveats (redact is best-effort and a second model pass; grounding is born-digital-only), and 'The document is never stored.' No contradiction with readOnlyHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded: purpose and when-to-use precede parameters, and it is organized into scannable sections (input, options, COST, returns, caveats). It is long (~700 words), but that length is largely earned by 9 parameters, 10 options, and a cost model; minor redundancy between per-option cost notes and the dedicated COST section keeps it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a very high-complexity tool with a bare schema, minimal annotations, and an output schema, the description covers input selection, output shape (mode, fields, not_found, pages_read), cost prediction, error behavior, and edge cases (AUTO mode, unrecognised types, capability-only calls, both url and bytes_b64). It even points to GET /v1/extract/capabilities for the machine-readable capability list.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% — the schema supplies only types and defaults — so the description must compensate fully, and it does: fields is explained in three shapes including the type enum and the 'question' alias, template lists concrete presets ('payslip', 'tax_invoice', 'bank_statement', 'receipt'), url vs bytes_b64 carries routing and cost implications, max_pages has 'default a few; hard ceiling 10', render_scale is fully enumerated, and every option's sub-parameters are specified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+method: 'Extract structured FIELDS from a document (PDF or image) with a vision model.' It explicitly differentiates from siblings — 'For "is this genuine?" use verify_document' — and routes classification to an option here rather than a separate tool. An agent can tell this apart from every sibling without reading a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger with concrete examples: 'USE THIS WHEN you need specific values OUT of a document — a payslip's gross/net, an invoice's total/ABN... rather than a yes/no about the document.' It names the alternative (verify_document), states that classification is handled via options.classify, and explains the capability-only modes that replace the retired classify_document and redact_pii tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.