Skip to main content
Glama
mittalmayank842

mcp-business-docs

README.md
# mcp-business-docs

An MCP server that gives Claude Desktop — or any MCP client — read access to an
invoice ledger, plus OCR over local documents.

Most published MCP servers expose **tools** and stop there. This one implements all
three primitives, because they do different jobs:

| Primitive | Who decides to use it | What it's for |
| --- | --- | --- |
| **Tools** | the model | Actions it chooses mid-conversation |
| **Resources** | the client/user | Addressable content attached as context |
| **Prompts** | the user | Reusable workflows from a menu |

## What's exposed

**Tools** — `search_invoices`, `get_invoice`, `vat_summary`, `ocr_document`

**Resources** — `invoice://list` (browsable table), `invoice://{invoice_id}` (one
invoice as markdown, addressable by id)

**Prompts** — `chase_overdue(days)`, `reconcile(invoice_id)`

## Install into Claude Desktop

```bash
pip install -r requirements.txt
```

Then add to `claude_desktop_config.json` — macOS:
`~/Library/Application Support/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "business-docs": {
      "command": "python",
      "args": ["-m", "mcp_business_docs.server"],
      "env": { "PYTHONPATH": "/absolute/path/to/mcp-business-docs/src" }
    }
  }
}
```

Restart Claude Desktop. The tools appear under the connectors icon; `invoice://list`
appears as an attachable resource.

For Claude Code:

```bash
claude mcp add business-docs -- python -m mcp_business_docs.server
```

> **Add a demo GIF here.** Record Claude Desktop actually calling `search_invoices`
> and attaching `invoice://list`. It's the single most convincing thing this README
> can contain, and it takes two minutes with any screen recorder.

## Tool descriptions are prompt engineering

The model never sees your implementation — only the name, the docstring, and the
parameter schema. That makes the docstring the highest-leverage code in the repo.
Two habits that measurably help:

**State the boundary, not just the capability.** `search_invoices` says it covers
issued invoices only and excludes drafts and credit notes. Most tool-selection
errors come from the model not knowing where a tool stops.

**Return errors the model can act on.** `get_invoice("INV-0000")` returns the
known ids rather than raising. A thrown exception ends the turn; a structured error
lets the model correct itself on the next one.

## Try it

```bash
pip install -r requirements.txt
python -m mcp_business_docs.server     # stdio; Ctrl-C to stop
pytest tests/ -q
```

The store is seeded with four fabricated invoices. Swap `store.py` for a real
database and nothing in `server.py` changes — which is the argument for keeping the
protocol layer thin.

## Security note

`ocr_document` reads a local path and returns its text. That text is untrusted:
a scanned document can contain instruction-shaped strings aimed at whatever model
reads it. The tool labels its output as data, but a client that concatenates tool
results into a prompt without delimiting them is still exposed. Treat OCR output as
hostile input, not as context.

## Layout

```
src/mcp_business_docs/
  server.py   Tools, resources, and prompts
  store.py    SQLite-backed sample data
tests/        Logic tests that don't need a live client
```

## License

MIT