Skip to content

io.github.theluckystrike/mileage-tracker

by theluckystrike · remote · local (mcpb) · no sign-in to list tools · v0.21.1 · published by GitHub user theluckystrike

Log expenses, receipts and mileage from chat: auto-categorise, split VAT, summarise, export, rebill.

Deletes · 1Final · 5Changes · 6

14 tools: 1 can delete or cancel things, 5 do something that can't be undone, 6 change things and 2 only read.

Scanned Oct 21, 2026

4 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http mileage-tracker https://mcp.zovo.one/mcp/mileage-tracker --header 'Authorization: <your-authorization>'

Findings

Matches of fixed checks, with the text they matched.

4 warn
  • The server marks "expense_settings" as not read-only (readOnlyHint: false), and its words say it reads.

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The description's first verb is "read": a word for reading.

    What this check looks for
  • The server marks "expense_summary" read-only (readOnlyHint: true), and its own name, description or input give the class "irreversible".

    Matched text

    annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The input addresses people (input.to): what it sends cannot be taken back.

    What this check looks for
  • The server marks "expense_export" read-only (readOnlyHint: true), and its own name, description or input give the class "irreversible".

    Matched text

    annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The input addresses people (input.to): what it sends cannot be taken back.

    What this check looks for
  • The server marks "expense_to_invoice" as not read-only (readOnlyHint: false), and its words say it reads.

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The description's first verb is "preview": a word for reading.

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

14 tools

Deletes or cancels 1Claude Code: deny
  • expense_deleteDelete one expense by id and report what went.No findings

    Why it is in this group

    • The name "expense_delete" says "delete": a word for removing or ending something.
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    Delete one expense by id and report what went. The receipt FILE stays on disk. Deleting a rebilled expense loses the record of what an invoice charged, so correct it with expense_update instead.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: false
Can't be undone 5Claude Code: ask
  • expense_addRecord one expense and return its id, its net/VAT split and its billable flag.No findings

    Why it is in this group

    • The name "expense_add" says "add": a word for a change.
    • The input carries an amount (input.amount) and a currency, so it moves money.
    Description, as the server wrote it
    Record one expense and return its id, its net/VAT split and its billable flag. The response states every default that was applied, so the caller can see what was assumed rather than having to guess.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • expense_exportExport the expenses in a date range as csv, xlsx or json and return a download link that is valid for one hour.1 finding

    Why it is in this group

    • The input addresses people (input.to): what it sends cannot be taken back.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "expense_export" read-only (readOnlyHint: true), and its own name, description or input give the class "irreversible".

      Matched text

      annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The input addresses people (input.to): what it sends cannot be taken back.

      What this check looks for
    Description, as the server wrote it
    Export the expenses in a date range as csv, xlsx or json and return a download link that is valid for one hour. Nothing partial is ever written: if a limit is hit no file is produced at all.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • expense_mark_rebilledMark expenses as rebilled once the invoice that carries them actually exists.No findings

    Why it is in this group

    • The name "expense_mark_rebilled" says "mark": a word for a change.
    • The input addresses people (input.to): what it sends cannot be taken back.
    Description, as the server wrote it
    Mark expenses as rebilled once the invoice that carries them actually exists. Pass the expense_ids of one currency group from expense_to_invoice, or that project, date range and currency. Returns what was marked.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • expense_summaryTotals for a date range grouped by category, project, month or merchant, per currency with gross, net and VAT, never mixed.1 finding

    Why it is in this group

    • The input addresses people (input.to): what it sends cannot be taken back.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "expense_summary" read-only (readOnlyHint: true), and its own name, description or input give the class "irreversible".

      Matched text

      annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The input addresses people (input.to): what it sends cannot be taken back.

      What this check looks for
    Description, as the server wrote it
    Totals for a date range grouped by category, project, month or merchant, per currency with gross, net and VAT, never mixed. Receipts only; bank transactions are totalled by bank-statement's statement_summary.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • expense_updateChange one expense by id; only the fields you pass move.No findings

    Why it is in this group

    • The name "expense_update" says "update": a word for a change.
    • The input carries an amount (input.amount) and a currency, so it moves money.
    Description, as the server wrote it
    Change one expense by id; only the fields you pass move. amount is in MAJOR units. A rebilled expense refuses an amount, currency or vat_rate edit unless unlink_rebill drops the invoice link.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
Changes things 6Claude Code: ask
  • category_rulesReplace the merchant-to-category rules, or call with no rules to list them.No findings

    Why it is in this group

    • The description's first verb is "replace": a word for a change.
    Description, as the server wrote it
    Replace the merchant-to-category rules, or call with no rules to list them. Returns the stored rule list. The rules are applied by expense_add whenever a call gives no category of its own.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • expense_settingsRead or set the defaults expense_add uses when a call does not name them: default_vat_rate and default_currency.1 finding

    Why it is in this group

    • The description's first verb is "read": a word for reading.
    • The server marks it as not read-only (readOnlyHint: false).

    Findings

    • Warn

      The server marks "expense_settings" as not read-only (readOnlyHint: false), and its words say it reads.

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The description's first verb is "read": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Read or set the defaults expense_add uses when a call does not name them: default_vat_rate and default_currency. Returns the stored defaults. Call with no arguments to read them without changing anything.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • expense_to_invoicePreview the unbilled billable expenses of one project as invoice_create line items (description, quantity, unit_price, tax_rate), grouped per currency.1 finding

    Why it is in this group

    • The description's first verb is "preview": a word for reading.
    • The server marks it as not read-only (readOnlyHint: false).

    Findings

    • Warn

      The server marks "expense_to_invoice" as not read-only (readOnlyHint: false), and its words say it reads.

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The description's first verb is "preview": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Preview the unbilled billable expenses of one project as invoice_create line items (description, quantity, unit_price, tax_rate), grouped per currency. Read-only: nothing is marked rebilled here.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • license_activateTurn Pro on for this connection with key, an MCPL1.<payload>.<signature> issued at checkout for this server or the bundle.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Turn Pro on for this connection with key, an MCPL1.<payload>.<signature> issued at checkout for this server or the bundle. Data under your token stays; a wrong or expired key changes nothing. license_status confirms it.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • mileage_addRecord a business trip as an expense, priced as distance x rate.No findings

    Why it is in this group

    • The name "mileage_add" says "add": a word for a change.
    Description, as the server wrote it
    Record a business trip as an expense, priced as distance x rate. Give exactly one of km or miles. Returns the saved id with the rate used, where that rate came from and the money, in the rate's own currency.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • receipt_attachNot available on the hosted endpoint: it has no filesystem, so there is no receipt file to read or hash.No findings

    Why it is in this group

    • The name "receipt_attach" says "attach": a word for a change.
    Description, as the server wrote it
    Not available on the hosted endpoint: it has no filesystem, so there is no receipt file to read or hash. Attach receipts on a local install instead - download expense-tracker.mcpb from https://github.com/theluckystrike/mcp-servers/releases/latest and open it in Claude Desktop - or record the receipt reference in the expense note.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
Only reads 2Claude Code: allow
  • expense_listList expenses in a date range with each one's net/VAT split, category, merchant, project and billable flag, plus a total per currency.No findings

    Why it is in this group

    • The name "expense_list" says "list": a word for reading.
    Description, as the server wrote it
    List expenses in a date range with each one's net/VAT split, category, merchant, project and billable flag, plus a total per currency. Free reads the last 30 days and says when your range predates it.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • license_statusReport this endpoint's licence state for your token as JSON: the product, the tier free or pro, why it is not Pro, and the checkout URL.No findings

    Why it is in this group

    • The name "license_status" says "status": a word for reading.
    Description, as the server wrote it
    Report this endpoint's licence state for your token as JSON: the product, the tier free or pro, why it is not Pro, and the checkout URL. Call it to explain a free-tier refusal. No arguments, nothing changes.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.21.1. Values in angle brackets are yours to fill in.

claude mcp add --transport http mileage-tracker https://mcp.zovo.one/mcp/mileage-tracker --header 'Authorization: <your-authorization>'

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__mileage-tracker__expense_list",
      "mcp__mileage-tracker__license_status"
    ],
    "ask": [
      "mcp__mileage-tracker__expense_add",
      "mcp__mileage-tracker__expense_update",
      "mcp__mileage-tracker__receipt_attach",
      "mcp__mileage-tracker__category_rules",
      "mcp__mileage-tracker__expense_settings",
      "mcp__mileage-tracker__expense_summary",
      "mcp__mileage-tracker__mileage_add",
      "mcp__mileage-tracker__expense_export",
      "mcp__mileage-tracker__expense_to_invoice",
      "mcp__mileage-tracker__expense_mark_rebilled",
      "mcp__mileage-tracker__license_activate"
    ],
    "deny": [
      "mcp__mileage-tracker__expense_delete"
    ]
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as mileage-tracker. Review it before you use it.