Skip to main content
Glama

Verify extracted document facts

doc_verify_facts
Read-onlyIdempotent

Check values YOU extracted from a document against its text, deterministically; FactLot runs no model. Send the pages as text and one candidate per value: {predicate, value, quote, page}. Each candidate is checked in order: (1) the value's shape (Ingest predicates such as lease.expiration_date YYYY-MM-DD, lease.pro_rata_share in (0, 1], ordered lease.base_rent_schedule steps; any other dotted predicate needs a non-empty value); (2) the quote, at least 12 characters, is on the cited page, where only whitespace, line breaks, letter case and typographic quotes and dashes may differ (a word hyphenated across a line must keep its hyphen; a quote found on exactly one other page is accepted with the page corrected); (3) every number, date and party name in the value is written in the quote, in any common form: 1250000 matches "$1,250,000.00", 0.03 matches "3%" or "three percent", 2031-06-30 matches "June 30, 2031" or "6/30/2031"; text the lease states as written (a prohibited use, a carve-out, a protected use) is written in it as words, ignoring case, punctuation and line breaks; (4) a confidence you give below 0.8 holds it for review; (5) every other part of the value must be confirmed by the quote too: a true/false value, an enum or a summary not written in the quote holds the candidate for review, named in the reason. Verified means every part of the value was found in the quote. Returns verified (FactLot facts: method extracted, citing document_id, page, quote and character span, plus which value parts were checked and as what), needs_review (the quote is on the page but does not state the value: check consistency; low confidence: confidence; a part FactLot cannot confirm from the quote, such as a boolean: coverage) and rejected (wrong shape; quote missing, too short, or on several pages), each with a reason to act on. Not checked: meaning (a quote stating the number in another context passes), and whether the pages came from the file whose sha256 you give.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "document": "<document>",
      "candidates": "<candidates>",
      "as_of": "<as_of>"
    },
    "name": "doc_verify_facts"
  }
}

Input Schema

NameRequiredDescriptionDefault
as_ofYesDate the facts are stated as of (YYYY-MM-DD), usually today.
subjectNoFactLot URN the facts are about, e.g. your lease's fl:lease:… ID. Default: the document ID.
documentYesThe document the candidates were read from.
candidatesYesValues you extracted, each with its quote and page.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedInput schema / properties / candidates / items / properties / commencement
      Added value: +{
      +  "description": "Only for lease.base_rent_schedule written by lease year (steps {lease_years: [1, 5], annual_rent_psf}): the commencement date the step dates are derived from, with its own quote. FactLot checks it like a lease.commencement_date candidate and derives each step: Lease Year N runs from the (N−1)th anniversary of the commencement date to the day before the next. If it does not verify, the schedule stays in needs_review.",
      +  "properties": {
      +    "page": {
      +      "description": "1-based page of this document the quote is on (it may differ from the rent table's page).",
      +      "maximum": 100000,
      +      "minimum": 1,
      +      "type": "integer"
      +    },
      +    "quote": {
      +      "description": "Verbatim text that states the commencement date, at least 12 characters.",
      +      "maxLength": 5000,
      +      "type": "string"
      +    },
      +    "section": {
      +      "description": "Section, if any.",
      +      "maxLength": 200,
      +      "type": "string"
      +    },
      +    "value": {
      +      "description": "The commencement date (YYYY-MM-DD).",
      +      "format": "date",
      +      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "value",
      +    "quote",
      +    "page"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / candidates / items / properties / confirmation
      Added value: +{
      +  "description": "A person's confirmation of the parts of the value no quote can prove (a true/false value, an enum such as a CAM cap method or kick-out party, a paraphrased summary). With it, a candidate whose only gaps are such parts is verified with method human_verified: the parts the quote confirmed are listed under checked and the rest under confirmed_by_person. It never overrides a quote that is not on the page, a number or date the quote does not state, or a confidence below 0.8.",
      +  "properties": {
      +    "at": {
      +      "anyOf": [
      +        {
      +          "format": "date",
      +          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +          "type": "string"
      +        },
      +        {
      +          "format": "date-time",
      +          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      +          "type": "string"
      +        }
      +      ],
      +      "description": "When the person confirmed it: YYYY-MM-DD, or an ISO 8601 timestamp with offset. A date is recorded on the fact as that day at 00:00 UTC."
      +    },
      +    "by": {
      +      "description": "The name or role of the PERSON who read the clause and confirmed the value, e.g. \"J. Smith, lease administrator\". FactLot does not authenticate it. Never set this for a value no person has read: an agent must not confirm its own extraction.",
      +      "maxLength": 200,
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    "note": {
      +      "description": "What the person checked; returned with the result (the fact schema has no field for it).",
      +      "maxLength": 1000,
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "by",
      +    "at"
      +  ],
      +  "type": "object"
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / document / properties / ocr_pages
      Added value: +{
      +  "description": "Optional: pages (1-based) whose text came from OCR rather than the file's text layer (doc_read_pdf and factlot.read_pdf report them). Facts and citations on these pages carry ocr: true, so a reviewer checks the scan.",
      +  "items": {
      +    "maximum": 100000,
      +    "minimum": 1,
      +    "type": "integer"
      +  },
      +  "maxItems": 2000,
      +  "type": "array"
      +}
  3. Added

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the read-only, idempotent, non-destructive, closed-world annotations, the description discloses the deterministic no-model behavior, the ordered checks, confidence review threshold, human confirmation semantics, and the exact verified/needs_review/rejected outcomes with reasons. It also states the tool's limits around meaning and file authenticity, which are valuable behavioral boundaries.

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?

The description is dense and long, but it is front-loaded with the core action and organized around numbered checks, outcome types, and limitations. Some sentences restate schema details such as the 12-character quote minimum and confidence threshold, but most of the length is justified by the verifier's rule complexity.

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 four-parameter tool with nested candidate objects and no output schema, the description supplies the missing coverage: how candidates are evaluated, which conditions produce each result, what the reason refers to, and what is not checked. An agent has enough information to decide when to use it and how to prepare candidates correctly.

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?

Although schema coverage is already 100%, the description adds substantial meaning beyond the schema: it explains quote normalization, alternate numeric and date forms, page correction behavior, confidence handling below 0.8, and how the confirmation field is treated. These details directly affect how an agent must construct and interpret each candidate.

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?

The description states a specific verb and resource: check values extracted from a document against its text, deterministically without a model. It clearly distinguishes the tool as a quote-and-page verifier rather than a general extraction or calculation tool.

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

Usage Guidelines4/5

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

The description makes clear that this is for values the caller extracted and that candidates must be sent with a predicate, value, quote, and page. It also states important exclusions, such as not checking meaning or whether pages came from the file whose sha256 is supplied, though it does not explicitly route to sibling tools like doc_verify_claim or fact_validate.

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.