The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Expense Budget Tracker listing page.
Self-hosted open-source expense and budget tracker with balances, transfers, and multi-currency reporting on Postgres.
![]()
Live demo: expense-budget-tracker.com
Open http://localhost:3000.
This local stack is unauthenticated and published on loopback only. To change any of it, copy infra/docker/.env.example to infra/docker/.env: the shell environment and that file both outrank the development defaults in infra/docker/compose.yml. AUTH_MODE=cognito is not a supported configuration of this stack: the web service wires DATABASE_URL, not the DB_HOST/DB_PASSWORD pair that mode requires. The authenticated deployment lives in AWS, which deploys from infra/aws and never reads the compose file. Details in docs/deployment.md.
Connect through either the hosted MCP server or the direct Agent API. Their credentials are separate and are not interchangeable: MCP uses OAuth Bearer access, while the Agent API uses an ApiKey.
The hosted MCP server is available directly at https://mcp.expense-budget-tracker.com/mcp. Its canonical MCP Registry identity is com.expense-budget-tracker/expense-budget-tracker; it is published there, and each later version becomes available only after its own manual publication workflow succeeds and exact-version verification completes. It exposes five OAuth-secured tools:
list_workspaces — list workspaces available to the signed-in userget_schema — inspect the allowed relations, columns, constraints, and limitsget_guide — fetch the SQL-dialect, writing-data, or query-recipes protocol before actingsql_query — run one restricted SELECT or WITH...SELECTsql_execute — run one approved INSERT, UPDATE, or DELETECompatible remote MCP clients authenticate with OAuth authorization code + PKCE and Dynamic Client Registration. The required expenses:read scope enables the four read tools; a client may also request expenses:write, which is required for sql_execute.
Start at GET https://api.expense-budget-tracker.com/v1/. The discovery response tells agents to ask for the user's email first, and the same email OTP flow covers both signup and login.
GET https://api.expense-budget-tracker.com/v1/ in your agent — it will discover the OTP onboarding flow automaticallyApiKeyFor readonly work, agents send one SELECT or WITH...SELECT statement to the primary query endpoint:
For an explicitly approved write, agents send one INSERT, UPDATE, or DELETE statement to the primary execute endpoint:
After POST /v1/workspaces/{workspaceId}/select, the API key remembers that workspace, so X-Workspace-Id becomes optional on later /v1/sql/query, /v1/sql/execute, and compatibility /v1/sql calls; send the header to override the saved selection. If the user has exactly one workspace and no saved selection yet, the API auto-saves and uses that single workspace. POST /v1/sql remains available only for compatibility when an atomic multi-statement script is required.
Deployment — local Docker Compose and AWS CDK setup
Self-hosting — run the whole product outside AWS from one compose stack behind an edge proxy
AWS deployment — full AWS CDK guide
Architecture — system overview, data model, multi-currency design
For full privacy, self-host on your own AWS account. If you deploy or use the hosted service with the AWS/CDK setup described in infra/aws/README.md, the LLM chat runtime stores transcript state in Postgres. That means chat data is available to:
If you use chat to import bank statements, screenshots, PDFs, CSVs, or other financial files, data extracted from those files can also reach OpenAI and Langfuse as part of chat processing and tracing. If you do not trust even one of these parties, do not store your financial data in this hosted deployment.
The code is already deployed, and the maintainer stores his own real finances there. Only maintainer Kirill Markin has access to the demo database. For partial privacy, sign up with an email that doesn't contain your real name. Try the demo →