# Happydebits — for agents > Local-first recurring burn ledger. Humans and agents share one ledger: agents propose schema-valid changes; humans confirm before anything writes. Happydebits shows the real annual cost of recurring charges. Paste a statement or add charges by hand — no bank login. Data stays on the device. Optional MCP pairing lets Cursor/Claude read a short-lived snapshot and park proposals. ## Start here - Full agent guide: [/agent.md](https://happydebits.com/agent.md) (or `/agent.md` on this host) - Complete contract dump: [/llms-full.txt](https://happydebits.com/llms-full.txt) - Action proposal schema: [/ledger-action.schema.json](https://happydebits.com/ledger-action.schema.json) - Ledger export schema: [/ledger.schema.json](https://happydebits.com/ledger.schema.json) - Pair + MCP: open [/agents](https://happydebits.com/agents/) in the browser, Start pairing, paste MCP JSON into Cursor/Claude ## Human pages - Home (empty ledger / yearly burn): [/](https://happydebits.com/) - Import charges: [/import/](https://happydebits.com/import/) - Agents / MCP pairing: [/agents/](https://happydebits.com/agents/) - Pro billing: [/billing/](https://happydebits.com/billing/) ## Rules 1. Never rewrite the full ledger. Return a version-1 action proposal only. 2. Never claim changes were applied. Park proposals; the human confirms in UI. 3. Prefer `set_status: cancelled` over `delete` unless the user explicitly asks to delete. 4. If ambiguous, return no risky action and one `clarifyingQuestion`. 5. Use exact subscription ids from `get_ledger` / `list_charges` when updating. ## MCP tools - `get_ledger` — read paired snapshot - `list_charges` — filter charges - `propose_actions` — park proposal (idempotent via `clientRequestId`) - `get_proposal` — list proposal status ## HTTP pair API All JSON responses use `{ ok: true, ... }` or `{ ok: false, code, message, hint, retryable }`. Pairing returns **two secrets**: - `agentSecret` — MCP/HTTP (read + propose only) - `deviceSecret` — browser only (sync ledger, confirm/dismiss, end pair) - `POST /api/agent/pair` → `{ pairId, agentSecret, deviceSecret, expiresAt }` (rate-limited) - `PUT /api/agent/pair/:id/ledger` (Bearer **deviceSecret**) — browser syncs ledger - `GET /api/agent/pair/:id/ledger` (Bearer agent or device) - `POST /api/agent/pair/:id/proposal` (Bearer agent or device) body `{ proposal, clientRequestId? }` - `GET /api/agent/pair/:id/proposal?status=pending` - `PATCH /api/agent/pair/:id/proposal` (Bearer **deviceSecret**) body `{ proposalId, status: confirmed|dismissed }` - `DELETE /api/agent/pair/:id` (Bearer **deviceSecret**) — end session MCP env `HAPPYDEBITS_PAIR_SECRET` must be the **agentSecret**.