Build a Small-Business Invoice Agent with LangChain Deep Agents and MCP A developer published a walkthrough for building a multi-agent invoice-triage system using LangChain's Deep Agents framework and the Model Context Protocol (MCP). The architecture pairs an orchestrator that plans and maintains a todo list with extractor and reviewer subagents, all accessing vendor lookups, invoice history, duplicate checks and file reading through a FastMCP server backed by SQLite, with path-traversal protection on file reads. The author notes the design is an extensible reference rather than a production system and advises pinning versions of deepagents, langchain-mcp-adapters and mcp. Most "AI agent" tutorials stop at a chatbot that calls a weather API. Real small-business work looks different: a stack of PDFs in an inbox, a spreadsheet of vendors, and a person who has to decide what gets paid. In this post we'll build a small but realistic multi-agent system that triages incoming invoices, using two pieces that fit together well: The goal isn't a production system in 1,200 words. It's a clean architecture you can extend. Library APIs move fast, so pin your versions and check the docs for deepagents , langchain-mcp-adapters and mcp before you copy this into anything serious. A small company receives vendor invoices by email. For each one, someone has to: None of this needs a model to "be creative". It needs reliable extraction, a few lookups, and a clear audit trail. That's a good fit for agents with narrow tools. ┌──────────────────────────┐ │ Orchestrator Deep │ │ Agent: plans + todo │ └─────┬───────────┬────────┘ │ │ ┌─────────▼──┐ ┌────▼─────────┐ │ extractor │ │ reviewer │ │ subagent │ │ subagent │ └─────┬──────┘ └────┬─────────┘ │ MCP tools │ ┌─────▼───────────────▼────────┐ │ MCP server: vendors, invoice │ │ history, file reader │ └──────────────────────────────┘ The orchestrator never touches the database directly. Everything goes through MCP tools, which means the same server can later serve a different agent framework, a desktop assistant, or an internal app. Install the dependencies: pip install "mcp cli " langchain-mcp-adapters deepagents langchain-openai Here's a minimal MCP server using FastMCP . For the demo, the "database" is SQLite. python invoice server.py import sqlite3 from pathlib import Path from mcp.server.fastmcp import FastMCP mcp = FastMCP "invoices" DB = Path "business.db" def q sql: str, params: tuple = : with sqlite3.connect DB as conn: conn.row factory = sqlite3.Row return dict r for r in conn.execute sql, params .fetchall @mcp.tool def read invoice text filename: str - str: """Return the extracted text of an invoice file in the inbox folder.""" path = Path "inbox" / Path filename .name prevent path traversal return path.read text @mcp.tool def lookup vendor name: str - list dict : """Find known vendors whose name matches case-insensitive .""" return q "SELECT id, name, payment terms FROM vendors WHERE name LIKE ?", f"%{name}%", @mcp.tool def invoice history vendor id: int - list dict : """Past invoices for a vendor: number, date, total.""" return q "SELECT number, date, total FROM invoices WHERE vendor id = ? " "ORDER BY date DESC LIMIT 24", vendor id, @mcp.tool def is duplicate vendor id: int, invoice number: str - bool: """True if this vendor already has an invoice with this number.""" return bool q "SELECT 1 FROM invoices WHERE vendor id = ? AND number = ?", vendor id, invoice number if name == " main ": mcp.run transport="stdio" A few deliberate choices: Path filename .name stops the model or a malicious PDF from reading files outside the inbox. You can poke at it with the MCP inspector: mcp dev invoice server.py . langchain-mcp-adapters turns MCP tools into regular LangChain tools: python from langchain mcp adapters.client import MultiServerMCPClient client = MultiServerMCPClient { "invoices": { "command": "python", "args": "invoice server.py" , "transport": "stdio", } } tools = await client.get tools inside an async function by name = {t.name: t for t in tools} Splitting by name matters. Each subagent should only see the tools it needs. Deep Agents gives you a planning tool a todo list , a virtual file system for scratch notes, and the ability to spawn subagents with their own prompt and toolset. Subagents keep the orchestrator's context clean: the extractor can wade through a messy invoice without dumping all of that text into the main conversation. extractor = { "name": "extractor", "description": "Reads one invoice file and returns structured JSON.", "system prompt": "You extract invoice data. Call read invoice text, then return ONLY JSON " "with keys: vendor name, invoice number, date YYYY-MM-DD , " "line items list of {description, amount} , total. " "If a field is missing, use null. Never guess numbers." , "tools": by name "read invoice text" , } reviewer = { "name": "reviewer", "description": "Checks extracted invoice JSON against vendor records.", "system prompt": "You review invoices. Given extracted JSON: look up the vendor, check for " "duplicates, and compare the total to that vendor's history. Report " "flags: UNKNOWN VENDOR, DUPLICATE, TOTAL MISMATCH line items don't sum , " "UNUSUAL AMOUNT well above typical . Explain each flag in one sentence." , "tools": by name "lookup vendor" , by name "invoice history" , by name "is duplicate" , } Note what's not delegated to the model: the definition of each flag. You decide the business rules. The model applies them and explains its reasoning. python import asyncio from deepagents import create deep agent ORCHESTRATOR PROMPT = """You triage vendor invoices for a small business. For each file you are given: 1. Plan the work with your todo list. 2. Delegate extraction to the extractor subagent. 3. Pass its JSON to the reviewer subagent. 4. Write a summary per invoice: vendor, number, total, flags, and a recommendation of APPROVE or NEEDS HUMAN REVIEW. You never approve payments yourself.""" async def main files: list str : agent = create deep agent model="openai:gpt-4.1", any tool-calling model works tools= , orchestrator delegates everything system prompt=ORCHESTRATOR PROMPT, subagents= extractor, reviewer , result = await agent.ainvoke { "messages": {"role": "user", "content": f"Triage these invoices: {', '.join files }"} } print result "messages" -1 .content asyncio.run main "acme-1043.txt", "newco-0007.txt" In real code, create the MCP client and subagent dicts inside main so await client.get tools runs in the same event loop. The demo works. Here's what turns it into something a business can actually rely on: Validate structured output. Don't trust the extractor's JSON. Parse it with Pydantic and send it back for a retry on failure: python from pydantic import BaseModel, model validator class LineItem BaseModel : description: str amount: float class Invoice BaseModel : vendor name: str invoice number: str date: str line items: list LineItem total: float @model validator mode="after" def totals match self : if abs sum i.amount for i in self.line items - self.total 0.01: raise ValueError "line items do not sum to total" return self Arithmetic checks belong in code, not in a prompt. Keep a human in the loop. The agent recommends, a person approves. Deep Agents supports interrupting before sensitive tool calls if you later add write tools like mark approved . Log everything. Store every tool call and result. When the owner asks "why was this flagged?", you can show them. Evaluate with real samples. Gather 20–30 anonymized past invoices with known correct answers, and re-run them every time you change a prompt or model. That's your regression suite. Treat documents as untrusted input. An invoice can contain text like "ignore previous instructions". Read-only tools and narrow subagent permissions limit what a prompt injection can do. Swap "invoices" for insurance claims intake, real estate transaction documents, or permit applications, and the shape is the same: an MCP server wrapping your systems, an extractor, a reviewer that applies your rules, and an orchestrator that writes a decision-ready summary. That's the core of most intelligent document processing https://www.businessedgeanalytics.com/services/intelligent-document-processing.html work. The hard parts are the business rules and the evaluation set, not the framework. If you're deciding whether to build something like this or buy a SaaS tool, I wrote a longer comparison of custom AI vs. off-the-shelf solutions https://www.businessedgeanalytics.com/blog/custom-ai-vs-off-the-shelf.html . For more workflow ideas beyond invoices, see 5 AI workflow automations every business needs https://www.businessedgeanalytics.com/blog/ai-workflow-automations.html . Jimmy Hernandez is a senior AI engineer and founder of Business Edge Analytics https://www.businessedgeanalytics.com , a Louisville, KY firm that builds multi-agent systems, RAG assistants and document automation for businesses and public-sector teams. He works with LangChain Deep Agents, MCP and Python, and has a background in insurance and real estate.