io.github.bajoski34/mcp-flutterwave
MCP Server to interact with Flutterwave APIs.
Open source Open in the app JSON README (API)
About
MCP Server to interact with Flutterwave APIs.
Details
- Kind
- MCP servers
- Topic
- No topic detected
- Publisher
- bajoski34
- Origin
- official
- Category
- ferramentas
- Transport
- local
- Version
- 1.2.0
- Stars
- 4
- Open pull requests
- 1
- Last push
- 2026-09-07T14:11:43Z
- Repository state
- ativo
- Language
- TypeScript
- License
- MIT
- Added
- 2026-08-29 03:02:28
- Updated
- 2026-08-29 03:02:28
- Origin id
io.github.bajoski34/mcp-flutterwave
README
# mcp-flutterwave
[](https://github.com/bajoski34/mcp-flutterwave/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/mcp-flutterwave)
[](https://www.npmjs.com/package/mcp-flutterwave)
[](https://github.com/bajoski34/mcp-flutterwave/pkgs/container/mcp-flutterwave)
[](./LICENSE)
[](https://www.npmjs.com/package/mcp-flutterwave)
[](https://modelcontextprotocol.io)
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) 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](#features)
- [Installation](#installation)
- [Available Tools](#available-tools)
- [Card Charge Flow](#card-charge-flow)
- [Virtual Accounts](#virtual-accounts)
- [Bill Payment Flow](#bill-payment-flow)
- [FX Trade Flow](#fx-trade-flow)
- [Verification](#verification)
- [Stablecoins](#stablecoins)
- [Web App](#web-app)
- [MCP Server Setup](#mcp-server-setup)
- [Usage with Claude Desktop](#usage-with-claude-desktop)
- [MCP-UI Components](#mcp-ui-components)
- [Contributing](#contributing)
- [Changelog](#changelog)
- [Security](#security)
- [License](#license)
---
## 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
```bash
npm install -g mcp-flutterwave
```
### npx (no install needed)
```bash
npx mcp-flutterwave --tools=all
```
### Docker
Pull the image:
```bash
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:
```json
{
"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:
```json
// 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
```json
{
"email": "customer@example.com",
"currency": "NGN",
"tx_ref": "VA-NGN-001",
"is_permanent": true,
"bvn": "22415929481"
}
```
### GHS dynamic account
```json
{
"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.
```json
{ "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.
```json
{ "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.

### 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](https://dashboard.flutterwave.com) under **Settings → API Keys**.
Get your Anthropic key from the [Anthropic Console](https://console.anthropic.com).
**Build and start**
```bash
# 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](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
```bash
npm install -g mcp-flutterwave
```
### Via GitHub
```bash
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](https://modelcontextprotocol.io/quickstart/user) for details.
Pass `--tools=all` to enable every tool, or supply a comma-separated list to restrict which tools are registered.
### Via npm
```json
{
"mcpServers": {
"flutterwave": {
"command": "mcp-flutterwave",
"args": ["--tools=all"],
"env": {
"FLW_SECRET_KEY": "YOUR_SECRET_KEY",
"FLW_ENCRYPTION_KEY": "YOUR_ENCRYPTION_KEY"
}
}
}
}
```
### Via local build
```json
{
"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
```json
"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](https://www.npmjs.com/package/@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](./CONTRIBUTING.md) for details on how to get started, development guidelines, and how to submit pull requests.
---
## Changelog
All notable changes are documented in [GitHub Releases](https://github.com/bajoski34/mcp-flutterwave/releases).
---
## Security
If you discover a security vulnerability, please **do not** open a public issue. Instead, email [olaobajua@gmail.com](mailto:olaobajua@gmail.com) directly. We will respond as quickly as possible.
---
## License
MIT © [Abraham Olaobaju](https://github.com/bajoski34)
See [LICENSE](./LICENSE) for the full text.