Give your AI assistant the ability to accept payments, verify identities, manage virtual accounts, and query transactions, all through Monnify.
This is an MCP (Model Context Protocol) server. Once connected, your AI client can talk directly to the Monnify API using plain language. No custom integration code required.
A few examples of what you'd actually ask while wiring this into a real feature:
"add a reserved account to our wallet feature so customers can top up by bank transfer" > "set up a one-time checkout for a ₦15,000 order and give me the payment link" > "create a ₦50,000 invoice that expires in 48 hours" > "validate this account number before we save it to the customer's payout details" > "refund ₦2,500 on transaction TRX-20240601-009"
- Node.js 20 or later
- A Monnify account with API access enabled
- Your API Key, Secret Key, and Contract Code from the Monnify Dashboard → Developer → API Keys & Contracts
npx -y @monnify/mcp-server \
--apiKey=YOUR_API_KEY \
--secretKey=YOUR_SECRET_KEY \
--contractCode=YOUR_CONTRACT_CODE \
--env=sandboxSwitch --env=sandbox to --env=production when you're ready to go live.
The server speaks the MCP stdio protocol, which is supported by all major AI tools. Pick yours below.
Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"monnify": {
"command": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
}
}Restart Claude Desktop after saving. You will see "monnify" appear in the tools panel.
Project-level: add to .claude/mcp.json in your repo (checked in, shared with your team):
{
"servers": {
"monnify": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
}
}Global: add to ~/.claude/claude_desktop_config.json so it's available in every Claude Code session:
claude mcp add monnify \
-- npx -y @monnify/mcp-server \
--apiKey=YOUR_API_KEY \
--secretKey=YOUR_SECRET_KEY \
--contractCode=YOUR_CONTRACT_CODE \
--env=sandboxVerify it loaded:
claude mcp listMac: ~/Library/Application Support/ChatGPT/mcp.json
Windows: %APPDATA%\ChatGPT\mcp.json
{
"mcpServers": {
"monnify": {
"command": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
}
}Restart ChatGPT Desktop. MCP tools will appear in the tool-use panel when you start a new conversation.
Add to ~/.gemini/settings.json:
{
"mcpServers": {
"monnify": {
"command": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
}
}Run gemini in your terminal, then type @monnify to confirm the server is available.
Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json in your project root:
{
"mcpServers": {
"monnify": {
"command": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
}
}Open Cursor Settings → MCP to confirm the server shows as active.
Create .vscode/mcp.json in your workspace root:
{
"servers": {
"monnify": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
}
}Open the Copilot Chat panel, switch to Agent mode, and the Monnify tools will be available. Commit .vscode/mcp.json to share the setup with your team (credentials should come from environment variables; see using environment variables).
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"monnify": {
"command": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
}
}Add to ~/.config/zed/settings.json under "context_servers":
{
"context_servers": {
"monnify": {
"command": {
"path": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
}
}
}Add to ~/.continue/config.json under "mcpServers":
{
"mcpServers": [
{
"name": "monnify",
"command": "npx",
"args": [
"-y",
"@monnify/mcp-server",
"--apiKey=YOUR_API_KEY",
"--secretKey=YOUR_SECRET_KEY",
"--contractCode=YOUR_CONTRACT_CODE",
"--env=sandbox"
]
}
]
}Avoid hardcoding credentials in config files by passing them via environment variables instead:
{
"mcpServers": {
"monnify": {
"command": "npx",
"args": ["-y", "@monnify/mcp-server"],
"env": {
"MONNIFY_API_KEY": "YOUR_API_KEY",
"MONNIFY_SECRET_KEY": "YOUR_SECRET_KEY",
"MONNIFY_CONTRACT_CODE": "YOUR_CONTRACT_CODE",
"MONNIFY_ENV": "sandbox"
}
}
}
}All CLI flags have an equivalent environment variable:
| CLI flag | Environment variable |
|---|---|
--apiKey |
MONNIFY_API_KEY |
--secretKey |
MONNIFY_SECRET_KEY |
--contractCode |
MONNIFY_CONTRACT_CODE |
--env |
MONNIFY_ENV |
--transport |
MONNIFY_TRANSPORT |
--port |
MONNIFY_PORT |
--tools |
MONNIFY_TOOLS |
--format |
MONNIFY_RESPONSE_FORMAT |
The server automatically detects which client is connecting and adapts its responses:
| Client | Response format |
|---|---|
| Claude Desktop, Claude Code CLI | Conversational Markdown with status icons, Naira formatting, and human-readable dates |
| Cursor, VS Code Copilot, Windsurf, Zed, Continue.dev | Clean JSON, machine-readable and easy to pipe into other tools |
| ChatGPT, Gemini | Conversational Markdown |
Override the format with the --format flag if the auto-detection doesn't match your workflow:
# Force JSON for all clients (e.g. a custom integration)
npx -y @monnify/mcp-server --apiKey=... --format=json
# Force Markdown for all clients
npx -y @monnify/mcp-server --apiKey=... --format=markdownWhat conversational responses look like:
✅ Payment Initiated
Amount: ₦15,000.00
Reference: PAY-20240601-007
Customer: John Doe (john@example.com)
Checkout: https://checkout.monnify.com/pay/abc123
Expires: 1 Jul 2024, 11:59 PM WAT
What JSON responses look like (for engineering tools):
{
"paymentReference": "PAY-20240601-007",
"totalPayable": 15000,
"checkoutUrl": "https://checkout.monnify.com/pay/abc123",
"paymentStatus": "PENDING"
}| Flag | Default | Description |
|---|---|---|
--apiKey |
none | Your Monnify API key (required) |
--secretKey |
none | Your Monnify secret key (required) |
--contractCode |
none | Your Monnify contract code (required) |
--env |
sandbox |
sandbox or production |
--transport |
stdio |
stdio (local clients) or http (team deployments) |
--port |
3000 |
Port to listen on when using --transport=http |
--tools |
all | Comma-separated list of tool categories (see below) |
--format |
auto |
auto, markdown, or json |
--httpToken |
none | Bearer token to authenticate HTTP /mcp requests |
| Tool | What it does |
|---|---|
monnify_initiate_payment |
Creates a payment and returns a checkout URL |
monnify_reserve_account |
Reserves a virtual bank account for a customer |
monnify_get_reserved_account |
Fetches details and status of a reserved account |
monnify_get_reserved_account_transactions |
Lists transactions received on a reserved account |
monnify_deallocate_reserved_account |
Permanently removes a reserved account |
monnify_get_transaction_status |
Checks the status of a transaction by reference |
monnify_get_transaction_details |
Fetches full details of a transaction |
monnify_get_all_transactions |
Lists transactions with filters and pagination |
monnify_create_invoice |
Creates a payment invoice with an expiry date |
monnify_process_refund |
Issues a full or partial refund |
monnify_pay_with_bank_transfer |
Starts a pay-by-bank-transfer flow |
monnify_charge_card |
Charges a card with PAN and CVV |
monnify_charge_card_token |
Charges a previously saved card token |
monnify_authorise_card_otp |
Submits OTP to complete a card charge |
monnify_authorise_card_3ds |
Completes 3DS verification for a card charge |
| Tool | What it does |
|---|---|
monnify_create_mandate |
Creates a direct debit mandate |
monnify_get_mandate_status |
Checks if a mandate is active and ready to debit |
monnify_debit_mandate |
Debits an active mandate |
monnify_get_mandate_debit_status |
Checks the status of a debit attempt |
monnify_cancel_mandate |
Cancels a mandate permanently |
| Tool | What it does |
|---|---|
monnify_verify_bank_account |
Verifies an account number and returns the account name |
monnify_verify_bvn |
Matches a BVN against name, date of birth, and phone number |
monnify_verify_bvn_info |
Checks whether all submitted BVN details match holistically |
monnify_verify_nin |
Verifies a NIN and returns the associated record |
| Tool | What it does |
|---|---|
monnify_get_supported_banks |
Lists all supported banks and their codes |
| Tool | What it does |
|---|---|
monnify_create_sub_accounts |
Creates one or more sub-accounts for payment splitting |
monnify_get_sub_accounts |
Lists all sub-accounts on your integration |
monnify_update_sub_account |
Updates a sub-account's bank details, email, or default split |
monnify_delete_sub_account |
Permanently deletes a sub-account |
A sub-account must exist (created via monnify_create_sub_accounts, or the Monnify dashboard) before its subAccountCode can be used in incomeSplitConfig on monnify_initiate_payment, monnify_reserve_account, monnify_charge_card_token, or monnify_debit_mandate.
A few Monnify features are restricted or disabled by default. Knowing these upfront saves time debugging what looks like an integration bug:
| Feature | Behaviour |
|---|---|
monnify_verify_bvn, monnify_verify_bvn_info, monnify_verify_nin |
Live only. These identity checks always fail in sandbox, regardless of the BVN/NIN supplied. Test against production (with a real BVN/NIN) or mock the flow in your own tests. |
monnify_process_refund |
Disabled by default, and only works for transactions originally paid via ACCOUNT_TRANSFER. Check paymentMethod with monnify_get_transaction_status first. Transactions paid by CARD or USSD cannot be refunded through this API at all. Email integration-support@monnify.com to request access. |
Direct Debit (monnify_create_mandate and the rest of the mandate lifecycle) |
Disabled by default. Returns "not permitted" until enabled on your account. Email integration-support@monnify.com to request access. |
Sub Accounts (monnify_create_sub_accounts and the rest of the Sub Account tools, plus incomeSplitConfig/subAccountCode on payment, reserved-account, and mandate tools) |
Disabled by default. Returns "not permitted" until enabled on your account. Email integration-support@monnify.com to request access. A sub-account must also exist before its code can be used in any incomeSplitConfig. |
| Wallet balance / disbursement wallet endpoints | Not exposed as a tool in this server; when available on your account, they're also permission-gated the same way. |
If you hit a "not permitted" response on a feature not listed here, it likely needs enabling the same way. Contact integration-support@monnify.com rather than assuming the request is malformed.
Date format quirk: monnify_create_invoice's expiryDate must be YYYY-MM-DD HH:mm:ss (space-separated), not ISO 8601 (YYYY-MM-DDTHH:mm:ss). The tool validates this and will reject an ISO 8601 value with a clear error before it reaches the API.
Scope the server to only the tools your use case needs. This reduces the surface area exposed to the AI client and keeps the tool list focused.
# Verification and utilities only (e.g. a KYC onboarding agent)
npx -y @monnify/mcp-server --apiKey=... --secretKey=... --contractCode=... --tools=verification,utilities
# Collections only (e.g. a payment support agent)
npx -y @monnify/mcp-server --apiKey=... --secretKey=... --contractCode=... --tools=collections
# Collections + verification (e.g. a full checkout agent)
npx -y @monnify/mcp-server --apiKey=... --secretKey=... --contractCode=... --tools=collections,verificationAvailable categories: collections, directDebit, verification, utilities, subAccounts
Deploy a single shared instance and connect multiple clients to it. Useful for team environments, CI pipelines, or production AI integrations.
Step 1: Generate a bearer token
openssl rand -hex 32
# e.g. a3f8c2d1e4b5a6...Step 2: Start the server
npx -y @monnify/mcp-server \
--apiKey=YOUR_API_KEY \
--secretKey=YOUR_SECRET_KEY \
--contractCode=YOUR_CONTRACT_CODE \
--env=production \
--transport=http \
--port=3000 \
--httpToken=YOUR_GENERATED_TOKENThe server will reject any /mcp request that does not carry Authorization: Bearer YOUR_GENERATED_TOKEN. If you start without --httpToken, it starts unauthenticated and logs a warning. That's fine for local development, not for any internet-facing deployment.
Step 3: Connect your AI client
# Claude Code
claude mcp add monnify --transport http http://localhost:3000/mcpFor clients that accept a custom header, set Authorization: Bearer YOUR_GENERATED_TOKEN alongside the endpoint URL.
Step 4: Put HTTPS in front of it. Terminate TLS at a reverse proxy (nginx, Caddy, Cloudflare Tunnel) before exposing the server outside your local network. Never send credentials over plain HTTP.
Health check (no auth required): GET /health
Run the server directly from source against the sandbox environment:
git clone https://github.com/monnify/monnify-mcp-server
cd monnify-mcp-server
npm install
npm run build
node build/cli.js \
--apiKey=YOUR_API_KEY \
--secretKey=YOUR_SECRET_KEY \
--contractCode=YOUR_CONTRACT_CODE \
--env=sandboxOr use the MCP Inspector to explore tools interactively:
npx @modelcontextprotocol/inspector \
node $(pwd)/build/cli.js \
--apiKey=YOUR_API_KEY \
--secretKey=YOUR_SECRET_KEY \
--contractCode=YOUR_CONTRACT_CODE \
--env=sandboxOpen http://localhost:5173 in your browser to browse and invoke tools.
- Credentials are passed as CLI args or environment variables and never stored
- All API responses are filtered through a whitelist, so internal Monnify fields are stripped before returning data to the AI client
- Destructive tools (deallocate, cancel mandate) are clearly labelled in their descriptions so the AI client warns before executing them
- Scope tool access with
--toolsto only expose what a given agent needs
MIT. Built by the Monnify team.