Skip to main content
Glama
Saifalkayali

YNAB MCP Starter

by Saifalkayali
README.md
# YNAB MCP Starter

Production-style TypeScript starter repo for a read-only YNAB MCP server.

This starter is intentionally small and explicit:

- Node.js 18+
- TypeScript with strict compiler settings
- Zod-validated tool inputs and outputs
- Read-only YNAB API client with retries and timeout handling
- Unit tests with mocked YNAB responses
- Clear TODO markers where MCP transport wiring should be connected

## What This Repo Includes

```text
src/
  clients/   YNAB API client, environment config, and error types
  schemas/   strict Zod schemas for tool contracts
  server/    MCP server composition and transport TODO placeholders
  tools/     read-only business logic for each YNAB capability
  types/     shared API and service types
tests/       unit tests with mocked API responses
```

Implemented read-only capabilities:

- list budgets
- list accounts
- list categories
- list recent transactions
- find uncategorized transactions
- monthly spend by category

Write access is intentionally not implemented.

## Setup

1. Install dependencies:

```bash
npm install
```

2. Copy the example environment file:

```bash
cp .env.example .env
```

3. Set your YNAB token in `.env`:

```env
YNAB_TOKEN=your-token-here
```

4. Run local development mode:

```bash
npm run dev
```

## Scripts

- `npm run build` compiles TypeScript into `dist/`
- `npm run dev` runs the starter entrypoint with file watching
- `npm run lint` runs ESLint
- `npm run test` runs unit tests with Vitest
- `npm run typecheck` runs TypeScript in no-emit mode

## MCP Wiring

The repo includes the server composition layer, but it does not lock you into one transport yet.

Look for `TODO` comments in:

- [src/server/index.ts](/Users/saifalkayali/Documents/tech/gcp-terraform-web-app/src/server/index.ts)
- [src/server/registerTools.ts](/Users/saifalkayali/Documents/tech/gcp-terraform-web-app/src/server/registerTools.ts)

That is where you should:

1. Instantiate the MCP server
2. Register tool definitions and schemas
3. Connect stdio, SSE, or another transport
4. Add structured logging and operational hooks

## Security Notes

- This starter expects a `YNAB_TOKEN` personal access token in environment variables.
- Never hardcode the token in source files, tests, prompts, or logs.
- Keep the token scoped to read-only operational use and rotate it if it is exposed.
- Avoid logging raw YNAB API responses in production because they may contain transaction memos or other sensitive financial metadata.
- This starter only performs `GET` requests to the YNAB API. No write endpoints are implemented.

## Design Notes

- The YNAB client centralizes retries, timeout handling, and error normalization.
- Tool modules are isolated from HTTP details and operate on a small service interface.
- Zod schemas validate both tool inputs and tool outputs to catch drift early.
- Money amounts are exposed in both YNAB milliunits and human-friendly decimal amounts.
- Monthly category spend only counts outflows for the requested month.

## Example Prompts

- "List my YNAB budgets."
- "Show the accounts in budget `budget-id-123`."
- "List categories for budget `budget-id-123`."
- "Show the most recent 20 transactions in budget `budget-id-123`."
- "Find uncategorized transactions in budget `budget-id-123` since `2026-04-01`."
- "Summarize monthly spend by category for budget `budget-id-123` in `2026-04`."

## Testing

The tests mock YNAB API responses so you can validate behavior without a live token:

```bash
npm run test
```

## Production Hardening Ideas

- Add request correlation IDs and structured logs
- Add metrics around retries, rate limiting, and latency
- Add integration tests against a mocked HTTP layer
- Add result pagination controls if your MCP client expects larger result sets
- Add a secrets manager integration instead of local `.env` files for deployment