mcp-statement-of-account
This is an MCP server that turns your existing invoices, credit notes and deposits into customer statements of account, aging reports, dunning letters and PDFs, without writing back to your books.
Build a statement of account for one client over a period: opening balance, invoices issued, payments received, deposits applied, credit notes, and closing balance, in minor units and formatted.
Age open invoices into 0-30, 31-60, 61-90 and 90+ days past due as at any date, for one client or all clients, per currency, with the underlying invoices.
Generate a plain-text statement for pasting into an email, with movements in date order, balances, and optional greeting/sign-off.
Render an A4 PDF statement titled STATEMENT OF ACCOUNT, matching your invoice layout.
Write dunning letters at three levels (friendly, firm, final demand) listing overdue invoices, ages, totals and bank details; refuses if nothing is overdue.
Produce a whole-book receivables report (
statements_report) showing totals and aging per currency, clients ranked by overdue amount, and the oldest overdue invoice.Check and activate license status: report free/Pro tier, key source, expiry, and activate a Pro key offline.
Free tier limits apply: 5 statements a month, while aging is unlimited; PDFs, the receivables report and final-demand dunning are Pro features.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-statement-of-accountBuild a statement of account for Acme Corp for last month as a PDF."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-statement-of-account
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.
Works with Claude Desktop, Claude Code, Cursor and any Model Context Protocol client. Runs on your own machine, or hosted with no install.
Install
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>.
If 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.
Claude Desktop, one click. Download statement-of-account.mcpb from the latest release and double-click it.
From source. The mirror is self-contained: every @theluckystrike/* dependency is vendored, so a fresh clone builds with no extra setup.
git clone https://github.com/theluckystrike/mcp-statement-of-account.git
cd mcp-statement-of-account
npm install && npm run buildThen point your client at the built entry point:
{
"mcpServers": {
"statement-of-account": {
"command": "node",
"args": ["/absolute/path/to/mcp-statement-of-account/dist/index.js"]
}
}
}
@theluckystrike/mcp-statement-of-accountis not published on npm yet, so annpx -y @theluckystrike/mcp-statement-of-accountcommand will fail. The three paths above are the working ones and each is exercised by CI.

Read-only mirror of mcp-servers/servers/statement-of-account. See MIRROR.md.
In the official MCP Registry (io.github.theluckystrike/statement-of-account).
Send a client the one document that answers "what do I actually owe you". This MCP server
reads the books you already keep in this suite -- your invoices, your credit notes and your
deposits -- and turns them into a statement of account for a period: the balance you were
carrying at the start, every invoice you issued, every payment that came in, every credit
note you gave, and the balance at the end. It ages what is still open into 0-30, 31-60,
61-90 and over 90 days past due, so you can see at a glance which client is the problem;
it writes the statement as pasteable text or as an A4 PDF that looks like your invoices;
and it drafts the chaser, at a friendly, a firm or a final level. It never writes anything
back into your invoices, and it never invents a late fee.
Built by theluckystrike.
npm 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.
Related MCP server: mcp-business-docs
Install
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or
%APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"statement-of-account": {
"command": "npx",
"args": ["-y", "@theluckystrike/mcp-statement-of-account"]
}
}
}Claude Code
claude mcp add statement-of-account -- npx -y @theluckystrike/mcp-statement-of-accountCursor
~/.cursor/mcp.json (global) or .cursor/mcp.json (project), same entry as Claude Desktop.
Tools
tool | what it does |
| 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 |
| 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 |
| The same statement as plain text, movements in date order, ready to paste into an email |
| The same statement as an A4 PDF titled STATEMENT OF ACCOUNT, on the same page layout as your invoices and credit notes |
| A payment chaser at level 1 (friendly), 2 (firm) or 3 (final demand), with the overdue list and your bank details |
| Every client at once: what is outstanding per currency, aged, and the oldest overdue invoice in the book |
| Free or Pro, and where to upgrade |
| Activate a Pro key |
Plus the statement://sources resource, which says which of the three stores this server
could read and how many rows each holds, and the chase_overdue prompt.
Free vs Pro
Free | Pro | |
Statements built | 5 a calendar month | unlimited |
Rebuilding a statement already built | unlimited | unlimited |
| unlimited | unlimited |
| yes | yes |
| yes | yes |
| no | yes |
| no | yes |
| no | yes |
PDF footer credit | shown | removed |
Aging is free and unlimited on purpose. "Who owes me money" is the question this whole server exists for, and a free tier that hides it is a demo rather than a tool. The meter is on the statement, the document that actually goes to a client, and it counts distinct statements: the same client, period and currency built again is free forever.
Get Pro -- one-time, lifetime, for this server. Keys verify offline.
Where the numbers come from
Nothing here is typed in twice. The server reads three stores and writes to none of them:
store | server | what is taken from it |
|
| the invoices, their due dates and how much of each is paid |
|
| the credit notes, already stored with a negative sign |
|
| the deposit applications, and what is still held |
A store you have never installed is simply absent, and the statement is built without it. A store that is on disk and cannot be READ is a different thing entirely, and is reported as such on every figure, because a balance that could not be computed must never be shown as a balance of nothing owed. The one store the server refuses to work without is the invoice ledger.
A measured insight
Aging a past date with today's payment figures is not slightly wrong, it is silently
empty. Aging is usually written as "take each invoice, subtract what has been paid, and
bucket by the due date". The subtraction is the part nobody dates. On the worked month in
test/_client.mjs, aged at 2026-06-10, the two rules give:
rule | outstanding | overdue |
as at 2026-06-10 | 2,500.00 EUR | 500.00 EUR, 31 days late |
today's | 1,700.00 EUR | 0.00 EUR |
The naive rule understates what was owed by 800.00 of 2,500.00, a third of the balance,
and it reports NOTHING overdue on a date when an invoice was a month late, because a
payment that arrived two days later has already been subtracted from it. The failure is
invisible: the answer looks tidy, the buckets add up, and it cannot be reproduced next
month because the input keeps moving. So every figure in statement_aging is taken as at
the date asked for, in both directions: an invoice issued after it is not on the books, a
payment made after it has not happened, and a credit note issued after it has not been
given.
The second thing measurement showed: paid_minor and payments[] on an invoice do not
have to agree, and routinely do not. invoice_mark_paid writes both, but deposit_apply
raises paid_minor and appends no payment row at all, and an invoice created before that
field existed has no rows either. Reconstructing receipts from payments[] would have
lost 300.00 of the worked month's 900.00 of receipts, a third of the cash, with no error
anywhere. paid_minor is treated as the authority and the rows are only the attribution.
Rules this server holds to
A deposit is money that moves once. Applying a deposit already writes the payment on the invoice, so the statement counts it there and breaks it out as "of which deposits applied" rather than crediting it a second time. Deposit money still held is a memo line and is never part of the balance: it is the client's money until it is applied.
Currencies are never added together. One statement is one currency, and a client billed in two is asked which. There is no exchange rate in this server, so a single figure across a EUR ledger and a USD one would be one it made up.
Due today is not overdue. An invoice enters the 0-30 bucket on the first day past its due date. What is outstanding but not yet due is reported beside the buckets, never inside them and never hidden.
A credit note reduces the invoice it names and no other. An open balance floors at zero and any excess is reported as unapplied credit, rather than quietly cancelling an invoice the client never agreed it against.
No chaser invents a charge. The three dunning levels differ in tone and deadline and in nothing else. No level states a late fee, an interest rate or a legal cost, because this server holds no contract terms, no statutory rate and no jurisdiction, and the one place never to put a made-up number is a demand for money.
A chaser for a client with nothing overdue is refused, and the refusal says what is outstanding but not yet due.
Privacy
All data stays on your machine. The invoices, credit notes and deposits are read from
${XDG_DATA_HOME:-~/.local/share}/mcp-servers/, this server's own register of built
statements is written to .../mcp-servers/statement-of-account/, and nothing is sent
anywhere. There is no network call in this server at all. License keys verify offline.
License
MIT. Support: support@zovo.one
Built by theluckystrike.
Available Tools
8 toolsdunning_textWrite a dunning letterA
Write a payment chaser at level 1 friendly, 2 firm or 3 final demand: every OVERDUE invoice with its age, the total and your bank details. Refused if nothing is overdue. No interest is stated. Level 3 is Pro.
| Name | Required | Description | Default |
|---|---|---|---|
| as_of | No | Age the invoices as at this date, YYYY-MM-DD. Defaults to today | |
| level | Yes | 1 friendly reminder, 2 firm reminder, 3 final demand. Level 3 is Pro | |
| client | Yes | Client id from the invoice server, an exact client name, or a name containing this text | |
| currency | No | Only needed when the client has documents in more than one currency. Currencies are never added together | |
| greeting | No | Opening line, default "Hello" and the client name | |
| sign_off | No | Closing line, default your business name from the shared profile |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It discloses key behaviors: refusal when nothing is overdue, no interest stated, level 3 is Pro, and that every overdue invoice is included with age, total, and bank details. It doesn't mention whether the output is text or PDF, but the tool name and siblings suggest text output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no waste. The core behavior, level semantics, and refusal condition are all front-loaded. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a text-generation tool with 6 parameters and no output schema, the description covers the essential behavior, refusal condition, and level semantics. It doesn't specify the output format (plain text vs. formatted), but the sibling statement_text and the tool name make that reasonably clear. Minor gap: no mention of how currency is handled beyond the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all parameters. The description adds context about level meanings and the 'Pro' designation, but doesn't add much beyond the schema for parameters like as_of, client, currency, greeting, and sign_off.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Write a payment chaser') and resource (overdue invoices), and clearly distinguishes the three levels. It also differentiates from siblings like statement_text by focusing on dunning letters for overdue invoices.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use it (when invoices are overdue) and when not to ('Refused if nothing is overdue'). It doesn't explicitly name sibling alternatives, but the context is clear enough for an agent to select this tool over statement_text or statements_report.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
license_activateActivate licenseA
Activate a Pro key (MCPL1.xxx.yyy) from checkout: verified offline against a built-in public key, saved to your config file. A wrong, malformed or expired key is refused, unsaved. license_status reads it back.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | License key from the checkout confirmation page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It discloses that verification happens offline against a built-in public key, that the key is persisted to the config file, and that invalid keys are refused and left unsaved. This is substantial transparency for an activation tool, though it could mention overwriting an existing key or the exact return behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The first sentence front-loads the main action, source, verification method, and persistence. The second sentence efficiently covers error handling and points to the related read-back tool. Every clause adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a single-parameter tool with no output schema and no annotations, the description covers activation behavior, verification mechanism, persistence, error outcomes, and how to read the result later. The only minor gap is an explicit statement of what the function returns upon success or failure, but the phrase 'refused, unsaved' implies a feedback mechanism. Overall, it is sufficiently complete for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents the 'key' parameter at 100% coverage, so the baseline is 3. The description adds meaningful semantics by giving the concrete key format ('MCPL1.xxx.yyy'), confirming the key comes from the checkout page, and explaining that malformed or expired keys will be rejected. This goes beyond the schema's one-line description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Activate a Pro key'), the exact key format ('MCPL1.xxx.yyy'), the source ('from checkout'), and the core mechanism ('verified offline against a built-in public key'). It also differentiates itself from the sibling license_status by noting that license_status reads the activation back, so there is no ambiguity about which tool does what.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use this when you have a Pro key from checkout that needs to be activated. It also points to license_status as the read-back tool, which implies when to use a related sibling. It does not explicitly spell out 'do not use for checking status' or list other alternatives, but the context is strong enough to avoid misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
license_statusLicense statusA
Report this server's licence state: product, tier free or pro, licence id, expiry, the key source and the upgrade URL. No arguments, no network. Explains a free-tier refusal; license_activate installs a key.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are absent, so the description carries the full burden of behavioral disclosure. It discloses that the call is local ('no network') and argument-free, and it mentions a specific explanatory behavior. The word 'Report' implies read-only, though it does not explicitly state non-destructive or permission requirements; this is adequate for a status command.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The first sentence lists the output fields; the second adds constraints and the sibling pointer. Every clause contributes meaningful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter status tool with no output schema, the description lists the expected output fields, behavioral constraints, and the relevant alternative tool. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero parameters and the description reinforces this with 'No arguments'. It adds value by listing the reported fields, helping an agent understand what the empty input will yield. The baseline for zero-parameter tools is high, and the description meets it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Report'), a clear resource ('this server's licence state'), and enumerates the exact fields returned. It also names the sibling 'license_activate' as the tool that does something different, so an agent can distinguish them immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage constraints: no arguments, no network, and explains a free-tier refusal. It also directs the agent to license_activate when the task is to install a key, serving as an explicit pointer to the relevant alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statement_agingAge the open invoicesA
Age open invoices into 0-30, 31-60, 61-90 and over 90 days past DUE date at a date, per client and currency, with the invoices themselves. Free. statements_report rolls up the whole book instead.
| Name | Required | Description | Default |
|---|---|---|---|
| as_of | No | Age the invoices as at this date, YYYY-MM-DD. Defaults to today | |
| limit | No | Maximum invoice rows returned, default and ceiling 2000 | |
| client | No | One client id or name. Omit to age every client in the books | |
| currency | No | Only this currency. Omit for every currency, each aged separately |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full disclosure burden. It does reveal useful behavior: aging buckets, DUE-date basis, per-client/currency aggregation, inclusion of invoice-level rows, and a 'Free' cost signal. However, it does not explicitly state whether the operation is read-only, what exact response shape is returned, or any limits beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two efficient sentences plus a single-word cost note. The action and bucket definitions are front-loaded, and the sibling differentiation is stated without any filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a reporting tool with no annotations and no output schema, the description gives enough context to select and invoke it correctly: what it computes, at what date, per what dimensions, and how it differs from the sibling. It could be more complete about exact return fields or side effects, but these are minor for this apparent read-only aging report.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents all four parameters with 100% coverage, so the baseline is 3. The description reinforces client/currency and as-of date relevance, but adds no parameter-level detail beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Age open invoices into 0-30, 31-60, 61-90 and over 90 days past DUE date.' It also defines scope ('per client and currency, with the invoices themselves') and distinguishes itself from statements_report, so an agent can tell them apart immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative tool ('statements_report') and contrasts its behavior ('rolls up the whole book instead'). The word 'instead' makes the when-not-to-use clear: use this tool when per-client/currency invoice detail is needed, not a whole-book rollup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statement_buildBuild a statement of accountA
Build one client's statement for a period: opening, invoices, payments with deposits applied broken out, credit notes and closing, formatted and in minor units. Free: 5 a month; a rebuild is free.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Last day of the period, YYYY-MM-DD, inclusive | |
| from | Yes | First day of the period, YYYY-MM-DD. Everything dated before it becomes the opening balance | |
| client | Yes | Client id from the invoice server, an exact client name, or a name containing this text | |
| currency | No | Only needed when the client has documents in more than one currency. Currencies are never added together |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the transparency burden. It usefully discloses output contents, minor-unit formatting, and the free quota/rebuild rule, but it does not reveal side effects, whether builds persist, what output medium is produced, or any auth/permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two dense sentences with no filler: the first front-loads the operation and output components, the second conveys quota behavior. Every clause adds useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema, the description does explain what the statement contains and that amounts are in minor units. It falls short by not specifying the output format/medium or how this relates to statement_pdf/statement_text, and it leaves the free/rebuild quota mechanics unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents client, from, to, and currency. The description adds no parameter-level detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb-resource pair, 'Build one client's statement for a period', and enumerates the statement contents (opening, invoices, payments, credit notes, closing). It clearly explains what the tool does, but it does not explicitly distinguish this from sibling tools such as statement_pdf or statement_text, whose names suggest overlapping statement-generation functions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'one client's statement for a period' implies a single-client, period-based use case, and the quota note ('Free: 5 a month; a rebuild is free') gives some context on when building may be constrained. However, the description never says when to prefer this over alternatives like statements_report, statement_pdf, or statement_text, nor does it state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statement_pdfRender the statement of account as a PDFA
Call this tool to write one client's A4 statement of account and return the path. Titled STATEMENT OF ACCOUNT, movements in date order, BALANCE OUTSTANDING at the foot, and no VAT re-added. Pro.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Last day of the period, YYYY-MM-DD, inclusive | |
| from | Yes | First day of the period, YYYY-MM-DD | |
| as_of | No | Date printed on the statement, YYYY-MM-DD. Defaults to today | |
| client | Yes | Client id from the invoice server, an exact client name, or a name containing this text | |
| currency | No | Only needed when the client has documents in more than one currency. Currencies are never added together | |
| out_path | No | Where to write the PDF; defaults to this server's data directory under pdf/. Use a .pdf path: the bytes written are always PDF |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and does a solid job: it discloses the page size, title, chronological ordering, BALANCE OUTSTANDING placement, VAT handling, file-writing side effect, and returned path. It does not cover overwrite, authentication, or error behavior, but the core behavior is well described.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded with the action and return value. The second sentence is telegraphic but informative; however, the trailing 'Pro.' is unexplained noise that does not earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with six parameters and no output schema, it communicates the essential return contract and PDF content well. However, it does not resolve the ambiguity of the fuzzy client parameter or explicitly guide selection among the sibling statement tools, so it is not fully complete for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline of 3 applies. The description adds no parameter-specific details beyond the schema, except implicit mapping like 'one client's' to client and 'path' to out_path.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('write') and resource ('one client's A4 statement of account'), and the title confirms the PDF output. It is specific enough to be distinguished from report-style siblings, though it never names an alternative explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a direct instruction and a clear context ('one client's'), which implies when to use it. However, it does not explicitly mention when not to use it or point to sibling tools such as statement_text or statements_report, leaving the routing partially implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statements_reportWhat every client owesA
Receivables across every client at a date: totals and aging per currency, clients ranked by how much is OVERDUE, and the oldest overdue invoice. Pro. statement_aging is the free per-client view.
| Name | Required | Description | Default |
|---|---|---|---|
| as_of | No | Age the invoices as at this date, YYYY-MM-DD. Defaults to today | |
| limit | No | How many clients to list, worst first. Default 20 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full behavioral burden. It clearly frames this as a read-style reporting tool and discloses the Pro restriction plus the key output behaviors (totals, aging, overdue ranking, oldest overdue invoice). It does not explicitly say 'read-only' or describe license failure behavior, but the language strongly implies a non-mutating report.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences deliver the core functionality, the Pro qualifier, and the alternative tool without any filler. The most important fact, what the report contains, is front-loaded, and every phrase earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has only two optional, well-described parameters and no output schema, and the description gives a solid high-level account of the returned contents. The only slight gap is that 'Pro' is terse and does not explicitly state what happens if the license is absent, but the sibling license tools help fill that context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters as_of and limit are already fully documented with defaults, format, and constraints. The description does not need to add parameter semantics and adds only a slight thematic alignment with 'at a date' and 'worst first', so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb and resource: it reports receivables across every client at a given date, with totals, aging per currency, overdue ranking, and the oldest overdue invoice. It also explicitly contrasts itself with statement_aging, making the tool's distinct role clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description tells the agent when to prefer this tool: when a cross-client receivables view is needed. It explicitly names statement_aging as the free per-client alternative, giving clear routing guidance and preventing confusion with a closely related sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statement_textPlain-text statement of accountA
Turn one client's statement into a plain-text letter for an email: movements in date order, opening and closing balances, deposit held, a sign-off. It counts toward the 5 a month; statement_pdf writes the A4 page.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Last day of the period, YYYY-MM-DD, inclusive | |
| from | Yes | First day of the period, YYYY-MM-DD | |
| as_of | No | Date printed on the statement, YYYY-MM-DD. Defaults to today | |
| client | Yes | Client id from the invoice server, an exact client name, or a name containing this text | |
| currency | No | Only needed when the client has documents in more than one currency. Currencies are never added together | |
| greeting | No | Opening line, default "Hello" and the client name | |
| sign_off | No | Closing line, default your business name from the shared profile |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It does disclose the output format, ordering of movements, included balances, deposit-held note, sign-off, and monthly quota consumption. However, it does not state whether the operation has side effects on data, what permissions are needed, or how ambiguous client matches are handled.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with no filler. The core transformation is front-loaded, followed by the quota warning and the key sibling alternative. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description adequately explains what the returned text will contain and that the result is intended for email. It also covers the quota and differentiates from statement_pdf. It is slightly incomplete in that it does not orient the agent among other statement-related siblings, but the main use case is clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3 and the schema already documents all parameters. The description adds only indirect references to sign-off and date-ordered movements, not meaningful extra parameter-level semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: it turns one client's statement into a plain-text letter for email, with clear contents (movements, balances, deposit held, sign-off). It also distinguishes itself from statement_pdf by explicitly saying that tool writes the A4 page.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context for when to use the tool: plain-text email output versus statement_pdf's A4 page. It also warns that the tool counts toward a monthly quota of 5, which is a useful usage constraint. It does not explicitly cover when to prefer statement_build, statement_aging, or dunning_text.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.14.0- First observed
dunning_text - First observed
license_activate - First observed
license_status - First observed
statement_aging - First observed
statement_build - First observed
statement_pdf - First observed
statement_text - First observed
statements_report
TDQS
Scored across 8 tools
Each tool has a clearly distinct purpose: license activation/status, dunning text, per-client aging, whole-book reporting, and statement building/PDF/text outputs. The descriptions explicitly cross-reference differences, such as statement_aging vs statements_report and statement_text vs statement_pdf, so there is no real ambiguity.
Names are consistently snake_case and mostly use the statement_ prefix, but the verb/noun pattern is mixed: license_activate and statement_build are noun+verb, while license_status, statement_pdf, statement_text, and statements_report are noun+noun. The conventions are readable but not uniform enough for a higher score.
Eight tools is well-scoped for this server: two license utilities, one dunning helper, two aging/report tools, and three statement output tools. Each tool earns its place and covers a distinct part of the statement workflow without redundancy.
The core statement workflow is well covered: build, text, PDF, aging, receivables report, dunning, and license state. Minor gaps exist, such as no license deactivation or quota/usage check for the free monthly statement builds, but these are workable and not likely to break common agent flows.
Maintenance
Related MCP Connectors
Statements of account, aging buckets and dunning letters from your invoices.
Security and retainer deposits per client: hold, apply to an invoice, refund, statement.
Chase overdue invoices: reminder 1, reminder 2, final notice, escalation dates, aging.
Chilean DTE/SII invoicing — issue invoices, reconcile payments and manage clients with AI agents.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables the generation of professional PDF invoices and their distribution via email using customizable templates. It allows users to create, manage, and send invoices with standard business fields like tax rates and line items through natural language.32 npm2MIT
- FlicenseNot gradedqualityCmaintenanceEnables MCP clients to search and inspect an invoice ledger, generate VAT summaries, run OCR on local documents, and use reusable prompts for chasing overdue invoices and reconciling entries.2-
- AlicenseNot gradedqualityCmaintenanceLets a user ask what their business is owed, who to chase first, and get a chase email drafted in their own voice, via tools for weekly totals, chase queues, customer history, due-soon invoices and insights. Every tool only reads or returns a draft, so nothing can be sent.MIT
- AlicenseAqualityBmaintenanceEnables issuing credit notes and credit memos against an invoice or standalone as revisable drafts that can be finalized into frozen numbered documents, then rendered as Markdown or printable HTML with totals broken down by currency, reason and month. All amounts are handled as integer minor units and all data stays local, so nothing is sent anywhere.10MIT