caton mcp
by cesarzea
README.md
# Catón AI
[](https://github.com/cesarzea/caton-ai/actions/workflows/ci.yml)
[](https://github.com/cesarzea/caton-ai/actions/workflows/codeql.yml)
[](https://scorecard.dev/viewer/?uri=github.com/cesarzea/caton-ai)
[](LICENSE)
**A local-first, plugin-based financial watchdog for individuals and small businesses.**
Catón AI connects to where your money actually goes — bank accounts, cards and the usage APIs of
the services you pay for — keeps everything on your own machine, and lets plugins and AI agents
watch it for you: budgets, goals, cash-flow forecasts, and alerts such as _"tell me when my
Anthropic spend goes over $20"_.
> **Status: pre-alpha.** A first command-line version syncs European bank accounts through
> Enable Banking into a local ledger, reports monthly outflows and serves the ledger read-only to AI
> assistants over MCP. Plugins, agents, alerts and the web UI are not built yet.
## Why the name
Cato the Elder was the Roman censor famous for his austerity and for reprimanding waste. Catón AI
plays the same role for your finances: it keeps watch, and it tells you when something is off.
## Principles
- **Local-first and private.** Data and credentials stay on your machine. No telemetry.
- **Minimal core, everything else is a plugin.** Data sources, budgets, goals and watchdog agents
are plugins, including the official ones.
- **Permissions, not trust.** Plugins declare what they can read, write and whether they may use
the network; nothing gets network access by default.
- **Reviewed before activation.** Plugins are checked automatically — including an AI-assisted
security and functionality review — before they touch your data.
## Documentation
- [Architecture (arc42 + C4)](docs/architecture/README.md)
- [Architecture Decision Records](docs/adr/README.md)
## Engineering standards
Enforced standards run through `npm run check` locally and in CI on every pull request; `main`
cannot change unless they all pass. Each gate was verified to fail on a deliberate violation when
it was introduced.
**Architecture and code**
| Standard | Status |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| Architecture documented with [arc42](https://arc42.org) and [C4](https://c4model.com); decisions recorded as [MADR](https://adr.github.io/madr/) [architecture decision records](docs/adr/README.md) | Adopted |
| Module boundaries checked by [dependency-cruiser](https://github.com/sverweij/dependency-cruiser): public entry points only, no cycles, no undeclared or development dependencies in production code | Enforced |
| TypeScript [`@tsconfig/strictest`](https://github.com/tsconfig/bases); `any` forbidden | Enforced |
| [typescript-eslint](https://typescript-eslint.io) `strict-type-checked` + `stylistic-type-checked`, SonarJS cognitive complexity | Enforced |
| Tests with [Vitest](https://vitest.dev) and ≥ 90 % coverage | Enforced |
| Small units: files ≤ 150 lines, functions ≤ 30 lines, cyclomatic complexity ≤ 8 | Enforced |
| Dead-code detection with [knip](https://knip.dev): no unused files, exports or dependencies | Enforced |
| [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html) conventions (named exports only); Prettier formatting | Enforced |
**Security and supply chain**
| Standard | Status |
| ----------------------------------------------------------------------------------------- | -------- |
| [OpenSSF Scorecard](https://scorecard.dev) published on every change to `main` | Enforced |
| [CodeQL](https://codeql.github.com) `security-and-quality` analysis on every pull request | Enforced |
| GitHub Actions pinned by commit SHA, least-privilege workflow tokens | Enforced |
| Secret scanning with push protection; private vulnerability reporting | Enforced |
| Automated dependency updates with Dependabot | Enforced |
**Process**
| Standard | Status |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| Protected `main`: pull requests only, required checks (Node.js 24 and 26, CodeQL, PR title), linear history, squash merges | Enforced |
| Code review following [Google's engineering practices](https://google.github.io/eng-practices/review/), with a definition of done in [CONTRIBUTING](CONTRIBUTING.md) | Adopted |
| [Conventional Commits](https://www.conventionalcommits.org) for every commit on `main` | Enforced |
**Planned**
| Standard | Status |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| [OWASP Top 10 for LLM Applications 2025](https://genai.owasp.org/llm-top-10/) mapping and threat model | Planned |
| [OpenSSF Best Practices](https://www.bestpractices.dev) badge | Planned |
| Signed releases with SLSA provenance and SBOM | Planned |
| [OWASP ASVS 5.0](https://owasp.org/www-project-application-security-verification-standard/) level 2, before offering the product to businesses | Planned |
| Mutation testing of the accounting domain | Planned |
## Getting started
Requires Node.js 24 LTS or newer and an [Enable Banking](https://enablebanking.com) application
in restricted mode with your own accounts linked and authorised (one session per bank).
Create `~/.config/caton-ai/config.json`, readable only by you (`chmod 600`). Each entry is an
**instance** of a plugin; its secret variables are never written here:
```json
{
"instances": [
{
"id": "mybank",
"title": "My bank",
"plugin": "enable-banking",
"settings": {"app-id": "<application id>", "session-id": "<authorised session id>"}
}
]
}
```
Secrets go in an encrypted store ([ADR 0017](docs/adr/0017-secret-store.md)) as
`plugin:instance:variable`, here `enable-banking:mybank:private-key`. One secret can serve several
instances: save it under a name of your choice and enter `${that-name}` as their value
([ADR 0019](docs/adr/0019-plugin-variables-instances-and-shared-secrets.md)). The web interface
lists every secret an instance needs, with what it is and where to get it:
```sh
npm run build # builds the web interface once
npm start -- serve # prints a one-time link to http://127.0.0.1:7170
```
See [ADR 0018](docs/adr/0018-local-web-interface.md) for how it is protected. A configuration in
the first format (`plugins` and `connections`) is converted with `npm start -- config migrate`.
```sh
npm ci --ignore-scripts
npm start -- sync # fetch accounts, movements and balances into the local ledger
npm start -- accounts # accounts and latest balances
npm start -- spend 3 # money leaving your accounts per month, last 3 months (cash basis)
npm start -- status # last sync of every connection
```
Outflows still include transfers between your own accounts; transfer detection and
categorisation are next. Unattended PSD2 access allows only a few requests per account per day
(the exact quota is still to be verified), so sync at most once or twice a day. Current limitations are tracked in [ADR 0012](docs/adr/0012-interim-local-secrets-and-ledger-storage.md).
## Ask your AI assistant (MCP)
`caton mcp` serves the ledger **read-only** over the
[Model Context Protocol](https://modelcontextprotocol.io) (specification 2026-07-28; hosts still on
2025-era versions are served too). It never contacts a bank, amounts are exact decimals, and every
answer says whether the figures are complete. See [ADR 0013](docs/adr/0013-read-only-mcp-server.md).
| Tool | What it answers |
| -------------------- | ----------------------------------------------------------------------- |
| `sync_status` | When each bank connection last synced, and why it failed |
| `list_accounts` | Accounts and their latest balances |
| `list_transactions` | Movements by date, account, direction or text, one page at a time |
| `monthly_outflows` | Money that left the accounts per month (includes own-account transfers) |
| `top_counterparties` | Who received the most money |
Register it in your MCP host with absolute paths; the host must start Node.js 24 or newer, which
may not be the `node` on its `PATH`. For Claude Code:
```sh
claude mcp add caton-ai -- /path/to/node24/bin/node /path/to/caton-ai/packages/cli/src/main.ts mcp
```
For hosts configured with JSON, such as Claude Desktop:
```json
{
"mcpServers": {
"caton-ai": {
"command": "/path/to/node24/bin/node",
"args": ["/path/to/caton-ai/packages/cli/src/main.ts", "mcp"]
}
}
}
```
Account names, descriptions and counterparties come from banks and third parties; the server
tells the assistant to treat them as data, never as instructions. With a hosted model, what the
tools return is sent to its provider.
## Development
Requires Node.js 24 LTS or newer.
```sh
npm ci --ignore-scripts
npm run check # types, lint, format, architecture rules, dead code, web build, tests + coverage
```
See [CONTRIBUTING.md](CONTRIBUTING.md) for the quality gates and conventions.
## Security
Please report vulnerabilities privately as described in [SECURITY.md](SECURITY.md).
## License
[MIT](LICENSE) © César Zea
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues