Atlas / MCP servers / agigante80 / actual-mcp-server

actual-mcp-serverBLOCK

mcp/agigante80/actual-mcp-server

Talk to your self-hosted Actual Budget from any MCP client: a remote HTTP server for LibreChat/LobeChat or a local stdio process for Claude Desktop, with 71 tools for transactions, budgets, rules, and bank sync. No Docker needed for local use.

Verdict
BLOCK
Grade
D
Trust score
68 /100
Exposed tools
85 46r · 28w · 11d
Transport
stdio · streamable-http
License
MIT
Stars
66
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

Actual MCP Server

[](https://www.npmjs.com/package/actual-mcp-server) [](https://www.npmjs.com/package/actual-mcp-server) [](https://opensource.org/licenses/MIT) [](https://nodejs.org/) [](https://www.typescriptlang.org/) [](https://modelcontextprotocol.io/) [](https://hub.docker.com/r/agigante80/actual-mcp-server) [](https://hub.docker.com/r/agigante80/actual-mcp-server) [](https://ca.unraid.net/apps/actual-mcp-server-0bghkvs0c7c8bg) [](https://github.com/agigante80/actual-mcp-server/actions) [](https://github.com/agigante80/actual-mcp-server)

Talk to your budget. Run it anywhere. Trust it in production.

Actual MCP Server is a Model Context Protocol server that connects any MCP-compatible AI assistant (such as LibreChat, LobeChat, Claude Desktop, and more) directly to your self-hosted [Actual Budget](https://actualbudget.or

Read from source at commit 582fab680352OBSERVED · 2026-10-12
Advertisement
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add actual-mcp-server --env ACTUAL_BUDGET_PASSWORD=${ACTUAL_BUDGET_PASSWORD} --env ACTUAL_PASSWORD=${ACTUAL_PASSWORD} --env AUTH_BUDGET_ACL_SOURCE=${AUTH_BUDGET_ACL_SOURCE} --env AUTH_PROVIDER=${AUTH_PROVIDER} -- npx -y [email protected]
claude-desktop
{
  "mcpServers": {
    "actual-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "[email protected]"
      ],
      "env": {
        "ACTUAL_BUDGET_PASSWORD": "${ACTUAL_BUDGET_PASSWORD}",
        "ACTUAL_PASSWORD": "${ACTUAL_PASSWORD}",
        "AUTH_BUDGET_ACL_SOURCE": "${AUTH_BUDGET_ACL_SOURCE}",
        "AUTH_PROVIDER": "${AUTH_PROVIDER}"
      }
    }
  }
}
03

Exposed tools (85)

46 read · 28 write · 11 destructive. Blast radius: 11 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
actual-mcp-serverreadMCP server for Actual Budget
actual_account_groups_createwriteCreate a custom account group for organising accounts in the sidebar.
actual_account_groups_deletedestructiveDelete a custom account group. The accounts in it are NOT deleted: they become ungrouped.
actual_account_groups_listreadList the custom account groups used to organise accounts in the sidebar.
actual_account_groups_updatewriteRename a custom account group or change its sidebar position.
actual_accounts_closereadMark an account as closed in Actual Budget. Closed accounts are hidden from most views.
actual_accounts_createwriteCreate a new account in Actual Budget
actual_accounts_deletedestructiveDelete an account from Actual Budget. DESTRUCTIVE: if the account has transactions, they are
actual_accounts_get_balancereadGet the current balance of a specific account. Required: - id: Account UUID Optional: - cutoff: Date to calculate balance up to (YYYY-MM-DD format) Returns the account balance as a number (in cents), or an error if the account does not exist. Example: {
actual_accounts_listreadList all accounts in Actual Budget including checking, savings, credit cards, and investment accounts. Returns account ID, name, balance (in cents), on-budget/off-budget status, and open/closed state.
actual_accounts_reopenreadReopen a previously closed account in Actual Budget. The account becomes active again and
actual_accounts_updatewriteUpdate an account
actual_budgets_exportreadExport the currently active budget as an Actual Budget
actual_budgets_getMonthreadGet budget data for a specific month in YYYY-MM format (e.g.,
actual_budgets_getMonthsreadGet a list of all available budget months with summary data. Returns an array of months showing total budgeted, spent, and income for each month. Useful for viewing budget history and trends over time.
actual_budgets_get_allreadGet a list of all available budget files. Useful for multi-budget management and discovering available budgets on the server.
actual_budgets_holdForNextMonthreadHold an amount from this month
actual_budgets_importwriteRestore or import a budget from an Actual Budget
actual_budgets_list_availablereadList all pre-configured budgets available for switching.
actual_budgets_resetHolddestructiveReset the budget hold for a month, releasing any amount previously held for next month via holdBudgetForNextMonth.
actual_budgets_setAmountwriteSet the budgeted amount for a specific category in a given month. Amount in cents
actual_budgets_setCarryoverwriteSet carryover behavior for a category in a specific month. When enabled (true), leftover budget or overspending automatically rolls into the next month
actual_budgets_switchreadSwitch to a different pre-configured budget for all subsequent operations in this session.
actual_budgets_transferwriteTransfer budget amount between categories. Decreases the source category budget and increases the target category budget by the specified amount for the given month.
actual_categories_createwriteCreate a category. REQUIRED: group_id (category group UUID). Use actual_category_groups_get to find available groups. Optional: is_income (boolean, defaults to false for expense categories).
actual_categories_deletedestructiveDelete a category from Actual Budget. Transactions using this category will need to be recategorized. This operation cannot be undone.
actual_categories_getreadList all budget categories organized by category groups. Categories are spending/income buckets (e.g., Groceries, Rent, Salary) used for budgeting and transaction categorization. Returns both grouped view and flat list with category IDs, names, and group assignments.
actual_categories_updatewriteUpdate an existing category in Actual Budget. You can rename the category, move it to a different group, or change its properties.
actual_category_groups_createwriteCreate a new category group in Actual Budget. Category groups help organize categories into logical sections (e.g.,
actual_category_groups_deletedestructiveDelete a category group from Actual Budget. Note: Categories within the group will be moved to a default group or ungrouped. This operation cannot be undone.
actual_category_groups_getreadList all category groups in Actual Budget. Category groups organize related categories together (e.g.,
actual_category_groups_updatewriteUpdate an existing category group in Actual Budget. You can rename the group, change whether it
actual_entities_searchreadFind accounts, categories, or payees by a name pattern. Use this to resolve a partial or mistyped name to its entity (the fix for
actual_get_contextreadRead the budget structure and entity UUIDs (accounts, category groups with nested categories, and payees) in a single call.
actual_get_id_by_namereadResolve an entity name to its UUID. Looks up the UUID for any Account, Payee, Category, or Schedule by their display name. This is useful when you know the human-readable name but need the ID for other API calls. Allowed types:
actual_notes_getreadGet the note attached to an entity in Actual Budget.
actual_notes_updatedestructiveSet or clear the note attached to an entity in Actual Budget.
actual_payee_rules_getreadGet all payee rules associated with a specific payee. Returns PayeeRule objects that show how transactions with this payee are automatically processed (conditions and actions).
actual_payees_common_listreadReturn the most frequently used payees from recent transaction history (last ~12 weeks, top 10,
actual_payees_createwriteCreate a new payee in Actual Budget
actual_payees_deletedestructiveDelete a payee from Actual Budget. Transactions using this payee will have it removed. This
actual_payees_getreadList all payees in Actual Budget. Payees represent merchants, service providers, individuals, or other entities you transact with. Returns payee ID, name, and optional transfer account information for internal transfers.
actual_payees_mergewriteMerge one or more payees into a target payee. This consolidates duplicate payees by merging
actual_preferences_getreadRead the budget\
actual_query_runwriteRun a read-only SQL query against the budget data. Prefer SQL; a bare table name (e.g.
actual_rules_createwriteCreate a budget rule. ${CONDITION_OPERATORS_HELP} Stage: omit it for the normal stage (recommended), or
actual_rules_create_or_updatewriteCreate a rule, or update the existing rule with the same conditions. Prevents duplicates. A rule matches when it has the same conditions (field, op, value) and conditionsOp, in any order. On a match the rule
actual_rules_deletedestructiveDelete a budget rule from Actual Budget. The rule will no longer be applied to new or
actual_rules_getreadList all budget rules in Actual Budget. Rules automate transaction categorization and other budget operations based on conditions. Each rule has conditions (e.g., payee matches
actual_rules_updatewriteUpdate an existing budget rule by ID. Only provide the fields you want to change; do not repeat the rule ID inside fields. ${CONDITION_OPERATORS_HELP} Stage: omit it to leave the rule where it is, pass null for the normal stage, or
actual_schedules_createwriteCreate a schedule, one-off (YYYY-MM-DD date) or recurring (RecurConfig object: frequency and start, optional endMode, monthly patterns such as the last day or the second Monday). Amounts are in cents, negative for expenses.
actual_schedules_deletedestructivePermanently delete a schedule from Actual Budget. The schedule
actual_schedules_getreadList all schedules in Actual Budget. Schedules automate recurring transactions (e.g. monthly rent, weekly grocery runs). Each schedule has a date rule (one-off or RecurConfig), optional payee/account/amount, and a next_date field showing when it fires next.
actual_schedules_updatewriteUpdate a schedule; supply only the fields to change. A new date replaces the stored recurrence, patterns included. Set resetNextDate: true when changing the date or recurrence.
actual_server_get_versionreadGet the version of the Actual Budget server. Returns the version string of the connected Actual Budget server instance. This is the self-hosted Actual Budget server version, not the MCP server version. Use
actual_server_inforeadGet MCP server version and system information. Returns: - Server version - Server name - Node.js version - MCP SDK version - Actual Budget API version - Total tools available - Uptime Use this to check server status, verify version compatibility, or debug issues.
actual_session_closereadClose one of your idle MCP sessions to free up connection slots. Useful when you get
actual_session_listreadList your active MCP sessions with their activity status. Useful for diagnosing connection issues or seeing which sessions can be closed. The pool totals cover every session; the list shows only sessions you opened.
actual_tags_createwriteCreate a new tag in Actual Budget. The
actual_tags_deletedestructiveDelete a tag from Actual Budget by its UUID.
actual_tags_listreadList all tags defined in Actual Budget. Tags are stored without a leading
actual_tags_updatewriteUpdate an existing tag in Actual Budget. At least one of tag/color/description must be provided.
actual_test_badreadb
actual_test_doreadDo a thing
actual_test_metareadm
actual_test_optreado
actual_test_sumreadsum
actual_test_throwreadt
actual_transactions_createwriteCreate a new transaction in Actual Budget. Amount should be in cents (negative for expenses, positive for income).
actual_transactions_deletedestructiveDelete a transaction from Actual Budget by its ID.
actual_transactions_filterreadGet transactions with advanced filtering. Supports filtering by amount range, category, payee, notes, and status. Returns filtered transactions matching all specified criteria.
actual_transactions_getreadGet all transactions for a specific account within a date range. Returns transaction details including date, amount (cents), payee, category, notes, and cleared status. Dates in YYYY-MM-DD format. Perfect for account reconciliation and spending analysis.
actual_transactions_importwriteBulk import transactions with automatic reconciliation and duplicate detection. Matches against existing transactions using imported_id to prevent duplicates. Ideal for importing bank statements, CSV files, or syncing from external sources. Automatically applies budget rules.
actual_transactions_mergewriteMerge two transactions (e.g. a bank-imported duplicate and a manual entry). Same account and same amount required; split children cannot be merged.
actual_transactions_search_by_categoryreadSearch transactions by category name. Returns all transactions in a specific category with optional date range, account, and amount filters. Perfect for analyzing spending in budget categories.
actual_transactions_search_by_monthreadSearch transactions for a specific month. Returns all transactions matching the month and optional filters (account, category, payee, amount range). Efficiently queries by date range.
actual_transactions_search_by_payeereadSearch transactions by payee name. Returns all transactions for a specific payee with optional date range, category, and amount filters. Useful for analyzing spending patterns with specific vendors or service providers.
actual_transactions_summary_by_categoryreadGet spending summary grouped by category using ActualQL aggregation. Returns total amount and transaction count per category for a date range. Perfect for budget analysis and expense tracking. By default excludes income categories (set includeIncome=true to include them).
actual_transactions_summary_by_payeereadGet spending summary grouped by payee using ActualQL aggregation. Returns total amount and transaction count per payee for a date range. Useful for identifying top vendors and analyzing merchant spending patterns. Results are ordered by total amount (highest first).
actual_transactions_updatewriteUpdate an existing transaction in Actual Budget. Provide the transaction ID and the fields you want to update.
actual_transfers_createwriteCreate a paired transfer between two accounts — a debit on the source account and a credit
math.addwriteAdd two numbers
search.docsreadSearch a small demo document store
showLargeTransactionsreadShow recent transactions over a specified amount
testreadtest
04

Trust audit

BLOCKgrade D · trust 68/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryWARN
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (7 observation(s))
Network
declared (9 observation(s))
Shell
declared (1 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
scripts/diag-270-http.mjs:21
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // local self-signed bearer cert on :3601
Why it matters. certificate verification is disabled
Fix. leave verification on
MEDIUMInventory / provenance · inv.binary · CWE-1104
test-data/2026-01-08-Test Budget.zip
2026-01-08-Test Budget.zip
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/server/httpServer.ts:923
logger.info(`🔒 OIDC authentication enabled (JWT Bearer token required; issuer: ${config.OIDC_ISSUER})`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/server/httpServer.ts:932
logger.info(`🔒 HTTP authentication enabled (static Bearer token required)`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
docker-compose.yaml:45
#   http://192.168.1.50:5006       - Actual Budget on another machine on your network
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
docker-compose.yaml:142
# Examples: http://localhost:5006, http://192.168.1.50:5006, https://actual.yourdomain.com
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/unit/budget_acl_enforcement.test.js:466
password: 'pwd-secret-DO-NOT-LEAK',
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/unit/zod_error_format.test.js:107
const secret = 'SUPER_SECRET_VALUE_12345';
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
actual_account_groups_delete, actual_accounts_delete, actual_budgets_resetHold, actual_categories_delete, actual_category_groups_delete, actual_notes_update, actual_payees_delete, actual_rules_delete,
Why it matters. 11 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.binary · CWE-1104
tests/unit/budgets_export.test.js
budgets_export.test.js
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.hidden_file · CWE-1104
.leak-guard-allow
.leak-guard-allow
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInformation disclosure · disclose.log_secret · CWE-209, CWE-532
tests/unit/logger_redaction.test.js:101
logger.info('inbound', { headers: { authorization: 'Bearer abc.def' }, password: 'topsecretpw', note: 'LIVE-SECRET-TOKEN-XYZ123 here', accountId: 'a1' });
LOWInformation disclosure · disclose.log_secret · CWE-209, CWE-532
tests/unit/oidc_token_source.test.js:107
console.log(`\n[oidc-token-source] Results: ${passed} passed, ${failed} failed`);
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/lib/actual-adapter.ts:1
import type { components } from '../../generated/actual-client/types.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/lib/actual-adapter/auth-retry.ts:10
import logger from '../../logger.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/lib/actual-adapter/normalize.ts:7
import type { components } from '../../../generated/actual-client/types.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/lib/toolFactory.ts:17
import type { ToolDefinition } from '../../types/tool.d.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/resources/accountsSummary.ts:5
import type { components } from '../../generated/actual-client/types.js';
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:88
#   http://192.168.1.50:5006       (if it runs on another machine on your network)
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/guides/DEPLOYMENT.md:77
#   http://192.168.1.50:5006       - Actual Budget on another machine on your network
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/unit/entrypoint_invariants.test.js:119
ACTUAL_SERVER_URL: 'http://127.0.0.1:5999',
LOWNetwork egress · net.tls_off · CWE-200, CWE-319
scripts/deploy-and-test.sh:236
NODE_TLS_REJECT_UNAUTHORIZED=0 \
Why it matters. certificate verification is disabled
Fix. leave verification on
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@actual-app/api, @modelcontextprotocol/sdk, debug, dotenv, express, fuse.js, jose, mcp-auth
Why it matters. 19 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
README.md:198
2. Fill in **Actual server URL**, **Actual server password**, and **Actual server Sync ID** (the Sync ID is in Actual Budget: open the budget, **Settings, Show advanced settings, Sync ID**).
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
docs/SECURITY_AND_PRIVACY.md:450
**Contents**: a map from `sha256(principal)` to a budget sync id. It lets a re-initialized session (after a server restart) restore the user's last active budget.
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha 582fab680352full audit observations/trust-audit/mcp-server/agigante80__actual-mcp-server.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-12582fab680352BLOCKD68first audit
06

Questions

What is the actual-mcp-server MCP server?

Talk to your self-hosted Actual Budget from any MCP client: a remote HTTP server for LibreChat/LobeChat or a local stdio process for Claude Desktop, with 71 tools for transactions, budgets, rules, and bank sync. No Docker needed for local use.

What tools does actual-mcp-server expose?

85 in total: 46 read-only, 28 that write, and 11 that can delete or overwrite (actual_account_groups_delete, actual_accounts_delete, actual_budgets_resetHold, actual_categories_delete, actual_category_groups_delete). Every one is listed on this page with its risk.

Is actual-mcp-server safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (68/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 11 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does actual-mcp-server need?

It reads ACTUAL_BUDGET_PASSWORD, ACTUAL_PASSWORD, AUTH_BUDGET_ACL_SOURCE, AUTH_PROVIDER, BUDGET_1_PASSWORD, BUDGET_2_PASSWORD, BUDGET_3_PASSWORD, GH_TOKEN, MCP_ALLOW_UNAUTHENTICATED, MCP_AUTH_TOKEN, MCP_HTTPS_KEY and MCP_SSE_AUTHORIZATION from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does actual-mcp-server run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as actual-mcp-server at 0.22.31.

How current is this page?

The grade is for one exact copy of the source (582fab680352), read on 2026-10-12. The repository is watched and re-audited when it changes.

Advertisement