ynab-mcp-server
by lukendatigh
README.md
# ynab-mcp-server
A complete, open-source single tenant [MCP](https://modelcontextprotocol.io) server for the full [YNAB](https://www.ynab.com) v1 API. Every endpoint in YNAB's [OpenAPI spec](https://api.ynab.com/papi/open_api_spec.yaml) is reachable through one of the tools below -- including payee locations, category groups, user info, plan settings, and account creation, which most other YNAB MCP servers skip.
Runs two ways:
- **Locally over stdio** -- for Claude Desktop / Claude Code, zero hosting required.
- **Remotely over HTTP** -- for [claude.ai](https://claude.ai) / Cowork connectors, deployable to Fly.io with the included Dockerfile.
View the full product and technical design [here](PRD).
## Tools
23 tools cover all 30 YNAB endpoint paths (several endpoints are consolidated behind one tool via a `view`/`action` parameter to avoid near-duplicate tools). Full list with exact endpoint coverage: [docs/tools.md](docs/tools.md).
| Read | Write |
|---|---|
| `get_user` | `create_account` |
| `list_plans`, `get_plan`, `get_plan_settings` | `create_category`, `update_category` |
| `get_budget` | `modify_budget` |
| `list_accounts`, `get_account` | `create_category_group`, `update_category_group` |
| `list_category_groups`, `get_category_group` | `create_payee`, `update_payee` |
| `get_transactions` | `modify_transactions` |
| `list_payees` | `modify_scheduled_transactions` |
| `list_payee_locations`, `get_payee_location` | |
## Quick start (local, stdio)
Requires Node.js 20+. Grab a [YNAB personal access token](https://app.ynab.com/settings/developer) first.
```bash
npx ynab-mcp-server
```
Point your MCP client (Claude Desktop, Claude Code, etc.) at it. For Claude Desktop, add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"ynab": {
"command": "npx",
"args": ["ynab-mcp-server"],
"env": {
"YNAB_ACCESS_TOKEN": "your-token-here",
"YNAB_READ_ONLY": "false"
}
}
}
}
```
## Configuration
| Env var | Required | Default | Description |
|---|---|---|---|
| `YNAB_ACCESS_TOKEN` | yes | -- | Your YNAB personal access token. Never logged, never echoed in tool output. |
| `YNAB_READ_ONLY` | no | `false` | When `true`, every mutation tool is hidden from `tools/list` entirely. Recommended for any instance you don't fully trust the client of. |
| `YNAB_API_BASE_URL` | no | `https://api.ynab.com/v1` | Override for testing against a mock server. |
HTTP mode (below) needs three more: `PORT`, `PUBLIC_URL`, `MCP_HTTP_PASSWORD`. See [.env.example](.env.example) for all of them with descriptions.
## Remote (HTTP) deployment on Fly.io
The HTTP transport is gated by OAuth (required for claude.ai/Cowork connector approval). This is **single-tenant OAuth**: there's no concept of separate user accounts, it just gates access to *your* instance behind one shared password. See [docs/architecture.md](docs/architecture.md#oauth) for why and how.
1. Install [flyctl](https://fly.io/docs/flyctl/install/) and `fly auth login`.
2. `fly launch --no-deploy` from this directory (it will read `fly.toml`; rename the `app` there first if you want a specific subdomain).
3. Set secrets (never put these in `fly.toml`, which is committed to git):
```bash
fly secrets set YNAB_ACCESS_TOKEN=your-token-here
fly secrets set MCP_HTTP_PASSWORD=choose-a-strong-password
```
4. Edit `fly.toml`'s `PUBLIC_URL` to match your actual `*.fly.dev` hostname (or custom domain), then:
```bash
fly deploy
```
5. In claude.ai / Cowork, add a custom connector pointing at `https://<your-app>.fly.dev/mcp`. You'll be redirected to a login page on your own instance -- enter `MCP_HTTP_PASSWORD` to approve the connection.
Notes:
- Single `shared-cpu-1x` machine, no volume. OAuth session state (registered clients, tokens) lives in memory and is lost on redeploy or restart -- you'll just need to reconnect the connector afterwards. Acceptable trade-off for a low-traffic personal instance; see the TDD.
- `fly.toml`'s `[http_service]` is configured to stay always-on (not scaled to zero) for exactly that reason -- a stop/start cycle would otherwise force reconnection too.
## Development
```bash
npm install
npm run dev:stdio # run src/stdio.ts directly with tsx
npm run dev:http # run src/http.ts directly with tsx
npm run typecheck
npm run lint # biome check
npm run lint:fix
npm test
npm run build # bundles dist/stdio.js and dist/http.js with tsup
```
See [docs/architecture.md](docs/architecture.md) for the repo layout and request-flow details.
## License
MIT -- see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues