Skip to content

io.github.theluckystrike/budget-tracker

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

Track budgets from your AI chat: envelopes, monthly limits, variance reports. All data is local.

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 budget-tracker https://mcp.zovo.one/mcp/budget-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.Can send data out1 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.

    What it can reach

    • outboundThe input takes a destination (input.to): what the tool writes goes there.

    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.Can send data outNo 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.

    What it can reach

    • outboundThe input takes a destination (input.to): what the tool writes goes there.
    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.Can send data out1 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.

    What it can reach

    • outboundThe input takes a destination (input.to): what the tool writes goes there.

    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.Can send data out1 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).

    What it can reach

    • outboundThe input takes a destination (input.to): what the tool writes goes there.

    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.Reads text others writeNo findings

    Why it is in this group

    • The name "license_status" says "status": a word for reading.

    What it can reach

    • untrusted-inputThe description's first sentence says "url": it reads web pages, which anyone can write.
    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.

Exfil surface

Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.

No private-data, untrusted-input, outbound path in this server alone: no tool is tagged private-data.

Reads private data0
Reads files, mail, messages, databases, secrets, calendars or repositories.
Reads text others write1
Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
Can send data out4
Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.

Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.

Install

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

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

Run in a terminal.

Claude Code permissions

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

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

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as budget-tracker. Review it before you use it.

Capability tags behind 5 rules
  • mcp__budget-tracker__expense_summary outbound
  • mcp__budget-tracker__expense_export outbound
  • mcp__budget-tracker__expense_to_invoice outbound
  • mcp__budget-tracker__expense_mark_rebilled outbound
  • mcp__budget-tracker__license_status untrusted-input