Skip to main content
Glama
dunning-letters

dunning-letters

Automated payment reminders for overdue invoices

MCP server for dunning letters and overdue invoice payment reminders: reminder, final notice and aging. Chase overdue invoices on a ladder anchored to the due date: reminder 1, reminder 2, the final notice, with the aging and the day's chase list.

Works with Claude Desktop, Claude Code, Cursor and any Model Context Protocol client. Runs on your own machine, or hosted with no install.

Product page: https://mcp.zovo.one/s/dunning-letters - what it does, the tools it exposes, and a live token endpoint.

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/dunning-letters 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/dunning-letters/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 dunning-letters.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-dunning-letters.git
cd mcp-dunning-letters
npm install && npm run build

Then point your client at the built entry point:

{
  "mcpServers": {
    "dunning-letters": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-dunning-letters/dist/index.js"]
    }
  }
}

@theluckystrike/mcp-dunning-letters is not published on npm yet, so an npx -y @theluckystrike/mcp-dunning-letters command will fail. The three paths above are the working ones and each is exercised by CI.

dunning-letters demo

Read-only mirror of mcp-servers/servers/dunning-letters. See MIRROR.md.

theluckystrike/mcp-dunning-letters MCP server

In the official MCP Registry (io.github.theluckystrike/dunning-letters). Chase overdue invoices without losing the thread. Register an unpaid invoice, client, invoice reference, amount in integer cents, currency, due date, and the server runs the escalation ladder: reminder 1 (polite, due + 7 days), reminder 2 (firm, with the late fees note, due + 14), and the final notice (before-action wording, due + 21; the gaps are configurable per invoice). For each stage it generates the letter, as Markdown or as a self-contained printable HTML page. It records what you sent and when, lists everything overdue with days late and stage, ages the whole register into current/30/60/90+ buckets, and answers "what do I need to send today". Nothing is emailed or sent anywhere: this server produces the letter text, and sending it is your act.

Built by theluckystrike.

npm publish for @theluckystrike/mcp-dunning-letters is pending, so npx -y @theluckystrike/mcp-dunning-letters returns 404 today. Until then, a clone+build is the working path.

Related MCP server: kelo-mcp

Install

Claude Desktop

macOS ~/Library/Application Support/Claude/claude_desktop_config.json, Windows %APPDATA%\Claude\claude_desktop_config.json:

{
  "mcpServers": {
    "dunning-letters": {
      "command": "npx",
      "args": ["-y", "@theluckystrike/mcp-dunning-letters"]
    }
  }
}

Claude Code

claude mcp add dunning-letters -- npx -y @theluckystrike/mcp-dunning-letters

Cursor

~/.cursor/mcp.json (global) or .cursor/mcp.json (project), same entry as Claude Desktop.

Tools

tool

what it does

invoice_register

Start chasing an unpaid invoice: client, reference, amount, currency, due date. Returns DUN-YYYY-NNNN and the three escalation dates

payment_record

Record money received, full or partial. A part payment lowers what the next letter asks for; covering the balance closes the ladder

letter_render

Generate the chase letter for the current stage -- reminder 1, reminder 2 or the final notice -- as Markdown or self-contained printable HTML. Nothing is emailed: you send the text it produces

letter_sent

Record that a letter actually went out, with its date, so the ladder advances. Letters go out in order

overdue_list

Every unpaid invoice past its due date: days late, outstanding, letters sent, what is due next, worst first

aging_summary

The whole register in current/1-30/31-60/61-90/91+ buckets, counts and totals in integer cents, per currency

chase_today

The day's chase list: which invoices cross an escalation threshold today, which letter to send each, what falls due next

invoice_status

One chased invoice in full: payments, letters, schedule, next action

invoice_delete

Delete an invoice entered wrongly. The id is not reissued

license_status / license_activate

Free or Pro, and the key

Free vs Pro

Free

Pro

Unpaid invoices chased at once

3

Unlimited

All three letters, both formats

Yes

Yes

Aging summary and the day's chase list

Yes

Yes

Late fee accrual in the letters

Yes

Yes

Payment recording and history

Yes

Yes

The cap is on how many chases run at once, never on the letters or the aging: three late payers taken from first reminder to final notice is a real chase list, and an invoice that gets paid frees its slot. What is metered is breadth, a fourth concurrent chase is a collections workload, not a freelancer's month.

Get Pro: https://mcp.zovo.one/buy/dunning-letters, $19 one-time for this server, or $39 for the bundle.

A measured insight

The ladder is anchored to the due date, not to the last letter, and the two drift apart exactly when chasing is going badly.

The worked chase in test/_client.mjs: USD 1,250.00 due 2026-06-01, gaps 7/14/21, so the letters fall due on 06-08, 06-15 and 06-22 whether or not anything was sent. If reminder 1 actually goes out late, say 06-20, twelve days after its date, a previous-letter-anchored ladder would push the final notice to 07-11. This one does not: 06-22 stands, because the client's obligation was fixed by the due date, not by when you got around to writing. Recording a sending moves only which stage is next; it never moves the schedule. The letters are also strictly sequential: an invoice 60 days late with nothing sent is still owed reminder 1, because a final notice that no polite letter preceded reads as a threat, not a chase.

The late fee is measured the same way, once: simple interest, pro-rata on a 30-day month, on the amount outstanding on the day the letter is written, rounded once to the minor unit. On the worked chase that is 125,000 minor units at 2% over 30 days late, 2,500 exactly, and after a 50,000 part payment it is 1,500 on the 75,000 that remains, so the final notice asks for 76,500 and no invented figure more.

Privacy

All data stays local, in ${XDG_DATA_HOME:-~/.local/share}/mcp-servers/dunning-letters/. Two files: invoices.json, counter.json. Nothing is sent anywhere, no account, no API key, no network call in this server at all, and the letters are rendered to text for you to send yourself; this server holds no mail credentials and wants none. License keys are verified offline.

Built by theluckystrike. https://github.com/theluckystrike

Frequently asked questions

Is there an MCP server for payment reminders or dunning letters?

Yes. The dunning-letters server at mcp.zovo.one automates accounts-receivable follow-up: tiered reminder sequences (friendly, firm, final), printable PDF letters, per-customer aging. Free tier, hosted remote endpoint.

How do I send payment reminders from Claude?

Connect https://mcp.zovo.one/mcp/dunning-letters and say: 'List overdue invoices and draft a firm reminder for Acme.' The letter follows the standard tier sequence and exports as PDF.

Use these docs as an MCP server

Any MCP client (Claude, Cursor, Windsurf, VS Code) can read this repository's documentation directly via GitMCP - no install:

Available Tools

11 tools
aging_summaryAging summary of what is owedA

The aging summary across every unpaid invoice: current, 1-30, 31-60, 61-90 and 91+ day buckets, with counts and totals in integer cents, per currency. This is the answer to "how much am I owed, and how stale is it".

Inputs: on.

chase_todayWhat to chase todayA

The day's chase list: which invoices cross an escalation threshold today, which letter to send each and how long it has been waiting, what falls due in the next few days, and which invoices have had all three letters and need a decision outside this server.

Inputs: on, within_days.

invoice_deleteDelete an invoice from the registerA

Delete an invoice entered wrongly, by id or reference: the record, its payments and its letter history. The id is not reissued, so a gap in the DUN series is the record that a deletion happened.

Inputs: invoice (required).

invoice_registerRegister an unpaid invoice to chaseA

Start chasing an unpaid invoice: register the client, the invoice reference, the amount in integer cents, the currency and the due date, and get the three-letter escalation schedule (reminder 1, reminder 2, final notice) with the date each falls due. Free tier: 3 unpaid invoices chased at once.

Inputs: due (required), client (required), currency (required), reference (required), +6 more.

invoice_statusThe full state of one chased invoiceA

One chased invoice in full: what was billed, what has been paid and what is still owed, every letter sent with its date, the escalation schedule with each stage's state, and what happens next and when.

Inputs: invoice (required), on.

letter_renderGenerate the chase letter for the current stageA

Chase an unpaid invoice: generate the letter for the current stage of the ladder -- reminder 1 (polite), reminder 2 (firm, with the late fees note) or the final notice (before-action wording) -- as Markdown or as self-contained printable HTML. Nothing is emailed or sent anywhere: this server produces the letter text, and sending it is your act. Record the sending with letter_sent so the ladder advances.

Inputs: invoice (required), on, stage, format.

letter_sentRecord that a letter was sentA

Record that a chase letter was actually sent, with its date, so the ladder advances to the next stage. Letters go out in order: reminder 2 cannot be recorded before reminder 1. Returns what is due next and when.

Inputs: invoice (required), sent, stage.

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.

Inputs: key (required).

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.

Inputs: no named parameters.

overdue_listList overdue invoicesA

Every unpaid invoice past its due date: how many days late, what is still owed, which letters have gone out, and what is due next and when. Sorted by days late, worst first.

Inputs: on, limit.

payment_recordRecord a payment receivedA

Record money received against a chased invoice, in whole MINOR units: a part payment lowers what is still chased, a payment that covers the balance closes the ladder and frees the free-tier slot. Returns the outstanding amount.

Inputs: invoice (required), amount_minor (required), date, note.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 11 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose: registration, payments, letter generation, recording sent letters, status queries, reporting, and license management. Even the reporting tools (overdue_list, aging_summary, chase_today) target different views (detailed list, summary buckets, today's actions) with descriptions that prevent confusion.

    Naming Consistency4/5

    All tool names use snake_case and mostly follow a noun-verb or verb-noun pattern, but the order is inconsistent (e.g., invoice_register vs. payment_record). Some names are noun-noun (license_status, aging_summary) or ambiguous (chase_today). Despite this, the pattern is readable and predictable enough.

    Tool Count5/5

    With 11 tools, the set is well-scoped for the domain. It covers the core invoice lifecycle (register, status, delete), payment handling, letter generation and sending, comprehensive reporting (overdue, aging, daily chase), and license management. Each tool earns its place.

    Completeness5/5

    The tool surface is complete for dunning letter management: starting chases, recording payments, generating and tracking letters, querying invoice state, and producing aggregated reports. The license tools are separate but necessary. No obvious gaps in the lifecycle are apparent.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      B
      maintenance
      Enables building client statements of account from existing invoices, credit notes, and deposits, with aged outstanding balances, PDF/plain-text output, and drafted payment chasers at friendly, firm, or final levels.
      8
      60 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Lets 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
    • A
      license
      A
      quality
      B
      maintenance
      Enables 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.
      10
      57 npm
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables trades and field service work to be tracked per job: logging labor hours at worker rates and materials used, keeping running totals in integer cents per currency, and moving each job through a status machine from open to invoiced or archived. It also produces daily or weekly summaries of hours and value, and renders a printable card with a signature line for client sign-off.
      11
      55 npm
      MIT