Skip to main content
Glama
bunq Partner MCP

bunq Partner MCP

Official
by bunq

bunq Partner MCP

An MCP (Model Context Protocol) server that connects AI assistants like Claude to the bunq Partner API. Once set up, you can drive the entire partner onboarding flow — provisioning users, KYC, accounts, payments, cards, and compliance — through natural language conversation.

What you can do

After connecting, you can ask Claude things like:

  • "Provision a new user with email jan@example.nl and phone +31612345678"

  • "Check the status of provision 4521"

  • "Create a EUR bank account for user 8823"

  • "Make a payment of €50 from account 12 to IBAN NL91ABNA0417164300"

  • "Show me all open compliance inquiries for user 9002"

  • "Register a webhook for mutations on user 8823 pointing to https://myapp.com/webhooks"

Claude handles the full auth lifecycle, request signing, token management, and status polling automatically.

Related MCP server: you-need-an-advisor-mcp

Prerequisites

Setup

1. Clone and build

git clone https://github.com/bunq/partner-mcp.git
cd partner-mcp
npm install
npm run build

2. Add to Claude Desktop

Edit your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "bunq-partner": {
      "command": "node",
      "args": ["/absolute/path/to/partner-mcp/dist/index.js"],
      "env": {
        "BUNQ_API_KEY": "your_partner_api_key_here",
        "BUNQ_ENV": "sandbox"
      }
    }
  }
}

Replace /absolute/path/to/partner-mcp with the actual path where you cloned the repo.

3. Restart Claude Desktop

Quit and reopen Claude Desktop. You should see the bunq tools available.

4. Verify the connection

Ask Claude: "Check my bunq session info" — it should respond with your authenticated user ID and environment.

Environments

BUNQ_ENV

Base URL

sandbox (default)

https://partner-api.sandbox.bunq.com

production

https://api.partner.bunq.com

Always test in sandbox first. Sandbox API keys contain a sandbox_ prefix.

Sessions for provisioned users

Calls on behalf of a provisioned user (KYC, accounts, payments, cards, inquiries, freeze) must use that user's own session, not your partner session.

  1. When get_provision shows ACTIVE, call create_user_session with its provision_id.

  2. The server reads the provision's credential token itself, creates the user's installation, device and session, and keeps them. The token never reaches the conversation. The tool returns only user_id and user_api_key_id.

  3. Pass that user_id to every per-user tool. The server picks the matching session. Use user_api_key_id only to register that user's webhooks with set_notification_filters.

A per-user tool called before create_user_session fails with a message that tells you to create the session first.

What stays out of the conversation

Tool results never contain a credential token (token_value), a full card number (only the last 4 digits) or a CVC code.

Optional settings

Variable

Default

Meaning

BUNQ_PERSIST_STATE

true for sandbox, false for production

Keeps the key pairs, installations and sessions in a local file, so a restart does not register a new device or lose user sessions.

BUNQ_STATE_FILE

~/.bunq-partner-mcp/state-<env>-<key hash>.json

Where that file goes. It holds private keys and tokens and is written with mode 0600.

BUNQ_TIMEOUT_MS

30000

HTTP timeout per call.

The server checks the X-Bunq-Server-Signature of every successful response and refuses an unsigned or wrongly signed one.

Updating

When a new version is released:

cd partner-mcp
git pull
npm install
npm run build

Then restart Claude Desktop.

Available tools

The full API documentation — covering auth, OAuth, user provision, onboarding & KYC, webhooks, monetary accounts, payments, devices, cards, and compliance — lives in GitBook:

📚 Partner Onboarding API docs

Project structure

partner-mcp/
├── src/
│   ├── index.ts          # MCP server entry point (stdio transport)
│   ├── bunq-client.ts    # HTTP client, partner and user sessions, signatures
│   ├── state-store.ts    # Optional state file for keys and sessions
│   ├── encryption.ts     # Application-layer request/response encryption
│   ├── tools.ts          # Tool definitions (MCP schemas)
│   ├── operations.ts     # One entry per API tool: method, path, session, body
│   └── handler.ts        # Argument checks, custom tools, operation runner
├── test/                 # Unit tests (node:test), incl. the swagger parity test
├── partner-api-swagger.yaml       # Maintained OpenAPI spec
├── package.json
└── tsconfig.json

Support

Available Tools

45 tools
close_provisionB

Cancels a user provision. Sets status to CANCELLED.

Inputs: provision_id (required).

create_bank_accountC

Creates a EUR IBAN bank account (MonetaryAccountBank) for a provisioned user.

Inputs: user_id (required), currency, description.

create_card_cvc2B

Generates a new CVC2 security code for a card. This is an encrypted endpoint — the request is end-to-end encrypted on top of TLS.

Inputs: card_id (required), user_id (required), type.

create_card_panB

Generates and retrieves the primary account number (PAN) for a card. This is an encrypted endpoint — the request is end-to-end encrypted on top of TLS.

Inputs: card_id (required), user_id (required).

create_credit_cardA

Orders a new Mastercard credit card for a user. Use order_status=VIRTUAL_DELIVERY for immediate virtual card, or NEW_CARD_REQUEST_RECEIVED for physical delivery by post.

Inputs: user_id (required), second_line (required), product_type (required), name_on_card, +2 more.

create_debit_cardA

Orders a new Mastercard debit card for a user. Use order_status=VIRTUAL_DELIVERY for immediate virtual card, or NEW_CARD_REQUEST_RECEIVED for physical delivery by post.

Inputs: user_id (required), second_line (required), product_type (required), name_on_card, +3 more.

create_external_accountB

Creates a non-EUR external monetary account (MonetaryAccountExternal) via CurrencyCloud.

Inputs: user_id (required), currency (required), service, description, +1 more.

create_oauth_clientA

Creates a new OAuth client for the partner account. Required before provisioning any users.

Inputs: no named parameters.

create_paymentB

Creates a payment from a monetary account. For provisioned users without PSD2 access, only internal transfers between Eva and the partner are allowed. Description is limited to 140 characters.

Inputs: amount (required), user_id (required), account_id (required), description (required), +4 more.

create_provisionA

Provisions a new UserPerson under the partner account. Kicks off the full onboarding flow. Returns a provision_id to monitor progress via get_provision. The provision goes through sub-statuses: PENDING_PROCESS_USER → PENDING_PROCESS_RELATION_USER → PENDING_PROCESS_OAUTH_REQUEST → PENDING_PROCESS_USER_ONBOARDING. When ACTIVE, a credential.token_value is returned — this is Eva's API key. It expires in 1h (sandbox) / 4h (production): create a session immediately with create_user_session.

Inputs: email (required), phone_number (required), external_uuid (required), products, +1 more.

create_user_sessionA

Creates a session on behalf of a provisioned user using their credential.token_value (obtained from get_provision when status=ACTIVE). Returns a session token and UserApiKey.id — use this session token for all subsequent calls on behalf of that user. Must be called within 1h (sandbox) / 4h (production) of the token being issued.

Inputs: credential_token (required).

get_attachmentA

Gets metadata and download URLs for a previously uploaded attachment.

Inputs: user_id (required), attachment_id (required).

get_cardB

Gets details of a specific card including status, limits, and expiry date.

Inputs: card_id (required), user_id (required).

get_card_cvc2A

Gets the details of a specific generated CVC2 code. This is an encrypted endpoint.

Inputs: card_id (required), user_id (required), generated_cvc2_id (required).

get_identity_verificationA

Gets the identity verification session details including the SDK token and status. Use the token field to initialise the Incode SDK in your app.

Inputs: user_id (required), session_id (required).

get_monetary_accountB

Gets details of a specific monetary account including balance and IBAN.

Inputs: user_id (required), account_id (required).

get_oauth_clientA

Gets details (client_id, secret, callback URLs) for a specific OAuth client.

Inputs: oauth_client_id (required).

get_paymentC

Gets details of a specific payment.

Inputs: user_id (required), account_id (required), payment_id (required).

get_provisionA

Gets the current status and details of a user provision. Poll this after create_provision to track progress. When status=ACTIVE and credential.token_value is present, immediately call create_user_session — the token expires in 1h (sandbox) / 4h (production).

Inputs: provision_id (required).

get_session_infoA

Returns the current session status, authenticated user ID, and active environment (sandbox/production). Useful to verify the connection is working before other calls.

Inputs: no named parameters.

get_user_inquiryB

Gets full details of a compliance inquiry including all entries and their status.

Inputs: user_id (required), inquiry_id (required).

list_card_cvc2B

Lists all generated CVC2 codes for a card. This is an encrypted endpoint.

Inputs: card_id (required), user_id (required).

list_cardsB

Lists all cards (credit and debit) for a user.

Inputs: user_id (required).

list_monetary_accountsB

Lists all monetary accounts for a user.

Inputs: user_id (required).

list_notification_failuresA

Lists failed webhook deliveries for the partner's company user. The userId should be the UserCompany.id — this returns failures for all underlying provisioned users. Each record includes user_id (which provisioned user the failure belongs to) and user_requested_id (set when the filter was created via an API key, otherwise null).

Inputs: user_id (required).

list_oauth_clientsA

Lists all OAuth clients for the partner account.

Inputs: no named parameters.

list_paymentsA

Lists all payments (incoming and outgoing) for a monetary account.

Inputs: user_id (required), account_id (required).

list_provisionsB

Lists all partner user provisions with optional filtering.

Inputs: status, external_uuid.

list_user_inquiriesA

Lists compliance information inquiries for a provisioned user. Use status=EXPECTING_REPLY_FROM_USER to find open inquiries requiring action.

Inputs: user_id (required), status, purpose.

refresh_sessionA

Force-refreshes the bunq session token. Use this if you receive authentication errors.

Inputs: no named parameters.

register_oauth_callback_urlB

Registers an OAuth callback URL for a specific OAuth client.

Inputs: url (required), oauth_client_id (required).

reset_provision_tokenA

Requests a new credential API key for a provision whose token was lost, expired, or revoked. Sets status to TOKEN_RESET_REQUESTED. Poll get_provision until a new credential.token_value appears, then call create_user_session immediately.

Inputs: provision_id (required).

respond_to_inquiry_entryA

Submits an answer for a specific inquiry entry on behalf of Eva. Provide either attachment IDs (upload via upload_attachment first) or a free-text answer, or both. Only PENDING entries can be answered. After submission the entry moves to WAITING_FOR_REVIEW.

Inputs: user_id (required), entry_id (required), inquiry_id (required), answer, +1 more.

retry_notification_failuresB

Retries delivery of up to 100 failed webhook notifications by their failure IDs.

Inputs: user_id (required), failure_ids (required).

set_address_mainB

Sets the main (residential) address for a provisioned user during onboarding.

Inputs: city (required), street (required), user_id (required), postal_code (required), +2 more.

set_address_postalB

Sets the postal address for a provisioned user during onboarding.

Inputs: city (required), street (required), user_id (required), postal_code (required), +2 more.

set_nationalityA

Submits nationality information for a provisioned user. Required within 90 days.

Inputs: user_id (required), nationalities (required).

set_notification_filtersA

Sets webhook URLs for a user. ⚠️ This REPLACES all existing filters — always include the full desired list in one call. To add one filter, fetch the existing ones first and include them all. To remove all, pass an empty array. Categories: PARTNER_USER_PROVISION, USER_ONBOARDING, USER_INFORMATION_INQUIRY, MUTATION, PAYMENT, CARD, CARD_TRANSACTION_SUCCESSFUL, CARD_TRANSACTION_FAILED.

Inputs: filters (required), user_id (required).

set_tax_residentA

Submits tax residency information for a provisioned user. Required within 90 days.

Inputs: user_id (required), tax_residents (required).

start_identity_verificationA

Creates an identity verification session using the Incode SDK. Returns a session ID. Follow up with get_identity_verification to obtain the SDK token, pass it to the Incode SDK, then call submit_identity_verification once the SDK flow completes.

Inputs: user_id (required), purpose, provider.

submit_identity_verificationA

Notifies bunq that the Incode SDK flow is complete and the identity verification result is ready to be processed. Call this after the SDK returns a successful completion callback.

Inputs: user_id (required), session_id (required).

update_cardA

Updates a card's status, spending limits, or PIN. Use to activate a card after delivery, block/unblock it, or report it lost/stolen.

Inputs: card_id (required), user_id (required), status, card_limit, +2 more.

update_user_personB

Updates personal information for a provisioned user: name and date of birth.

Inputs: user_id (required), last_name (required), first_name (required), date_of_birth (required), +1 more.

upload_attachmentB

Uploads a file attachment for a provisioned user. The attachment ID can then be passed to respond_to_inquiry_entry via all_attachment_id to submit documents for a compliance inquiry. Supported types: image/png, image/jpeg, image/gif, application/pdf. Note: the actual file bytes must be sent as raw binary — provide the file path.

Inputs: user_id (required), description (required), content_type (required), base64_content (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 45 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes, e.g., provisioning, KYC, banking, cards. Some potential confusion exists between set_nationality and set_tax_resident, or start_identity_verification vs. get_identity_verification vs. submit_identity_verification, but descriptions clarify the flow. Overall, an agent can distinguish tools with reasonable accuracy.

    Naming Consistency4/5

    Tool names follow a consistent verb_noun pattern (e.g., create_provision, get_card, list_payments). Minor deviations like 'register_oauth_callback_url' vs. 'create_oauth_client' are present but not disruptive. No mixing of casing styles.

    Tool Count3/5

    45 tools is high for a single server. While the domain is broad (provisioning, KYC, accounts, cards, payments, compliance, OAuth, notifications), many tools could be consolidated (e.g., three CVC2 tools, multiple identity verification tools). The set feels slightly bloated.

    Completeness4/5

    The tool surface covers the full lifecycle for user provisioning, KYC, banking, cards, payments, and compliance inquiries. Minor gaps exist: no tool to close a bank account, delete a card, or manage OAuth clients beyond creation. Overall, core workflows are well-supported.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      A
      maintenance
      Lets AI assistants read and manage a self-hosted Actual Budget: accounts, transactions, budgets, categories, payees, rules, schedules and reports. Runs over stdio for Claude Desktop and Claude Code, or over HTTP with Bearer or OIDC auth for LibreChat and LobeChat.
      15
      1,864 npm
      77
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that connects AI assistants to YNAB budgets, enabling natural language queries about finances backed by full API coverage and built-in YNAB methodology knowledge.
      1
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that enables AI assistants to match users with capital providers for business loans, real estate, and asset tokenization through a conversational intake process.
      MIT