Skip to content

Connect an AI assistant (MCP)

MoneyLights has a built-in MCP server, so an AI assistant — Claude Desktop, Claude Code, an IDE agent, anything that speaks the protocol — can work with your organization’s data on request.

It is the same credential as the REST API: an MCP connection is an API key, with the same scopes, the same limits and the same revoke button. There is nothing separate to manage.

The endpoint is https://api.moneylights.app/mcp (Streamable HTTP). A typical client configuration:

{
"mcpServers": {
"moneylights": {
"url": "https://api.moneylights.app/mcp",
"headers": { "X-API-Key": "ml_sk_..." }
}
}
}

With Claude Code it is one command:

Terminal window
claude mcp add --transport http moneylights https://api.moneylights.app/mcp \
--header "X-API-Key: ml_sk_..."

Create the key in Settings → API keys and grant it only the scopes the assistant needs. Everything requires the key, including listing the tools.

The tool list is computed from your key’s scopes, on every request. A key without a scope is never even told the corresponding tool exists.

ToolScopeWhat it does
get_cashflow_overviewcashflow:readMonthly income/expense/net, opening balance, top categories
get_analytics_overviewanalytics:readAggregates by category, client, project and person
list_transactionstransactions:readTransactions, filtered and paged, each with the documents linked to it
list_documentsdocuments:readDocuments and their extracted fields, each with the movements linked to it
get_document_filedocuments:readThe original file of one document — the PDF or image the app shows
get_pending_distributionprofitpulse:readPending Safe-to-Spend distributions
list_vendorsvendors:readVendors, with total spend
list_clientsclients:readClients, with total revenue
list_projectsprojects:readProjects, with totals and targets
upload_documentdocuments:writeFiles an invoice or receipt into your documents

Both overviews compute on the same base and say so: every response carries a basis — period, currencies, the accounts covered (every visible one, unless asked for by id), and how transfers between the organization’s own accounts were treated. By default they are excluded from income and expenses, leg by leg, exactly as the app’s Cashflow view shows them; pass includeInternalTransfers: true to either tool for the raw bank movement, which the basis then labels as such and which is not comparable with the default. Compare figures across the two tools only when their basis matches. netCashResult is income minus expenses of bank movements — a cash result, not accounting profit.

Both lists say it, from both sides, the way the app shows it. Every transaction carries linkedDocuments and every document carries linkedTransactions; each entry names the other side and a link:

  • confirmed — the document is matched to the movement, which counts as documented.
  • suggested — the matcher proposes the pairing; nobody has confirmed it and the movement is still missing its document. The entry carries the matcher’s score.

An assistant can therefore tell no invoice from an invoice waiting to be confirmed from already filed — and cannot change any of it, because this connection has no tool for that.

A movement may carry several confirmed documents. A document links to at most one movement, so an invoice paid in several parts shows only the movement it was matched to. A document still Processing has no links yet; None means none.

Scopes still hold: the far side of a link is described (supplier and number, or description and amount) only to a key that can read that resource too. With one scope you get the other side’s id, the kind of link and the score — enough to know a movement is documented, not what the invoice says.

get_document_file takes a documentId from list_documents and returns the stored file itself — the same PDF or image the app opens — as an embedded resource with its MIME type (application/pdf, image/jpeg, …), next to the document’s id, file name and size — files up to 10MB, the same ceiling as an upload. That is how an assistant checks whether a difference comes from the invoice, from what was extracted or from the movement it was matched to, without exporting anything. It is a read: nothing on the document, its extracted fields or its links changes. A document that is not yours is simply not found.

upload_document is the one tool that writes, and it was chosen for that role deliberately: it only ever adds. The assistant sends the file (PDF or image, up to 10MB) and MoneyLights runs it through the same pipeline as an upload in the app — stored, its fields extracted (supplier, date, number, amounts) and auto-matched against your bank transactions.

Sending the same file twice never duplicates your data: the re-upload is recorded as a flagged duplicate pointing at the original. Everything the assistant files is visible — and deletable — in the app.

Every other write (creating clients, reclassifying transactions, configuring envelopes…) stays in the app on purpose: those actions assume a human confirming them.

The server also offers ready-made starting points — a monthly cashflow review, a vendor spend analysis, a missing-documents cleanup — listed only when your key can run every tool they need. Use them as-is or edit freely.

  • The assistant is bounded by the key, re-checked on every request. Demote or remove the key’s creator and the assistant narrows or stops on the next call.
  • Financial data contains text written by strangers — payment references, emailed documents. Tool results are delivered inside a marked boundary telling the model to treat them as data, never as instructions. Treat that as a mitigation, not a guarantee, and scope keys tightly.
  • To disconnect an assistant, revoke its key in Settings → API keys. Immediate, always available.

Give each assistant its own key — one per client means you can cut one without disturbing the rest.