{
  "markdown": "# mcp-statement-of-account\n\n<!-- mirror-seo:start -->\n\n**MCP server for customer statements of account, accounts receivable and invoice aging.** The one document that answers what a client actually owes you, aged as at any date, with the chaser drafted.\n\nWorks with Claude Desktop, Claude Code, Cursor and any Model Context Protocol client. Runs on your own machine, or hosted with no install.\n\n## Install\n\n**Hosted, nothing to install.** Get a token from <https://mcp.zovo.one/mcp/connect> (the connect page) or <https://mcp.zovo.one/mcp/token> (the same token as JSON); a free anonymous one is issued on the spot and a Pro key works the same way. Then point an MCP client at `https://mcp.zovo.one/mcp/statement-of-account` over streamable-http and send the token as `Authorization: Bearer <token>`.\n\nIf your client cannot set headers, put the token in the path instead: `https://mcp.zovo.one/mcp/statement-of-account/t/<token>`. Both forms work. The bare URL with no token answers 401 on `tools/call`, so the token is not optional.\n\n**Claude Desktop, one click.** Download `statement-of-account.mcpb` from the [latest release](https://github.com/theluckystrike/mcp-servers/releases/latest) and double-click it.\n\n**From source.** The mirror is self-contained: every `@theluckystrike/*` dependency is vendored, so a fresh clone builds with no extra setup.\n\n```sh\ngit clone https://github.com/theluckystrike/mcp-statement-of-account.git\ncd mcp-statement-of-account\nnpm install && npm run build\n```\n\nThen point your client at the built entry point:\n\n```json\n{\n  \"mcpServers\": {\n    \"statement-of-account\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/mcp-statement-of-account/dist/index.js\"]\n    }\n  }\n}\n```\n\n> `@theluckystrike/mcp-statement-of-account` is **not published on npm yet**, so an `npx -y @theluckystrike/mcp-statement-of-account` command will fail. The three paths above are the working ones and each is exercised by CI.\n\n![statement-of-account demo](https://raw.githubusercontent.com/theluckystrike/mcp-servers/main/assets/demo-statement-of-account.gif)\n\nRead-only mirror of [mcp-servers/servers/statement-of-account](https://github.com/theluckystrike/mcp-servers/tree/main/servers/statement-of-account). See [MIRROR.md](MIRROR.md).\n\n<!-- mirror-seo:end -->\n\nSend a client the one document that answers \"what do I actually owe you\". This MCP server\nreads the books you already keep in this suite -- your invoices, your credit notes and your\ndeposits -- and turns them into a statement of account for a period: the balance you were\ncarrying at the start, every invoice you issued, every payment that came in, every credit\nnote you gave, and the balance at the end. It ages what is still open into 0-30, 31-60,\n61-90 and over 90 days past due, so you can see at a glance which client is the problem;\nit writes the statement as pasteable text or as an A4 PDF that looks like your invoices;\nand it drafts the chaser, at a friendly, a firm or a final level. It never writes anything\nback into your invoices, and it never invents a late fee.\n\nBuilt by [theluckystrike](https://github.com/theluckystrike).\n\nnpm publish for `@theluckystrike/mcp-statement-of-account` is pending, so `npx -y @theluckystrike/mcp-statement-of-account` returns 404 today. Until then, the `.mcpb` one-click bundle or a clone+build is the working path.\n\n## Install\n\n### Claude Desktop\n\n`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or\n`%APPDATA%\\Claude\\claude_desktop_config.json` (Windows):\n\n```json\n{\n  \"mcpServers\": {\n    \"statement-of-account\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@theluckystrike/mcp-statement-of-account\"]\n    }\n  }\n}\n```\n\n### Claude Code\n\n```sh\nclaude mcp add statement-of-account -- npx -y @theluckystrike/mcp-statement-of-account\n```\n\n### Cursor\n\n`~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project), same entry as Claude Desktop.\n\n## Tools\n\n| tool | what it does |\n| --- | --- |\n| `statement_build` | One client's statement for a period: opening balance, invoices issued, payments received, credit notes, deposits applied, closing balance. Every figure in minor units and formatted |\n| `statement_aging` | What is owed, split into 0-30, 31-60, 61-90 and over 90 days past the due date as at a chosen date, for one client or for everyone, per currency |\n| `statement_text` | The same statement as plain text, movements in date order, ready to paste into an email |\n| `statement_pdf` | The same statement as an A4 PDF titled STATEMENT OF ACCOUNT, on the same page layout as your invoices and credit notes |\n| `dunning_text` | A payment chaser at level 1 (friendly), 2 (firm) or 3 (final demand), with the overdue list and your bank details |\n| `statements_report` | Every client at once: what is outstanding per currency, aged, and the oldest overdue invoice in the book |\n| `license_status` | Free or Pro, and where to upgrade |\n| `license_activate` | Activate a Pro key |\n\nPlus the `statement://sources` resource, which says which of the three stores this server\ncould read and how many rows each holds, and the `chase_overdue` prompt.\n\n## Free vs Pro\n\n| | Free | Pro |\n| --- | --- | --- |\n| Statements built | 5 a calendar month | unlimited |\n| Rebuilding a statement already built | unlimited | unlimited |\n| `statement_aging` | unlimited | unlimited |\n| `statement_text` | yes | yes |\n| `dunning_text` levels 1 and 2 | yes | yes |\n| `dunning_text` level 3, final demand | no | yes |\n| `statement_pdf` | no | yes |\n| `statements_report` | no | yes |\n| PDF footer credit | shown | removed |\n\nAging is free and unlimited on purpose. \"Who owes me money\" is the question this whole\nserver exists for, and a free tier that hides it is a demo rather than a tool. The meter is\non the statement, the document that actually goes to a client, and it counts distinct\nstatements: the same client, period and currency built again is free forever.\n\n[Get Pro](https://mcp.zovo.one/buy/statement-of-account) -- one-time, lifetime, for this\nserver. Keys verify offline.\n\n## Where the numbers come from\n\nNothing here is typed in twice. The server reads three stores and writes to none of them:\n\n| store | server | what is taken from it |\n| --- | --- | --- |\n| `invoices.json` | `mcp-invoice` | the invoices, their due dates and how much of each is paid |\n| `credit-notes.json` | `mcp-billing-docs` | the credit notes, already stored with a negative sign |\n| `deposits.json` | `mcp-deposits` | the deposit applications, and what is still held |\n\nA store you have never installed is simply absent, and the statement is built without it.\nA store that is on disk and cannot be READ is a different thing entirely, and is reported\nas such on every figure, because a balance that could not be computed must never be shown\nas a balance of nothing owed. The one store the server refuses to work without is the\ninvoice ledger.\n\n## A measured insight\n\n**Aging a past date with today's payment figures is not slightly wrong, it is silently\nempty.** Aging is usually written as \"take each invoice, subtract what has been paid, and\nbucket by the due date\". The subtraction is the part nobody dates. On the worked month in\n`test/_client.mjs`, aged at 2026-06-10, the two rules give:\n\n| rule | outstanding | overdue |\n| --- | --- | --- |\n| as at 2026-06-10 | 2,500.00 EUR | 500.00 EUR, 31 days late |\n| today's `paid_minor` | 1,700.00 EUR | 0.00 EUR |\n\nThe naive rule understates what was owed by 800.00 of 2,500.00, a third of the balance,\nand it reports NOTHING overdue on a date when an invoice was a month late, because a\npayment that arrived two days later has already been subtracted from it. The failure is\ninvisible: the answer looks tidy, the buckets add up, and it cannot be reproduced next\nmonth because the input keeps moving. So every figure in `statement_aging` is taken as at\nthe date asked for, in both directions: an invoice issued after it is not on the books, a\npayment made after it has not happened, and a credit note issued after it has not been\ngiven.\n\nThe second thing measurement showed: `paid_minor` and `payments[]` on an invoice do not\nhave to agree, and routinely do not. `invoice_mark_paid` writes both, but `deposit_apply`\nraises `paid_minor` and appends no payment row at all, and an invoice created before that\nfield existed has no rows either. Reconstructing receipts from `payments[]` would have\nlost 300.00 of the worked month's 900.00 of receipts, a third of the cash, with no error\nanywhere. `paid_minor` is treated as the authority and the rows are only the attribution.\n\n## Rules this server holds to\n\n- **A deposit is money that moves once.** Applying a deposit already writes the payment on\n  the invoice, so the statement counts it there and breaks it out as \"of which deposits\n  applied\" rather than crediting it a second time. Deposit money still held is a memo line\n  and is never part of the balance: it is the client's money until it is applied.\n- **Currencies are never added together.** One statement is one currency, and a client\n  billed in two is asked which. There is no exchange rate in this server, so a single\n  figure across a EUR ledger and a USD one would be one it made up.\n- **Due today is not overdue.** An invoice enters the 0-30 bucket on the first day past its\n  due date. What is outstanding but not yet due is reported beside the buckets, never\n  inside them and never hidden.\n- **A credit note reduces the invoice it names and no other.** An open balance floors at\n  zero and any excess is reported as unapplied credit, rather than quietly cancelling an\n  invoice the client never agreed it against.\n- **No chaser invents a charge.** The three dunning levels differ in tone and deadline and\n  in nothing else. No level states a late fee, an interest rate or a legal cost, because\n  this server holds no contract terms, no statutory rate and no jurisdiction, and the one\n  place never to put a made-up number is a demand for money.\n- **A chaser for a client with nothing overdue is refused**, and the refusal says what is\n  outstanding but not yet due.\n\n## Privacy\n\nAll data stays on your machine. The invoices, credit notes and deposits are read from\n`${XDG_DATA_HOME:-~/.local/share}/mcp-servers/`, this server's own register of built\nstatements is written to `.../mcp-servers/statement-of-account/`, and nothing is sent\nanywhere. There is no network call in this server at all. License keys verify offline.\n\n## License\n\nMIT. Support: support@zovo.one\n\nBuilt by [theluckystrike](https://github.com/theluckystrike).\n",
  "bytes": 10525,
  "sha": "fb1553713fe0b7487894a53238d9971d4f7383856cd19e8c68b58431f1f27363",
  "repo_slug": "theluckystrike/mcp-statement-of-account",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_theluckystrike_mcp_statement_of_account_ab573d54/readme"
}