Native Android budget tracker built with Kotlin, Jetpack Compose, and Supabase.
Track accounts, transactions, categories, recurring items, reminders, and monthly activity from a single personal finance app.
- Email/password and Google sign-in
- Debit, credit, and loan accounts
- Income, expense, and transfer transactions
- Categories and subcategories
- Calendar-based monthly activity view
- Recurring income, expenses, and transfers
- Reminder notifications with boot rescheduling
- Settings for currency, dark mode, month start day, and notification time
- Optional local MCP server for assistant-driven account and transaction tools
| Area | Choice |
|---|---|
| Language | Kotlin 2.3.0, JVM 17 |
| UI | Jetpack Compose, Material 3 |
| Architecture | MVVM, single-activity app |
| DI | Hilt |
| Backend | Supabase Auth, PostgREST, Realtime |
| Local prefs | DataStore Preferences |
| Background work | WorkManager |
| MCP server | TypeScript, @modelcontextprotocol/sdk, Supabase JS |
- App version:
1.0.0 - Version code:
1 - Min SDK: 26
- Target/Compile SDK: 36
- Application ID:
com.minley.budget
Create local.properties at the repo root:
sdk.dir=C:\\Users\\you\\AppData\\Local\\Android\\Sdk
minley.supabase.url=https://your-project-ref.supabase.co
minley.supabase.publishableKey=your-publishable-key
minley.google.clientId=your-google-oauth-web-client-id.apps.googleusercontent.comYou can copy local.properties.example as a starting point.
Build and install:
./gradlew assembleDebug
./gradlew installDebugOr open the project in Android Studio and run the app configuration.
Supabase is the source of truth for persistent app data. This repo intentionally does not publish the full database schema.
Before pointing the app at a Supabase project, verify:
- RLS is enabled on all user-owned tables.
- User-owned rows are restricted to the signed-in user.
- Client-callable RPCs cannot read or mutate another user's data.
- No
service_role, secret key, database password, or private key is shipped in the app.
The checked-in app uses local.properties values at build time and expects a publishable Supabase key only.
The optional local MCP server lives in mcp-server/. It can:
- List accounts
- Show balances
- List recent transactions
- Create transactions
- Create reminders
- Summarize monthly activity
Run it locally:
cd mcp-server
npm install
Copy-Item .env.example .env
npm run buildFill mcp-server/.env with your own Supabase project and account credentials. The .env, node_modules/, and dist/ files are intentionally ignored.
For direct Supabase MCP access in Codex or another MCP-capable assistant, create a local .mcp.json:
{
"mcpServers": {
"supabase": {
"type": "http",
"url": "https://mcp.supabase.com/mcp?project_ref=your-project-ref"
}
}
}Do not commit .mcp.json; it is local machine configuration.
app/src/main/java/com/minley/budget/
├── core/ # auth, DI, navigation, networking, notifications, theme, utilities
├── data/ # serializable models and Supabase-backed repositories
└── features/ # accounts, auth, calendar, categories, recurring, reminders, settings, transactions
mcp-server/
├── src/index.ts # local MCP tools
└── README.md # MCP setup
./gradlew testDebugUnitTest lintDebug assembleDebug
cd mcp-server && npm run checkCurrent note: Gradle unit tests are configured, but there are no unit test source files yet.
- Runtime credentials stay in local files.
local.properties,.mcp.json,mcp-server/.env, build outputs, and dependency folders are gitignored.- The full database schema is not published in this repo.
- See
SECURITY.mdfor the short security policy.
MIT. See LICENSE.
See AGENTS.md for repo-specific assistant notes.

