Skip to main content

Unofficial MCP server for the Akahu open-finance API (New Zealand). Personal Apps, read-by-default, write-with-consent.

Project description

nz-akahu-mcp

Unofficial MCP server for the Akahu open-finance API (New Zealand). Bring your own Akahu credentials; run locally over stdio; no hosted backend.

  • 14 tools. Account & balance reads, settled & pending transaction reads, batch lookup by id, identity read, refresh writes, support-ticket writes, name verification.
  • Read-only by default. Every write tool refuses until AKAHU_READ_ONLY=false.
  • Per-call consent for every write. Each write calls ctx.elicit() for confirmation in the client.
  • Personal Apps only. App-scoped endpoints, payments, and webhooks are not exposed.

Prerequisites

  1. Akahu Personal App + User token - register at https://my.akahu.nz/developers
  2. uv for the uvx runner (or pip with a virtualenv)
  3. Claude Code or Claude Desktop

The two recommended install paths below (marketplace plugin for Claude Code, .mcpb Desktop Extension for Claude Desktop) prompt for your tokens and store them in your OS keychain. Only the manual paths further down need shell env vars:

export AKAHU_APP_TOKEN="app_token_..."
export AKAHU_USER_TOKEN="user_token_..."
# Optional - everything below is the default:
export AKAHU_READ_ONLY=true
export AKAHU_AUTOMATION_BYPASS=false

Install in Claude Code

Marketplace plugin (recommended)

Tokens prompt at install and are stored in your OS keychain (macOS Keychain on macOS, Windows Credential Manager on Windows). No shell env or .env file required; the package stays unchanged on PyPI.

Claude Code v2.1.83 or later:

/plugin marketplace add severity1/severity1-marketplace
/plugin install nz-akahu-mcp@severity1-marketplace

After install, /mcp should show nz-akahu-mcp connected. See plugin/README.md for the configure / reconfigure / uninstall flow and the full table of prompted values.

Claude Desktop note: the marketplace plugin path does not work in Claude Desktop today - Desktop has no UI to set marketplace-plugin userConfig values (anthropics/claude-code#39827, #39455). Use the Desktop Extension path below.

Manual install

Prefer the marketplace plugin path above. The manual options below exist for users hacking on the server source, pinning a specific git ref, or running in environments without marketplace access. They all require you to manage tokens via shell env vars or --env flags.

Option A: remote install via claude mcp add

Once published to PyPI:

claude mcp add nz-akahu \
  --scope user \
  --env AKAHU_APP_TOKEN=app_token_... \
  --env AKAHU_USER_TOKEN=user_token_... \
  --env AKAHU_READ_ONLY=true \
  -- uvx nz-akahu-mcp

Before a PyPI release, install straight from GitHub:

claude mcp add nz-akahu \
  --scope user \
  --env AKAHU_APP_TOKEN=app_token_... \
  --env AKAHU_USER_TOKEN=user_token_... \
  -- uvx --from git+https://github.com/severity1/nz-akahu-mcp nz-akahu-mcp

Scope options:

  • --scope user - available in every Claude Code project for your user (recommended for personal banking data)
  • --scope project - shared via .mcp.json checked into the repo (don't use this for tokens)
  • --scope local - this project only, not shared (default)

Option B: local install via claude mcp add (clone + dev loop)

If you want to hack on the server:

git clone https://github.com/severity1/nz-akahu-mcp.git
cd nz-akahu-mcp
uv sync --extra dev
uv run pytest         # 151 tests, 100% line + branch coverage

# Wire the local checkout into Claude Code:
claude mcp add nz-akahu \
  --scope user \
  --env AKAHU_APP_TOKEN=app_token_... \
  --env AKAHU_USER_TOKEN=user_token_... \
  -- uv --directory "$(pwd)" run nz-akahu-mcp

Restart your Claude Code session after editing source.

Option C: pip install from PyPI

Install into a virtualenv:

python -m venv ~/.venvs/nz-akahu-mcp
source ~/.venvs/nz-akahu-mcp/bin/activate   # Windows: ~/.venvs/nz-akahu-mcp/Scripts/activate
pip install nz-akahu-mcp

Then point Claude Code at the installed console script (use the absolute path):

claude mcp add nz-akahu \
  --scope user \
  --env AKAHU_APP_TOKEN=app_token_... \
  --env AKAHU_USER_TOKEN=user_token_... \
  -- ~/.venvs/nz-akahu-mcp/bin/nz-akahu-mcp

To upgrade later: ~/.venvs/nz-akahu-mcp/bin/pip install --upgrade nz-akahu-mcp and restart Claude Code.

Verify the install

claude mcp list                # confirms 'nz-akahu' is registered
claude mcp get nz-akahu        # shows the resolved command and env

Inside Claude Code, ask: "What accounts do I have?" - it should call nz-akahu_accounts_list_accounts and return masked account details.

Install in Claude Desktop

Desktop Extension (recommended)

A .mcpb Desktop Extension is attached to every GitHub Release. Claude Desktop auto-generates a settings UI from the bundle's user_config schema and persists tokens to Windows Credential Manager / macOS Keychain.

  1. Download nz-akahu-mcp-X.Y.Z.mcpb from the latest GitHub Release.
  2. Double-click the file to install (or in Claude Desktop: Settings -> Extensions -> Advanced -> Install Extension).
  3. Fill in the prompted values:
    • Akahu User Token and Akahu App Token (sensitive, stored in OS keychain)
    • Read-only mode (default true - leave unless you specifically need write tools)
    • Automation bypass (default false - leave unless you want to skip consent prompts for account refresh)
  4. Enable the extension. Claude Desktop's MCP indicator should list nz-akahu-mcp as connected.

Updates: download the newer .mcpb from the Releases page and reinstall. The bundle pins uvx nz-akahu-mcp so PyPI package updates flow in on next launch regardless.

Manual: claude_desktop_config.json

Prefer the Desktop Extension path above - it auto-generates the settings UI, stores tokens in your OS keychain, and avoids hand-editing JSON. Use this manual path only if you can't install extensions in your environment.

Copy examples/claude_desktop_config.json into your Claude Desktop config and replace the placeholders. The config lives at:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Then restart Claude Desktop.

Run standalone (no client)

# Via uvx (zero-install):
uvx nz-akahu-mcp

# Via pip (after `pip install nz-akahu-mcp` in your venv):
nz-akahu-mcp

# From a local checkout:
uv run nz-akahu-mcp

The server speaks MCP over stdio. Inspect tool calls with:

uv run fastmcp dev src/nz_akahu_mcp/server.py

Architecture

+--- root FastMCP server (server.py) -----------+
| mounts 3 sub-servers, prints safety banner    |
+----+---------------+--------------+-----------+
     |               |              |
   accounts      transactions    identity
     |               |              |
     +----- AkahuClient (httpx + retry) ----+
                          |
                          v
                  https://api.akahu.io/v1
                  (dual-header auth)

Every write tool is decorated with @require_write_consent from safety.py. rg "@require_write_consent" enumerates writes; rg "automatable=True" enumerates the bypass-eligible subset.

Read-only by default

The server starts with AKAHU_READ_ONLY=true. Every write tool refuses with this message:

Write operations are disabled. To enable: set AKAHU_READ_ONLY=false in your .env and restart the MCP server. Each write will require your explicit confirmation through Claude (or set AKAHU_AUTOMATION_BYPASS=true for the automatable subset only).

When writes ARE enabled, every write still calls ctx.elicit() to ask you in Claude's UI before firing.

Automation bypass

Setting AKAHU_AUTOMATION_BYPASS=true together with AKAHU_READ_ONLY=false skips the elicit prompt for tools marked automatable=True:

Tool Bypass-eligible?
accounts/refresh_all_accounts YES
accounts/refresh_account YES
transactions/report_transaction_issue NO
identity/verify_name NO

Each bypassed call logs at INFO with the tool name. The server prints a startup banner listing the bypass-eligible tools.

Setting AKAHU_AUTOMATION_BYPASS=true with AKAHU_READ_ONLY=true is rejected at startup.

Tool reference

Read tools (10)

accounts/

  • list_accounts - all connected accounts (masked, formatted balances)
  • get_account(account_id) - single account details
  • get_account_balance(account_id) - balance only
  • get_pending_transactions(account_id) - not-yet-settled debits/credits for one account

transactions/

  • get_transactions(account_id?, start_date?, end_date?, category?, min_amount?, max_amount?, limit=100)
  • get_transaction(transaction_id)
  • get_transactions_by_ids(ids) - batch fetch by Akahu txn id (useful for webhook follow-up)
  • get_pending_transactions - not-yet-settled across all accounts
  • search_transactions(query, limit=50) - substring across description + merchant.name

identity/

  • get_me

Write tools (4)

  • accounts/refresh_all_accounts (bypass-eligible)
  • accounts/refresh_account(account_id) (bypass-eligible)
  • transactions/report_transaction_issue(transaction_id, issue_type, fields?, comment?, other_transaction_id?) (always elicits)
  • identity/verify_name(family_name, given_name?, middle_name?, initials?, account_id?) (always elicits) - requires Personal-App scope grant; without it Akahu returns 403

Privacy & security

  • Account numbers are masked: 01-1234-1234567-00 -> 01-****-***4567-00.
  • Tokens are never logged. The DEBUG-level body log is response-only.
  • All filters are applied client-side after the API call returns. Akahu has no field-level access control for Personal Apps.
  • The server runs entirely on your machine. The only outbound traffic is to https://api.akahu.io/v1.

Personal Apps only

This server uses the Akahu Personal App model (per-user OAuth). The following endpoints are not exposed because they are app-scoped and unreachable from a Personal App:

  • /categories - NZFCC category taxonomy (transactions carry their category inline)
  • /connections - supported-bank list
  • /identity/{id}/verify-name - app-scoped variant; use identity/verify_name instead

Full-app features are also out of scope:

  • Payments (make_payment, cancel_payment, etc.)
  • Webhooks (subscribe_webhook, etc.)

Scope-grant gotchas

These user-scoped endpoints require a Personal-App scope toggled at https://my.akahu.nz/developers; without the grant they return 403:

  • GET /parties - counterparty list (not shipped as a tool)
  • POST /verify/name and POST /verify/name/{id} - shipped as identity/verify_name

Releasing

To cut a release: bump version in pyproject.toml, push a vX.Y.Z tag, then publish a GitHub Release with that tag. The workflow runs the test+ruff+mypy gate, asserts the pyproject version matches the tag, and publishes to PyPI via Trusted Publishing (OIDC).

See PUBLISHING.md for the one-time PyPI setup and the manual-publish fallback.

Disclaimer

This is an unofficial integration. Not affiliated with Akahu, your bank, or any financial institution. Use at your own risk. The maintainers are not responsible for any data loss, unauthorised access, or financial impact arising from use of this software.

License

Apache-2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nz_akahu_mcp-0.1.3.tar.gz (128.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nz_akahu_mcp-0.1.3-py3-none-any.whl (27.2 kB view details)

Uploaded Python 3

File details

Details for the file nz_akahu_mcp-0.1.3.tar.gz.

File metadata

  • Download URL: nz_akahu_mcp-0.1.3.tar.gz
  • Upload date:
  • Size: 128.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nz_akahu_mcp-0.1.3.tar.gz
Algorithm Hash digest
SHA256 80ed5aa8bc327c824a0c10bfa47eae69de863a089a87c2fc0dd0e17240fb5e50
MD5 5886626917c008a6af4440b80de1a76d
BLAKE2b-256 c7dbf89f6de2888df9ed965597ca75f6f93f6aa45a16037e5a9f0aefe2a88712

See more details on using hashes here.

Provenance

The following attestation bundles were made for nz_akahu_mcp-0.1.3.tar.gz:

Publisher: release.yml on severity1/nz-akahu-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nz_akahu_mcp-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: nz_akahu_mcp-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 27.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nz_akahu_mcp-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 1fd2c536dc41cdd26c82fdb532659210106e6be9dbb4260c5b95ffcc298c43ed
MD5 24492b3cb84148f18d18b1acadb3bce3
BLAKE2b-256 5b758833e88963983dbc7a82f1d18dc0d3bbd43f2665099ef0048eed29bb75d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for nz_akahu_mcp-0.1.3-py3-none-any.whl:

Publisher: release.yml on severity1/nz-akahu-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page