BlogHow to Give an AI Agent the Ability to Read Invoices and Receipts

How to Give an AI Agent the Ability to Read Invoices and Receipts

2026-07-21 · 5 min read

AI agents in 2026 are good at reasoning and terrible at documents. An agent can plan a multi-step workflow, call five tools, and write a summary — but the moment a PDF invoice lands in the loop, it either guesses at the numbers or stalls. Reading a receipt reliably is not a reasoning problem. It's an extraction problem, and it's exactly the kind of thing agents should delegate to a tool rather than attempt themselves.

This is a short guide to wiring document extraction into an agent as a tool it can call — using plain function calling, and using the Model Context Protocol (MCP) if that's how your stack discovers tools.

Why agents shouldn't parse documents directly

The instinct is to feed the invoice image straight into the agent's model and ask for the fields. It sometimes works. It also has the same failure modes as any raw-LLM extraction: inconsistent output shapes, occasional hallucinated values, and degradation on scans and photos. When that unreliable output then feeds downstream agent steps — "file this expense," "pay this vendor" — a single wrong number compounds through the whole workflow.

The cleaner architecture is the one good engineers already use for everything else an agent touches: give it a tool with a narrow contract. The agent decides when to read an invoice; the tool guarantees what the result looks like. The agent gets back the same normalized JSON every time and can reason about it confidently, because the extraction happened somewhere deterministic.

The tool contract

Whatever framework you're in, the tool you're exposing is simple: it takes a document and returns normalized fields.

text · 7 lines
Name:        extract_document
Description: Extract structured financial data from a receipt or invoice
             (PDF, JPG, or PNG). Returns merchant, totals, tax, dates,
             and line items as normalized JSON.
Input:       file (a receipt or invoice document)
Output:      { merchant, date, total, subtotal, tax, currency,
               invoice_id, line_items[] }

Under the hood, the tool is a single API call. Here it is as an OpenAI-style function the model can call:

python · 32 lines
import os, requests

def extract_document(file_path: str) -> dict:
    """Tool implementation: extract structured data from an invoice or receipt."""
    with open(file_path, "rb") as f:
        r = requests.post(
            "https://docuparseapi.com/api/v1/extract",
            headers={"Authorization": f"Bearer {os.environ['DOCUPARSE_API_KEY']}"},
            files={"file": (os.path.basename(file_path), f)},
        )
    r.raise_for_status()
    data = r.json()
    if not data.get("success"):
        return {"error": data.get("error", {}).get("code", "EXTRACTION_FAILED")}
    return data

# Tool schema the model sees
tools = [{
    "type": "function",
    "function": {
        "name": "extract_document",
        "description": "Extract structured financial data from a receipt or invoice "
                       "(PDF/JPG/PNG). Returns merchant, totals, tax, dates, line items.",
        "parameters": {
            "type": "object",
            "properties": {
                "file_path": {"type": "string", "description": "Path to the document file"}
            },
            "required": ["file_path"]
        }
    }
}]

Now the agent's job changes from "read this blurry receipt and hope" to "call extract_document, then reason about clean data." The extraction is boring, deterministic, and out of the model's hands — which is exactly what you want for the part that has to be correct.

Wiring it in as an MCP tool

If your agents discover tools through the Model Context Protocol — which by 2026 is how most of them do it — you can expose the same extraction as an MCP tool so any MCP-capable client (a coding assistant, a chat agent, an internal orchestrator) can use it without bespoke glue.

With a Python MCP server, the tool is a decorated function:

python · 22 lines
# server.py — minimal MCP server exposing document extraction
import os, requests
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("document-extraction")

@mcp.tool()
def extract_document(file_path: str) -> dict:
    """Extract merchant, totals, tax, dates, and line items from a receipt or invoice."""
    with open(file_path, "rb") as f:
        r = requests.post(
            "https://docuparseapi.com/api/v1/extract",
            headers={"Authorization": f"Bearer {os.environ['DOCUPARSE_API_KEY']}"},
            files={"file": (os.path.basename(file_path), f)},
        )
    data = r.json()
    if not data.get("success"):
        return {"error": data.get("error", {}).get("code", "EXTRACTION_FAILED")}
    return data

if __name__ == "__main__":
    mcp.run()

That's the whole adapter. Once it's registered with your agent host, the model can call extract_document the same way it calls any other tool — and the contract guarantees it gets back normalized JSON rather than whatever it would have hallucinated from the raw image.

The design principle worth keeping: the agent orchestrates, the tool guarantees. Reasoning stays with the model; correctness stays with the deterministic layer. Documents belong firmly in the second category.

A realistic agent workflow

Put together, a "process my expense inbox" agent looks like this:

  1. Agent is pointed at an inbox or folder of receipts.
  2. For each document, it calls extract_document — gets back normalized fields.
  3. It reasons over clean data: categorize the expense, flag anything over a threshold, check for duplicates.
  4. It calls the next tool — write to a sheet, create an expense record, post to your accounting system.

Every step after extraction is operating on trustworthy structured data, so the agent's reasoning is actually reliable. Compare that to feeding raw images through the model at step 2 and hoping the totals survive to step 4.

Getting started

You need two things: an API key and the tool definition above.

  • Grab a key on the free tier — 20 documents/month, no credit card, enough to build and test the whole agent loop.
  • See the exact response schema your tool will return in the docs, or drop a real document into the live demo first to see the shape.
  • If your agent is going to write extracted data somewhere, the expense-tracking build guide shows the store-to-database half of the workflow.

The agent is the interesting part. Let it stay interesting — hand the document reading to a tool that just works.


DocuParseAPI is a receipt and invoice parsing API. One POST request returns normalized JSON, which makes it a clean tool to expose to any AI agent — via function calling or MCP. Start free — 20 documents/month, no credit card.

Ready to start parsing documents?

More from the blog