Home · Guides

Log expenses and mileage in Claude, split VAT, rebill to an invoice

The usual way to keep a business expense ledger is a spreadsheet you update days later from a pile of receipts, or an app you open, log into and tap through. The MCP Expense Tracker puts the ledger in the chat window: say "61.50 euros at Adobe, software, 23% VAT, billable to Acme" and it is logged with the VAT already split out, categorised from a rule you set once, and marked ready to rebill. Everything is a plain JSON file on your own machine.

Install it

One command for Claude Code:

claude mcp add expense-tracker -- npx -y @theluckystrike/mcp-expense-tracker

Cursor reads the same kind of config. Add this to ~/.cursor/mcp.json (or the project-level .cursor/mcp.json), then restart Cursor:

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

Claude Desktop uses claude_desktop_config.json with the same block. There is no account, no API key and no login step: the server runs locally over stdio and writes to ~/.local/share/mcp-servers/expense-tracker/.

Log a receipt and watch the VAT split

Every amount you say is the gross figure printed on the receipt. vat_rate does the rest: net = round(gross * 100 / (100 + rate)) and vat = gross - net, so net plus VAT is always exactly the gross, to the cent. Take the line above: 61.50 EUR gross at 23% VAT splits to net 50.00 EUR and VAT 11.50 EUR. Money is stored as integer minor units in the expense's own currency, so that split has no floating point residue and a summary of many expenses adds up to the same total you would get by hand.

An empty category is not left blank. If you have told the server that Adobe means software, the same sentence without a category still files it under software, because expense_add checks the stored merchant rules before it gives up and leaves the field empty.

Categories that learn from you, not from a fixed list

category_rules holds a list of match-to-category pairs. Each match is tried first as a case-insensitive regular expression and, if that is not valid regex, as a plain substring, so "adobe" or "amazon.*office" both work without escaping. The first rule that matches wins. Call category_rules with no arguments to see what is stored, or replace the whole list at once: no machine learning, no confidence score, just the rule you wrote read back to you exactly.

Mileage from a rate table, not a guess

"Log a 45 km trip in Poland for a client meeting in Krakow, billable to Acme" prices itself: mileage_add multiplies distance by the region's rate and rounds once. The built-in table is PL 1.15 PLN per km, UK 0.45 GBP per mile, US 0.70 USD per mile and EU 0.30 EUR per km. 45 km at the Polish rate is 45 x 1.15 = 51.75 PLN, stored as an expense in PLN with no VAT rate, because mileage allowances are not usually VAT-bearing. With no region given, kilometres default to the EU rate and miles to the US rate; rate_per_km overrides the table entirely if your own employer or tax authority sets a different figure. These are convenience defaults, not tax advice: check the rate your own authority allows for the year before you rely on it.

Receipts you can prove later

receipt_attach takes a path to the receipt file, checks that it exists, and stores the path together with a sha256 of its bytes. That hash is the part worth having: if the file on disk is ever edited or replaced, the stored hash no longer matches it, so an audit later has a way to prove the receipt attached to an expense is the same file that was there when the expense was logged.

Summaries, always per currency

"How much did I spend on software this quarter, and what is still billable to Acme" runs expense_summary grouped by category, project, month or merchant, reporting the gross, the net and the VAT for each group. Currencies are never mixed: an expense in PLN and one in EUR appear as two lines under the same category rather than one wrong total. expense_list answers narrower questions the same way, with totals per currency for whatever date range and filters you gave it.

Rebilling without taxing twice

The point of marking an expense billable is to get it onto a client's invoice, and the wiring to the invoice server is the part worth being precise about. expense_to_invoice takes a project and a date range and returns line items shaped exactly as invoice_create expects: {description, quantity, unit_price, tax_rate}. The unit_price it sends is the net amount, not the gross, and tax_rate carries the VAT rate along with it. The invoice server then computes its own tax line from unit_price and tax_rate, which lands on the same 11.50 EUR of VAT the expense already split out. If the rebill sent the gross 61.50 EUR as the unit price instead, the invoice would add 23% VAT on top of an amount that already included VAT once, over-charging the client by the whole VAT figure. Because one invoice carries one currency, expenses in more than one currency come back grouped by currency, and you pass one group per invoice. Expenses are marked rebilled once sent, so asking again for the same project and range does not bill the client twice; include_rebilled and mark_rebilled exist for the times you want to override that.

Export and free tier

expense_export writes a date range to csv, xlsx or json and never writes a partial file: if a limit would be exceeded, nothing is created at all and the tool says why. Free covers unlimited logging of expenses, mileage and receipts, a 30-day window on expense_list and expense_summary, 3 projects, 5 category rules, csv and json export up to 200 rows, and expense_to_invoice for up to 20 items at cost price. Pro ($19 once) opens full history, unlimited projects and rules, xlsx export, and a markup_percent on the rebill. Full comparison in free versus Pro. Product page: MCP Expense Tracker, which pairs with MCP Invoice for the rebill above and MCP Time Tracker for the hours on the same project, covered in the time tracking guide.

Questions

How exactly is VAT split out of a receipt amount?

The amount you give is the gross figure on the receipt. net = round(gross * 100 / (100 + vat_rate)) and vat = gross - net, so net plus VAT always equals the gross exactly. 61.50 EUR at 23% VAT splits to net 50.00 EUR and VAT 11.50 EUR.

What are the mileage rates and can I use my own?

The built-in table is PL 1.15 PLN/km, UK 0.45 GBP/mile, US 0.70 USD/mile, EU 0.30 EUR/km, with EU used by default for kilometres and US for miles. rate_per_km overrides the table with your own figure and currency. These are convenience defaults, not tax advice.

Does rebilling an expense charge VAT twice?

No. expense_to_invoice sends the net amount as unit_price and the original rate as tax_rate, so invoice_create computes the same VAT figure once. Sending the gross amount instead would tax an already-taxed figure a second time, which is why the server sends net.

How does it prove a receipt file has not been altered?

receipt_attach stores the file's path together with a sha256 hash of its bytes at the moment you attach it. If the file is later edited or swapped, the stored hash no longer matches it, which is what an audit checks.

Is anything uploaded when I log an expense or export a report?

No. All data is stored in a plain JSON file under ~/.local/share/mcp-servers/expense-tracker/, and the server makes no network calls at all. Exports write to a local path you choose or the server's own data directory.

Related

All MCP servers and prices · All guides