idin9-doc-ocr-mcp
# idin9-doc-ocr-mcp
Standalone **Model Context Protocol (MCP)** server for document OCR and **Thai tax invoice**
processing, with automated scanner ingestion (SMB/Shared Folder) and SQLite storage.
The server extracts tax invoices from PDFs and scanned images, parses the 13 core Thai
tax-invoice fields, applies three-tier routing (success / need-train / failed), and stores
results in SQLite. It can also poll an SMB scanner share or watch a local drop folder.
## Features
- **Digital + scanned documents** — PyMuPDF for embedded text, Tesseract (`tha+eng`) with
image pre-processing (grayscale, de-noise, adaptive threshold, de-skew) for scans.
- **Thai tax invoice parsing** — supplier/buyer, 13-digit tax IDs, line items, summary,
currency, and capture-rate scoring.
- **Three-tier routing**
- `success` — 100% capture + valid totals + buyer verification → `processed/YYYY-MM/`
- `need_train` — 80–99% capture → `Need-Train/`
- `failed` — < 80% capture or non-tax document → `failed/`
- **Automated ingestion** — SMBv2/v3 scanner share polling and watchdog folder watching.
- **SQLite storage** — WAL mode, tax invoices + canonical contacts tables, full CRUD.
- **MCP tools** — exposed via FastMCP for Hermes / Claude Desktop / any MCP client.
## Requirements
- Python 3.11+
- Tesseract OCR with Thai + English language packs (`tesseract-ocr-tha`, `tesseract-ocr-eng`)
- Access to a scanner SMB share (optional)
### Debian / Ubuntu Tesseract install
```bash
sudo apt-get update
sudo apt-get install -y tesseract-ocr tesseract-ocr-tha tesseract-ocr-eng
```
## Installation
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then edit values
```
## Configuration
Copy `.env.example` to `.env` and adjust:
| Variable | Description |
| --- | --- |
| `SCAN_DROP_DIR` | Local/mounted scanner drop folder |
| `SMB_HOST`, `SMB_SHARE`, `SMB_USER`, `SMB_PASSWORD`, `SMB_DOMAIN` | SMB scanner share (leave blank to disable) |
| `DB_PATH` | SQLite database path |
| `TESSERACT_CMD`, `OCR_LANGUAGES`, `OCR_DPI` | OCR engine settings |
| `MIN_EMBEDDED_TEXT_CHARS` | Threshold to decide digital vs scanned extraction |
## Running
```bash
python -m src.mcp_server
```
Or with Docker:
```bash
docker compose up --build
```
## MCP Client Configuration
### Hermes
```json
{
"mcpServers": {
"idin9-doc-ocr-mcp": {
"command": "python",
"args": ["-m", "src.mcp_server"],
"cwd": "/path/to/idin9-doc-ocr-mcp",
"env": {
"TESSERACT_CMD": "tesseract",
"OCR_LANGUAGES": "tha+eng"
}
}
}
}
```
### Claude Desktop
```json
{
"mcpServers": {
"idin9-doc-ocr-mcp": {
"command": "python",
"args": ["-m", "src.mcp_server"],
"cwd": "/path/to/idin9-doc-ocr-mcp"
}
}
}
```
## Available Tools
| Tool | Purpose |
| --- | --- |
| `ocr_extract_invoice(file_path)` | Extract a single PDF/image invoice |
| `ocr_batch_process(folder_path?)` | Process all pending files in a folder |
| `ocr_poll_scanner_share()` | Pull & process new files from the SMB share |
| `ocr_get_record(invoice_id?, invoice_number?)` | Retrieve a stored record |
| `ocr_list_records(status?, limit=50)` | List records with filters |
| `ocr_manage_contact(action, tax_id, company_name?)` | CRUD on contacts |
| `ocr_review_queue(limit=50)` | List low-confidence (`need_train`) records awaiting human confirmation |
| `ocr_review_record(invoice_id, action, reviewer, notes?, corrected?)` | Confirm (→ success) or reject (→ failed) a review item |
| `ocr_system_health()` | DB/SMB/queue health report |
## Human Review Workflow (Multi-User)
Documents that score **80–99% capture** (or have valid totals but an unverified
buyer) are routed to `Need-Train/` and stored with status `need_train`. These are
held for human confirmation before they are trusted as final.
Two interfaces are provided, both backed by the same SQLite database:
### 1. MCP tools (for Claude Desktop / Hermes)
- `ocr_review_queue()` → returns pending items.
- `ocr_review_record(invoice_id, action="confirm"|"reject", reviewer, notes?, corrected?)`
- **confirm** → status becomes `success`, file moves to `processed/YYYY-MM/`,
reviewer identity and optional corrected fields are stored.
- **reject** → status becomes `failed`, file moves to `failed/`.
### 2. Web UI (for manual multi-user review)
Run the review web server:
```bash
python -m src.webui
# or: idin9-doc-ocr-webui
# optional port: WEBUI_PORT=8080 python -m src.webui
```
Open `http://localhost:8080`. The queue lists every pending invoice; opening one
shows an editable form (header, supplier, buyer, summary) plus the raw OCR text.
A reviewer enters their name, then **Confirms as correct** or **Rejects as bad**.
The reviewer name is remembered via a cookie and recorded on the record
(`reviewer`, `reviewed_at`, `review_notes`, `review_status`).
The `tax_invoices` table gains these review columns: `review_status`
(`pending`/`confirmed`/`rejected`), `reviewer`, `reviewed_at`, `review_notes`.
## Data Layout
```
data/
drop/ # scanner drop folder (watchdog)
staging/ # temporary download area (SMB)
processed/YYYY-MM/ # successful extractions
Need-Train/ # 80-99% capture, for review/training
failed/ # <80% capture or non-tax documents
idin9_doc_ocr.db # SQLite database
```
## Development & Tests
```bash
pip install -e ".[dev]"
pytest
```
## License
MIT
TDQS
Scored across 9 tools
Most tools have clearly distinct purposes: extraction, batch processing, scanner polling, record retrieval, review, contact management, and health checks. The only slight overlap is between ocr_batch_process and ocr_poll_scanner_share, since both process files from directory-like sources.
All tools share the ocr_ prefix and use snake_case, which creates a strong predictable pattern. However, ocr_batch_process and ocr_system_health deviate from the strict verb_noun structure used by most other tools.
Nine tools is well-scoped for an OCR invoice processing server covering ingestion, extraction, retrieval, review, contacts, and system health. Each tool serves a meaningful part of the workflow without redundancy or bloat.
The toolset covers the main OCR invoice lifecycle: extract, batch process, poll scanner, retrieve/list records, review low-confidence results, manage contacts, and check health. Minor gaps exist, such as no direct update/delete for processed invoice records outside the review flow or explicit reprocessing of failed items.