plugin — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited plugin (MCP Server) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Unofficial MCP server for the Akahu open-finance API (New Zealand). Bring your own Akahu credentials; run locally over stdio; no hosted backend.
AKAHU_READ_ONLY=false.ctx.elicit() for confirmation in the client.uvx runner (or pip with a virtualenv)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=falseTokens 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-marketplaceAfter 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.Prefer the [marketplace plugin path](#marketplace-plugin-recommended) 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-mcpBefore 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-mcpScope 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-mcpRestart 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-mcpThen 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-mcpTo 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 envInside Claude Code, ask: "What accounts do I have?" - it should call nz-akahu_acct_list_accounts and return masked account details.
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.
nz-akahu-mcp-X.Y.Z.mcpb from the latest GitHub Release.true - leave unless you specifically need write tools)false - leave unless you want to skip consent prompts for account refresh)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.
claude_desktop_config.jsonPrefer the [Desktop Extension path](#desktop-extension-recommended) 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:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json~/.config/Claude/claude_desktop_config.jsonThen restart Claude Desktop.
# 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-mcpThe server speaks MCP over stdio. Inspect tool calls with:
uv run fastmcp dev src/nz_akahu_mcp/server.py+--- 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.
The server starts with AKAHU_READ_ONLY=true. Every write tool refuses with this message:
Write operations are disabled. To enable: setAKAHU_READ_ONLY=falsein your.envand restart the MCP server. Each write will require your explicit confirmation through Claude (or setAKAHU_AUTOMATION_BYPASS=truefor the automatable subset only).
When writes ARE enabled, every write still calls ctx.elicit() to ask you in Claude's UI before firing.
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.
`accounts/`
list_accounts - all connected accounts (masked, formatted balances)get_account(account_id) - single account detailsget_account_balance(account_id) - balance onlyget_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 accountssearch_transactions(query, limit=50) - substring across description + merchant.name`identity/`
get_meaccounts/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 40301-1234-1234567-00 -> 01-****-***4567-00.https://api.akahu.io/v1.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 insteadFull-app features are also out of scope:
make_payment, cancel_payment, etc.)subscribe_webhook, etc.)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_nameTo 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.
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.
Apache-2.0. See LICENSE.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.