mcp-flutterwave

bajoski34/mcp-flutterwave
2 starsMITCommunity

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

MCP Server to interact with Flutterwave APIs.

README.md

mcp-flutterwave

![CI](https://github.com/bajoski34/mcp-flutterwave/actions/workflows/ci.yml) ![npm version](https://www.npmjs.com/package/mcp-flutterwave) ![npm downloads](https://www.npmjs.com/package/mcp-flutterwave) ![Docker](https://github.com/bajoski34/mcp-flutterwave/pkgs/container/mcp-flutterwave) ![License: MIT](./LICENSE) ![Node.js](https://www.npmjs.com/package/mcp-flutterwave) ![MCP](https://modelcontextprotocol.io)

An MCP (Model Context Protocol) server that enables AI assistants to interact with the Flutterwave API — create payment links, charge customers directly, manage transfers, collect via virtual accounts, pay bills, and more.

Note: This server currently targets the Flutterwave v3 API. Support for v4 is coming soon.

Also ships with a built-in web app that connects to the MCP server and lets you talk to a Claude-powered Flutterwave assistant directly in your browser.

---

Contents

---

Features

  • Checkout — Create hosted payment links and disable them
  • Direct Charges — Charge customers via card, bank account, mobile money, M-Pesa, or USSD
  • Full card auth flow — PIN, AVS (Address Verification), 3D Secure redirect, and OTP validation all handled automatically
  • Charge Validation — Validate OTP-based charges with a dedicated tool
  • Transactions — Verify by ID or reference, view event timeline, resend failed webhooks
  • Transfers — Initiate single transfers, manage beneficiaries
  • Payment Plans — Create and retrieve subscription plans
  • Virtual Accounts — Generate dedicated account numbers for NGN and GHS bank transfer collection (static or dynamic)
  • Bill Payments — Pay airtime, data, cable TV, electricity, internet bills and more (Nigeria)
  • FX Trade — Convert between NGN, GHS, and USD with live quotes (RFQ → trade in two steps)
  • Verification — BVN identity verification, bank account name resolution, and card BIN lookup
  • Stablecoins — Send USDC/USDT to Polygon wallets, or convert NGN/USD fiat into stablecoins
  • Rich UI — Every tool returns a branded HTML card rendered inline in supported clients
  • Web App — A standalone browser chat interface powered by Claude + this MCP server

---

Installation

npm

npm install -g mcp-flutterwave

npx (no install needed)

npx mcp-flutterwave --tools=all

Docker

Pull the image:

docker pull ghcr.io/bajoski34/mcp-flutterwave:latest

The server communicates over stdio, so it must be launched by an MCP client — not run standalone. Configure Claude Desktop to use the Docker image as the MCP server:

{
  "mcpServers": {
    "flutterwave": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "FLW_SECRET_KEY=YOUR_SECRET_KEY",
        "-e", "FLW_ENCRYPTION_KEY=YOUR_ENCRYPTION_KEY",
        "ghcr.io/bajoski34/mcp-flutterwave:latest"
      ]
    }
  }
}

The -i flag keeps stdin open so Claude Desktop can communicate with the server over stdio.

Requirements: Node.js 20 or later (for npm/npx).

---

Available Tools

Checkout

| Tool | Description | |---|---| | create_checkout | Create a hosted Flutterwave payment link | | disable_checkout | Disable an existing payment link |

Direct Charges

| Tool | Description | |---|---| | charge_card | Directly charge a debit or credit card — handles PIN, AVS, 3DS, and OTP flows | | charge_bank_account | Debit a bank account (NGN / GHS) | | charge_mobile_money | Mobile money — Ghana, Uganda, Rwanda, Zambia, Francophone Africa | | charge_mpesa | M-Pesa charge (KES) | | charge_ussd | USSD charge (NGN) | | validate_charge | Validate a pending charge using OTP |

Transactions

| Tool | Description | |---|---| | read_transaction | Get transaction details by ID | | read_transaction_with_reference | Get transaction details by tx_ref | | read_transaction_timeline | View the event timeline for a transaction | | resend_transaction_webhook | Resend a failed webhook |

Transfers

| Tool | Description | |---|---| | create_transfer | Initiate a bank transfer | | create_beneficiary | Save a new transfer beneficiary | | list_beneficiaries | List all saved beneficiaries |

Payment Plans

| Tool | Description | |---|---| | create_payment_plan | Create a recurring payment plan | | get_payment_plans | List payment plans with optional filters |

Virtual Accounts

| Tool | Description | |---|---| | create_virtual_account | Create a dedicated bank account number for a customer (NGN or GHS) | | get_virtual_account | Retrieve a virtual account's status and details by order_ref | | update_virtual_account | Link or update the BVN on an NGN virtual account | | list_virtual_account_bulk | List all accounts created in a bulk batch |

Bill Payments

| Tool | Description | |---|---| | get_bill_categories | List available bill categories (AIRTIME, CABLEBILLS, UTILITYBILLS, etc.) | | get_bill_providers | List billers/providers for a category | | get_bill_items | List payable items for a specific biller | | validate_bill_customer | Validate a customer account before payment (meter number, smartcard, etc.) | | pay_bill | Submit a bill payment | | get_bill_status | Check payment status and retrieve prepaid tokens (electricity) |

FX Trade

| Tool | Description | |---|---| | request_fx_quote | Submit a Request For Quote (RFQ) for a currency conversion | | get_fx_quote | Poll the quote status — wait for READY before trading | | initiate_fx_trade | Lock in a READY quote and execute the trade | | get_fx_trade | Poll trade status until SETTLED or FAILED |

Verification

| Tool | Description | |---|---| | initiate_bvn_verification | Begin a BVN identity check — returns a single-use customer consent URL | | get_bvn_details | Retrieve full BVN identity data after consent is given | | resolve_bank_account | Look up the account holder name for a bank account number | | verify_card_bin | Look up card brand, type, issuer, and country from the first 6 digits |

Stablecoins

| Tool | Description | |---|---| | get_stablecoin_fee | Get the transfer fee before sending — shows net amount the recipient receives | | send_stablecoin | Send USDC or USDT to a Polygon wallet address | | convert_to_stablecoin | Convert NGN or USD fiat balance into USDC or USDT |

---

Card Charge Flow

Direct card charges are multi-step. The charge_card tool handles every stage automatically and tells Claude what to do next.

1. charge_card(card details)
        │
        ├─ mode: "pin"        → ask customer for PIN
        │       charge_card(same params + authorization: { mode: "pin", pin: "..." })
        │               │
        │               ├─ mode: "otp"      → validate_charge(flw_ref, otp)
        │               └─ mode: "redirect" → send customer to 3DS URL
        │
        ├─ mode: "avs_noauth" → ask customer for billing address
        │       charge_card(same params + authorization: { mode: "avs_noauth", city, address, ... })
        │               │
        │               ├─ mode: "otp"      → validate_charge(flw_ref, otp)
        │               └─ mode: "redirect" → send customer to 3DS URL
        │
        ├─ mode: "redirect"   → send customer to 3DS URL, then read_transaction to verify
        │
        └─ (none)             → charge complete — read_transaction to verify

Authorization parameters

When a second call is needed, pass authorization alongside the original card details:

// PIN flow
{ "authorization": { "mode": "pin", "pin": "3310" } }

// AVS flow
{ "authorization": { "mode": "avs_noauth", "city": "Lagos", "address": "12 Victoria Island", "state": "LA", "country": "NG", "zipcode": "100001" } }

AMEX cards

American Express transactions require the card_holder_name field in addition to standard card details.

Payload encryption

Card payloads are encrypted with 3DES-ECB using your FLW_ENCRYPTION_KEY before they are sent to Flutterwave (PCI DSS requirement). The encryption is handled automatically — set the environment variable and the server does the rest.

---

Virtual Accounts

Virtual accounts give each customer a dedicated bank account number to make transfers into. Flutterwave notifies your webhook when a payment arrives.

| Feature | NGN | GHS | |---|---|---| | Dynamic (one-time) | ✓ — set amount, expires in ~1 hr | ✓ — use frequency and duration | | Static (reusable) | ✓ — is_permanent: true, BVN required | ✓ — is_permanent: true | | BVN required | Static accounts only | No |

NGN static account

{
  "email": "customer@example.com",
  "currency": "NGN",
  "tx_ref": "VA-NGN-001",
  "is_permanent": true,
  "bvn": "22415929481"
}

GHS dynamic account

{
  "email": "customer@example.com",
  "currency": "GHS",
  "tx_ref": "VA-GHS-001",
  "amount": 500,
  "frequency": 5,
  "duration": 7
}

After creation, save the order_ref — it is the key for retrieving or updating the account via get_virtual_account and update_virtual_account.

---

Bill Payment Flow

Bill payments follow a 6-step discovery flow. Skip validate_bill_customer for airtime and mobile data.

1. get_bill_categories
        ↓ choose a category (e.g. UTILITYBILLS)

2. get_bill_providers(category)
        ↓ get biller_code (e.g. "BIL127" for IKEDC)

3. get_bill_items(biller_code)
        ↓ get item_code and amount info

4. validate_bill_customer(item_code, customer_id)   ← skip for AIRTIME / MOBILEDATA
        ↓ confirm customer name and details

5. pay_bill(biller_code, item_code, customer_id, amount)
        ↓ returns reference

6. get_bill_status(reference)
        ↓ confirms completion
          for electricity: prepaid token is in extra.token — share it with the customer

Supported categories

| Code | Description | |---|---| | AIRTIME | Mobile airtime top-up | | MOBILEDATA | Data bundle purchase | | CABLEBILLS | Cable TV (DSTV, GOTV, StarTimes) | | INTSERVICE | Internet service subscriptions | | UTILITYBILLS | Electricity (prepaid & postpaid) | | TAX | Government tax payments | | DONATIONS | Charitable donations | | TRANSLOG | Transport / logistics | | DEALPAY | Deal payments | | RELINST | Religious institutions | | SCHPB | School / education payments |

Bill payments are available for Nigeria only (country: NG).

---

FX Trade Flow

Currency conversion uses a two-step quote-then-trade flow. Quotes are valid for 5 minutes and available weekdays only (Monday–Friday).

1. request_fx_quote(base_currency, target_currency, quantity)
        ↓ returns quote_id, status: NEW

2. get_fx_quote(quote_id)   ← poll until READY or FAILED
        ↓ READY: contains rate, approved_quantity, total_value, expiry

3. initiate_fx_trade(quote_id, narration)
        ↓ locks in rate, returns trade_id, status: NEW

4. get_fx_trade(trade_id)   ← poll until SETTLED or FAILED
        ↓ SETTLED: converted funds credited to target currency wallet instantly

Supported currency pairs

| Pair | Sell | Receive | |---|---|---| | NGN/USD | Nigerian Naira | US Dollar | | GHS/USD | Ghanaian Cedi | US Dollar | | USD/NGN | US Dollar | Nigerian Naira |

Quote statuses

| Status | Meaning | |---|---| | NEW | Quote is being priced | | READY | Rate locked — call initiate_fx_trade now | | PROCESSING | A trade has been initiated on this quote | | EXPIRED | 5-minute window passed — submit a new quote | | FAILED | Pair unsupported, minimum not met, or account limit exceeded |

Trade statuses

| Status | Meaning | |---|---| | NEW | Trade queued | | PENDING | Executing | | SETTLED | Funds exchanged and credited to target currency wallet | | FAILED | Insufficient balance or processing error |

Key constraints

  • Minimum trade: $1,000 USD equivalent in the base currency
  • Quote lifetime: 5 minutes from issuance (READY state)
  • One-time use: Each quote can only be used for one trade
  • Approved quantity: May differ from requested quantity due to liquidity or account limits — always use approved_quantity for reconciliation
  • Account enablement: Contact hi@flutterwavego.com to enable FX trading on your account

---

Verification

Bank Account Resolution

Verify a recipient's account details before sending a transfer. Always show the resolved name to the user before proceeding.

{ "account_number": "0690000040", "account_bank": "044" }

Common bank codes: 044 Access Bank · 057 Zenith Bank · 058 GTBank · 033 UBA · 011 First Bank

Card BIN Lookup

Identify card metadata from the first 6 digits of a card number.

{ "bin": "553188" }
// → { brand: "MASTERCARD", type: "CREDIT", issuer: "NEXUS MERCHANT BANK", country: "NIGERIA" }

AMEX cards identified via BIN require the card_holder_name field when calling charge_card.

BVN Verification (Nigeria)

Two-step consent flow — customer must approve data sharing on the NIBSS portal.

1. initiate_bvn_verification(bvn, firstname, lastname, redirect_url)
        ↓ returns reference + single-use consent URL

2. Customer visits consent URL → approves data sharing on NIBSS portal
        ↓ webhook (bvn.completed) fires OR poll:

3. get_bvn_details(reference)
        ↓ returns name, DOB, gender, phone, NIN, state of origin, watchlist status

Requires Flutterwave account enablement — contact hi@flutterwavego.com. If the customer has already consented, initiate_bvn_verification returns url: null and you can call get_bvn_details immediately.

---

Stablecoins

Send USDC or USDT over the Polygon network, or convert NGN/USD fiat balances into stablecoins. Always call get_stablecoin_fee first so the user knows the net amount the recipient will receive.

Wallet-to-wallet transfer

1. get_stablecoin_fee(amount, currency: "USDT", debit_currency: "USDT")
        ↓ shows fee and net amount

2. send_stablecoin(wallet_address, amount, currency, debit_currency)
        ↓ returns reference and transfer status

Fiat-to-stablecoin conversion

1. get_stablecoin_fee(amount, currency: "USDC", debit_currency: "NGN")
        ↓ shows fee (percentage-based) and net USDC amount

2. convert_to_stablecoin(merchant_id, amount, currency, debit_currency: "NGN")
        ↓ deducts NGN from your fiat wallet, credits USDC/USDT

Key constraints

| Constraint | Detail | |---|---| | Network | Polygon only — no Tron, Solana, or Stellar | | Coins | USDC and USDT | | Wallet format | EVM address: 0x + 40 hex characters (42 total) | | Fiat sources | NGN or USD for convert_to_stablecoin; stablecoin must match currency for send_stablecoin | | Fee type | Flat fee for same-currency; percentage fee for fiat → stablecoin |

---

Web App

The app/ directory contains a standalone browser chat interface that wraps this MCP server with a Claude-powered conversation loop.

!Flutterwave MCP-UI Components

How it works

Browser  →  POST /api/chat
               ↓
           Claude (Sonnet) — all MCP tools injected via advanced-tool-use beta
               ↓  tool_use
           MCP Server (this repo, spawned via stdio)
               ↓
           Flutterwave API

The web app uses three Anthropic Advanced Tool Use features:

  • Tool Search — non-core tools are deferred and loaded on demand, reducing token usage by ~85%
  • Programmatic Tool Calling — Claude can write code that calls multiple tools in sequence without inflating the conversation context
  • Tool Use Examples — curated input_examples for every tool improve parameter accuracy from ~72% to ~90%

The app returns a rich branded UI card for every tool response — checkout links, transaction details, charge states, transfer summaries, virtual accounts, bill receipts — rendered inline in the chat.

Running the web app

Prerequisites

| Variable | Required | Description | |---|---|---| | FLW_SECRET_KEY | Yes | Your Flutterwave secret key | | FLW_ENCRYPTION_KEY | For card charges | Your Flutterwave encryption key | | ANTHROPIC_API_KEY | Yes | Your Anthropic API key |

Get your keys from the Flutterwave Dashboard under Settings → API Keys. Get your Anthropic key from the Anthropic Console.

Build and start

# Clone and install
git clone https://github.com/bajoski34/mcp-flutterwave.git
cd mcp-flutterwave
npm install

# Build both the MCP server and the web app
npm run build:all

# Start
ANTHROPIC_API_KEY=sk-ant-... FLW_SECRET_KEY=FLWSECK_... npm run start:app

Then open http://localhost:3000.

Available scripts

| Script | Description | |---|---| | npm run build | Build the MCP server only | | npm run build:app | Build the web app only | | npm run build:all | Build everything | | npm run start:app | Start the web app (requires a prior build) | | npm run dev:app | Build everything then start the web app | | npm test | Run the test suite |

Port

Set the PORT environment variable to change from the default 3000.

---

MCP Server Setup

Via npm

npm install -g mcp-flutterwave

Via GitHub

git clone https://github.com/bajoski34/mcp-flutterwave.git
cd mcp-flutterwave
npm install
npm run build

Environment variables

| Variable | Required | Description | |---|---|---| | FLW_SECRET_KEY | Yes | Your Flutterwave secret key | | FLW_ENCRYPTION_KEY | For card charges | Your Flutterwave encryption key (from Dashboard → Settings → API) |

---

Usage with Claude Desktop

Add the following to your claude_desktop_config.json. See the MCP quickstart for details.

Pass --tools=all to enable every tool, or supply a comma-separated list to restrict which tools are registered.

Via npm

{
  "mcpServers": {
    "flutterwave": {
      "command": "mcp-flutterwave",
      "args": ["--tools=all"],
      "env": {
        "FLW_SECRET_KEY": "YOUR_SECRET_KEY",
        "FLW_ENCRYPTION_KEY": "YOUR_ENCRYPTION_KEY"
      }
    }
  }
}

Via local build

{
  "mcpServers": {
    "flutterwave": {
      "command": "node",
      "args": [
        "/path/to/mcp-flutterwave/build/index.js",
        "--tools=all"
      ],
      "env": {
        "FLW_SECRET_KEY": "YOUR_SECRET_KEY",
        "FLW_ENCRYPTION_KEY": "YOUR_ENCRYPTION_KEY"
      }
    }
  }
}

Selective tools

"args": [
  "--tools=create_checkout,read_transaction,create_transfer"
]

Accepted tool names (use all to enable everything):

create_checkout            disable_checkout
read_transaction           read_transaction_with_reference
read_transaction_timeline  resend_transaction_webhook
create_transfer            create_beneficiary            list_beneficiaries
create_payment_plan        get_payment_plans
charge_card                charge_bank_account           charge_mobile_money
charge_mpesa               charge_ussd                   validate_charge
create_virtual_account     get_virtual_account           update_virtual_account
list_virtual_account_bulk
get_bill_categories        get_bill_providers            get_bill_items
validate_bill_customer     pay_bill                      get_bill_status
request_fx_quote           get_fx_quote
initiate_fx_trade          get_fx_trade
initiate_bvn_verification  get_bvn_details
resolve_bank_account       verify_card_bin
get_stablecoin_fee         send_stablecoin               convert_to_stablecoin

---

MCP-UI Components

Every tool returns a rich HTML card alongside its text response, powered by @mcp-ui/server. The cards use Flutterwave's design tokens — navy #0A0E27, deep orange #FF5804, brand orange #F5A623, and the system sans-serif typeface.

Card charge UI states

| State | Card shown | |---|---| | PIN required | Step-by-step instructions, transaction reference | | AVS required | Required billing address fields as chips | | 3DS redirect | Bank authentication URL with a direct link | | OTP required | Bank message, flw_ref to pass to validate_charge | | Completed | Amount, status badge, transaction and Flutterwave references |

Virtual account UI

The virtual account card shows the bank account number in a large, prominent box alongside the bank name, account type (Static / Dynamic), currency, expiry date, and order reference.

Bill payment UI

| Tool | Card shown | |---|---| | pay_bill | Bill receipt — biller, item, customer ID, amount, status | | get_bill_status | Status card with prepaid token (electricity) in large monospace text, with a share note |

Verification UI

| Tool | Card shown | |---|---| | initiate_bvn_verification | Consent card — customer name (BVN last-4 only), single-use consent link with open button, step-by-step instructions | | get_bvn_details | Identity card — name, DOB, gender, phone, NIN, state of origin; BVN partially masked; red watchlist badge if flagged | | resolve_bank_account | Green verified card — account name in large text with account number and bank code | | verify_card_bin | Brand-coloured card (Visa blue / Mastercard red / Amex blue / dark for others) — brand, type badge, issuer, country |

Stablecoin UI

| Tool | Card shown | |---|---| | get_stablecoin_fee | Blue-themed fee card — coin pair, flat fee or percentage breakdown, net amount the recipient receives | | send_stablecoin | Transfer card — truncated wallet address, amount, status badge | | convert_to_stablecoin | Conversion card — fiat debit currency, target stablecoin, merchant ID, status |

FX trade UI

Both request_fx_quote/get_fx_quote and initiate_fx_trade/get_fx_trade return dark navy-themed cards:

| State | Card shown | |---|---| | Quote NEW / PROCESSING | Instrument badge, status pill, poll instruction | | Quote READY | Exchange rate, approved quantity, received amount, expiry, call-to-action | | Quote FAILED / EXPIRED | Error message with reason | | Trade NEW / PENDING | Amount in target currency, poll instruction | | Trade SETTLED | Green settled banner, target currency amount, recipient, wallet credit note | | Trade FAILED | Red failure banner with response_message |

Cards are compatible with:

  • Flutterwave Web App (this repo's app/) — rendered inline in the chat
  • MCP Inspector — for testing during development
  • Any MCP client that supports the resource content type with HTML

---

Contributing

We welcome contributions! Please read our Contributing Guide for details on how to get started, development guidelines, and how to submit pull requests.

---

Changelog

All notable changes are documented in GitHub Releases.

---

Security

If you discover a security vulnerability, please do not open a public issue. Instead, email olaobajua@gmail.com directly. We will respond as quickly as possible.

---

License

MIT © Abraham Olaobaju

See LICENSE for the full text.

Related MCP servers

Browse all →