Letting AI assistants work in the mailbox and the ledger, safely

We wanted AI assistants that could triage mail and post to the accounts. A general API in an agent's hands can send, delete or post the wrong number, so we built MCP servers where the dangerous verbs simply don't exist.

Locality
UK
Disciplines
AI with guardrails, Systems integration, Identity and security
Stack
  • Python
  • Model Context Protocol
  • Microsoft Graph
  • QuickBooks Online API
  • MSAL
  • Docker

At a glance

  • 12

    mailbox tools, none of which can send

  • 26

    accounting tools behind a dry-run gate

  • 6

    instances in production

  • 61

    tests on the mailbox server alone

The challenge

AI assistants are genuinely useful on a busy mailbox and a backlog of bookkeeping. They're also very confident, and a general-purpose mail or accounting API gives them the same power as the account owner: send anything, delete anything, post anything.

We wanted an assistant that could do the useful work on live mailboxes and live books, and was physically unable to do the dangerous things, rather than politely asked not to.

Architecture

Governed AI connectors architectureArchitecture diagram with 9 components. AI assistant to Mailbox tools. AI assistant to Accounting tools. Mailbox tools to Mailbox fence. Mailbox fence to Microsoft Graph (cert auth). Accounting tools to Company fence. Company fence to QuickBooks Online. QuickBooks Online to Read-back gate. Read-back gate to Audit log.Mailbox serverAccounting servercert authAI assistantMCP clientMailbox toolsDraft-onlyMailbox fenceOne mailbox per instanceMicrosoft GraphExchange RBAC scopeAccounting toolsDry run by defaultCompany fenceConfig + idempotencyQuickBooks OnlineRead-back gateTies to the penny or rolls backAudit logAppend-only

Swipe to explore the diagram

Every call passes a fence before it reaches the real system. The mailbox server has no send path, and every accounting write is verified by reading it back.

What we built

Mailbox server

  • 12 tools for listing, reading, moving and filing mail, plus attachments and drafts
  • One mailbox per instance, with no mailbox parameter for a model to change
  • Outbound is draft-only. There's no send code path, so a person reviews everything before it leaves
  • Delete moves to Deleted Items and nothing is ever hard deleted
  • Attachment bytes never pass through the model's context: they're staged on the server, fetched by URL and expire after 10 minutes

Accounting server

  • 26 typed tools over the QuickBooks Online API, mostly reads and reports, with a deliberately small set of writes
  • Every write is a dry run until explicitly committed, and idempotent
  • A read-back gate checks each posting ties to the penny and rolls it back if it doesn't
  • One codebase for VAT-registered and non-VAT companies, switched by config that fails closed at boot

Delivery

  • A base repo for the code and runbook, and a config-only deploy repo per instance that pins a tag, so an upgrade is a pull request
  • Unit tests with Graph and MSAL faked, dependency and image scanning in CI, and hash-pinned dependencies

Engineering decisions

The tool surface is the security boundary

We don't ask a model nicely not to send mail. The capability isn't there to call, and mailbox-scoped RBAC backs that up a layer further down.

Money never moves automatically

Bill payments, card payments and tax payments are intentionally absent from the accounting server. It can record what happened. It can't pay anyone.

Gross is sovereign

The caller declares the document total and the server derives net and VAT, refusing any line that doesn't reconcile. A wrong VAT figure fails loudly instead of landing in the books.

Fence the company

Before every write the server compares the live company identity with the one it was configured for. If they differ, or either is missing, the fence closes completely.

Fail visibly

Identity calls carry connect and read timeouts, and auth failures surface the real error code. A hang that looks like a slow tool is far worse than an honest error.

Outcome

Assistants now triage, extract documents and draft replies on live mailboxes, and post daily takings, supplier bills and month-end journals into four companies' books, gated and reconciled. Bringing another company on board took a read-only harvest and a config file.