Naira Offramp MCP
Targets USDC on Arc as the source asset for an NGN offramp, supporting quotes and simulated payouts from Arc USDC to Nigerian bank accounts.
Integrates with Circle Agent Wallet through the Circle CLI, scaffolded for future wallet signing and live USDC settlement; the current demo does not access a wallet or move real funds.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Naira Offramp MCPQuote NGN 15,000 to my saved bank from my USDC on Arc."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Naira Offramp MCP
Ask an agent to cash out USDC on Arc into a Nigerian bank account. Save a verified bank account once; future requests use it by default.
Current release: a working MCP demo. Balances, rates, and bank payouts are simulated. Real Arc-to-NGN settlement is not implemented or verified, and live mode is unavailable.
The wallet integration targets Circle Agent Wallet, through the Circle CLI. The current demo does not access a wallet or move real funds.
Try it
Requires Node.js 22.13 or newer.
git clone https://github.com/Adeyemir/naira-offramp-mcp.git
cd naira-offramp-mcp
npm ci
npm run build
npm run demoThe isolated demo saves a fake recipient, quotes NGN 15,000, simulates approval and payout, then shows the remaining balance. It creates and removes its own temporary database and needs no credentials. Demo approvals are automatic only in this isolated script; MCP requests use the client's confirmation dialog.
Related MCP server: Peer Cash MCP
Connect to Codex or Claude Code
Build first. Replace /absolute/path below with your checkout's absolute path. Neither command requires an LLM API key in this project; your MCP client supplies the model.
Codex
codex mcp add naira-offramp --env OFFRAMP_MODE=demo -- node /absolute/path/naira-offramp-mcp/dist/cli.jsClaude Code
claude mcp add --env OFFRAMP_MODE=demo --transport stdio naira-offramp -- node /absolute/path/naira-offramp-mcp/dist/cli.jsRestart or reconnect your client after registering. See the official Codex MCP guide and Claude Code MCP guide for client configuration.
Start by asking:
Save my demo payout account: Demo Bank, account 0000000000, holder DEMO USER.
Approve the client's confirmation dialog. Then ask:
Quote NGN 15,000 to my saved bank from my USDC on Arc.
Execute that demo payout.
Show my payout status and remaining balance.
The client must support MCP form elicitation and display approval requests to a human. Tool arguments cannot grant approval. If your client lacks that feature, quotes and inspection still work; local review commands are available.
How it works
flowchart TD
Request[Your request in Codex or Claude] --> MCP[MCP tools]
MCP --> Bank[Saved bank or explicitly specified recipient]
Bank --> Quote[Quote NGN amount and maximum USDC debit]
Quote --> Approval[You review and approve]
Approval --> Settlement[Settlement adapter]
Settlement --> Provider[Payout provider]
Provider --> Status[Provider confirms bank payout]In this release, the settlement and provider are simulated. The Circle CLI signing helper is scaffolded for the future live integration. Live integration status explains the remaining work.
Tools
Tool | Purpose |
| Inspect the balance available for cashouts. |
| Show the saved recipient with a masked account number. |
| Verify and save a recipient after human approval. |
| Quote an exact NGN amount or a total USDC budget. |
| Obtain approval and execute the prepared payout once. |
| Inspect settlement and provider progress. |
| Show the ten most recent payouts. |
Amounts are decimal strings. currency: "NGN" means exact naira to receive; currency: "USDC" means maximum total USDC spend including fees. Normal tool results mask bank account numbers and omit settlement addresses. The approval dialog shows the full recipient and exact quote.
Quotes expire. Repeating execution of the same payout inspects its existing state. An uncertain submission is recorded for reconciliation and is never automatically resent. A chain confirmation alone does not mark a bank payout complete. Demo completion always returns simulated: true and bankPaid: false.
Development
npm run check
npm run build
npm test
npm run doctorTests cover the MCP protocol, human approval, amount precision, fees, quote expiry, concurrent execution, uncertain submission, and persistence across server restarts. They use fake providers and do not move real funds.
npm start runs the stdio MCP server; it waits for an MCP client. npm run dev runs the TypeScript entry point. Use usage and configuration for more detail.
Contributing and license
MIT. Contributions are welcome. Initial scope: Arc USDC → NGN. The provider and settlement interfaces allow future integrations without changing the MCP layer.
Available Tools
7 toolsexecute_payoutADestructiveIdempotent
Request human approval for the exact prepared quote, then execute it at most once. Never claims bank credit from a chain receipt alone. Repeated calls inspect the existing payout; uncertain submissions require reconciliation and must not be resent.
| Name | Required | Description | Default |
|---|---|---|---|
| payoutId | Yes | The ID returned by prepare_payout; never create a replacement to retry a payment. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive=true, idempotent=true, openWorld=true, but the description adds substantial non-structured context: human approval gating, at-most-once execution, the rule that a chain receipt alone never proves bank credit, and the reconciliation requirement for uncertain submissions. It is consistent with idempotentHint rather than contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, front-loaded with the core action and approval requirement, followed by safety constraints. Every sentence earns its place, though the wording is terse to the point of being clipped.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, open-world mutation tool with no output schema and a single fully-documented parameter, the description covers approval, at-most-once execution, retry/reconciliation, and credit-claiming semantics. It does not describe failure/error behavior or what an agent should report back after execution, leaving a small gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the payoutId description already carries the key guidance ('never create a replacement to retry'). The description adds no parameter-level syntax or constraints beyond what the schema states, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (execute a prepared payout) with the crucial qualifier 'at most once' and the approval step. An agent can immediately distinguish it from prepare_payout (which produces the quote) and from payout_status (which only inspects).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly defines the retry/repeat semantics ('Repeated calls inspect the existing payout'), the reconciliation requirement for uncertain submissions, and the prohibition on resending. It does not explicitly name payout_status or payout_history as alternatives for pure inspection, but the context is clear enough to route correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_balanceARead-onlyIdempotent
Inspect the USDC balance for Arc cashouts. Demo values are simulated; this does not move funds.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, idempotent, non-destructive and closed-world, so the bar is lower, and the description still adds meaningful context the annotations cannot express: the values are simulated demo data and no funds move. That is exactly the kind of caveat an agent needs before reporting a balance as real.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler; the resource and the demo-value caveat are both front-loaded. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read tool whose annotations already declare the safety profile and with no output schema required, the description is nearly complete. Only the return shape (a balance figure) is left implicit, which is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the rubric the baseline is 4. There is nothing for the description to clarify about inputs, and it does not need to.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource (inspect the USDC balance) and scopes it to Arc cashouts, which separates it from the payout/bank siblings. It stops short of explicitly contrasting with any named sibling, but the intent is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'for Arc cashouts' hints at context, but the description never says when to call this versus alternatives like payout_status or payout_history, nor that it should precede prepare_payout/execute_payout. No exclusions or prerequisites are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_default_bankARead-onlyIdempotent
Get the saved recipient's bank, name, and masked account ending. No bank is chosen automatically.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is covered. The description usefully adds that no bank is auto-selected and that the account ending is masked, which is genuine behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences, front-loaded with the action and return payload, neither of which is padding. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and no output schema, the description carries the burden of conveying the return shape, which it does (bank, name, masked ending). It stops short of stating what happens when no saved bank exists, a minor gap for such a simple read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; there are no arguments whose meaning could be clarified. Nothing in the description misrepresents the parameterless contract.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb (Get) and resource (saved recipient's bank) and names the returned fields (bank, name, masked account ending), which lets an agent distinguish it from set_default_bank. It never explicitly names siblings, but the get-vs-set contrast is clear from the naming.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use statement relative to prepare_payout, execute_payout, or set_default_bank. The clue that 'no bank is chosen automatically' implies behavior rather than routing guidance, so the agent is left to infer usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
payout_historyARead-onlyIdempotent
List the ten most recent payouts in this local mode/profile. Bank account numbers are masked.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and non-open-world, so safety is covered. The description adds useful behavior beyond that: results are capped at ten entries, scoped to the local mode/profile, and bank account numbers are masked — the masking note is genuinely valuable context not derivable from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core action and scope. No filler; every clause (cap of ten, local profile, masking) earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter, read-only list tool with full annotation coverage and no output schema, the description is nearly sufficient. It could mention ordering or an empty-history case, but nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters (schema coverage 100%), so the baseline is 4. Nothing about the description conflicts with the empty schema, and no parameter meaning needs to be added.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (payouts) with a clear scope: the ten most recent in the local profile. It doesn't explicitly contrast itself with payout_status, though the 'history/list' framing versus a single-status lookup is reasonably inferable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no prerequisites, and no mention of alternatives such as payout_status or get_balance. The agent must infer the use case entirely from the tool name and 'ten most recent' scope.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
payout_statusARead-onlyIdempotent
Inspect an existing payout. Reports completed only after the payout provider confirms completion. A demo completion is simulated and always has bankPaid=false. Never sends funds.
| Name | Required | Description | Default |
|---|---|---|---|
| payoutId | Yes | The ID returned by prepare_payout; never create a replacement to retry a payment. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive, open-world behavior, so the bar is lower. The description still adds genuine value beyond them: completion is only reported after the provider confirms, demo completions are simulated with bankPaid=false, and no funds are ever sent. It stops short of describing latency, polling expectations, or error states.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action and scoping constraint, followed by return-value caveats. No filler and nothing buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description reasonably covers the most load-bearing return semantics (completion only on provider confirmation, demo bankPaid=false). It leaves the overall response shape unspecified, but for a one-parameter read tool with full safety annotations, the agent has what it needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single payoutId parameter is fully documented in the schema (including the "never create a replacement to retry" warning). The description adds nothing about the parameter, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Inspect an existing payout") and immediately separates itself from the write siblings with "Never sends funds," so an agent can distinguish it from execute_payout and prepare_payout without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for checking status of an already-created payout (vs. creating/executing one), but it never explicitly names when to use this instead of payout_history or execute_payout. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_payoutA
Prepare a quote; no funds move. NGN means exact naira to receive; USDC means maximum total spend including all fees. Defaults to the saved bank. Supply a bank only when the user explicitly requests another destination. Repeated calls create separate quotes.
| Name | Required | Description | Default |
|---|---|---|---|
| bank | No | ||
| amount | Yes | Positive decimal text, e.g. 15000 or 10. Never use floating point numbers. | |
| currency | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real context beyond the annotations: it clarifies that despite readOnlyHint=false nothing moves funds, and 'repeated calls create separate quotes' explains the non-idempotent behavior in practical terms. Currency semantics (NGN = exact receive, USDC = max total spend incl. fees) is behavior an agent cannot get from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each carrying distinct information, with the safety-critical 'no funds move' claim front-loaded. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the essential behaviors for a quote tool (no fund movement, currency meaning, bank defaults, non-idempotency). It stops short of describing the quote's lifecycle or expiry, which matters given there is no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 33% schema coverage, the description carries needed weight: it defines currency semantics precisely and explains when to omit bank (defaults to saved). Amount format is left to the schema, which already covers it well.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action ('Prepare a quote') and immediately scopes it ('no funds move'), which cleanly separates it from execute_payout among the siblings. An agent can tell this is a quote-creation step, not a transfer.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete routing rules: default to the saved bank, supply a bank only when the user explicitly asks for another destination, and warns that repeated calls make separate quotes. It never explicitly names execute_payout as the follow-up step, which is the one missing link.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_default_bankADestructive
Verify and save a default Nigerian bank account once. Requires human approval through the MCP client. Demo accepts only Demo Bank / 0000000000 / DEMO USER.
| Name | Required | Description | Default |
|---|---|---|---|
| bank | Yes | Nigerian bank name. In demo mode: Demo Bank. | |
| expectedName | Yes | Expected full account holder name. In demo mode: DEMO USER. | |
| accountNumber | Yes | Ten-digit bank account. In demo mode: 0000000000. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, openWorldHint=true, idempotentHint=false and destructiveHint=true. The description adds genuinely new behavior: human approval is required, the account is verified before saving, and it happens only once. It does not explain why destructiveHint is true or what happens to a previously saved default account, which is the remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with zero filler; the core action is front-loaded and the approval prerequisite and demo constraints follow in priority order.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-required-parameter mutation with no output schema and full schema coverage, the description covers the essential non-schema facts: verification, human approval, one-time nature, and demo constraints. It is nearly complete, lacking only what happens to a pre-existing default.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already defines each field, including min/max lengths and the 10-digit pattern. The description only repeats demo values, adding no format or validation meaning beyond what the schema documents. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a concrete verb+resource: verify and save a default Nigerian bank account. It implies a one-time operation ('once'), which distinguishes it implicitly from the sibling get_default_bank. It does not explicitly name or contrast with that sibling, keeping it just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a prerequisite ('requires human approval through the MCP client') and demo-mode values, which is useful context, but it never states when to use this tool versus get_default_bank or when not to (e.g., if a default already exists). The set-vs-get distinction must be inferred from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.1.0- First observed
execute_payout - First observed
get_balance - First observed
get_default_bank - First observed
payout_history - First observed
payout_status - First observed
prepare_payout - First observed
set_default_bank
TDQS
Scored across 7 tools
Each tool targets a distinct action in the payout lifecycle: reading balance, managing the saved bank, listing history, inspecting a single payout, and the prepare/execute two-phase flow. prepare_payout vs execute_payout and payout_history vs payout_status are clearly delineated by descriptions that emphasize quote-vs-move and list-vs-inspect.
All names use consistent snake_case, and the verb_noun pattern (get_balance, set_default_bank, prepare_payout, execute_payout) is clear. The two noun-only names (payout_history, payout_status) are a minor deviation but remain readable and unambiguous.
Seven tools is well-scoped for an offramp flow: balance, bank config, quote, execution, status, and history. Every tool maps to a needed step, with no redundant or filler operations.
The surface covers the full payout lifecycle from bank setup through quoting, execution, status, and history, including a safety-oriented reconciliation path. Minor gaps exist around cancellation/refund or explicit fee-preview, but core workflows are covered.
Maintenance
Related MCP Connectors
Human-governed Arc agent services, live demand signals, quotes, feedback, and USDC commerce.
Nigeria payments for AI agents — bank transfer / USSD via Paystack. Never holds funds.
Non-custodial stablecoin bill-pay rails on Celo & Base for AI agents, settled on-chain via MCP.
Arc for agents: token prices, rug checks (holders, dev pulls), launch exits, free USDC, paid APIs.
Related MCP Servers
- FlicenseNot gradedqualityAmaintenanceEnables agents to vet merchants, create and verify USDC charges and invoices, assess trust and tokenized-asset authenticity, and manage provable books on Base, all non-custodially.49 npm-

Peer Cash MCPofficial
AlicenseAqualityFmaintenancePrepare custody-separated Base USDC cash-out plans, list supported fiat rails, and track settlement state through Peer Cash.933 npmMIT- AlicenseNot gradedqualityBmaintenanceEnables agents to accept and spend payments via Rill's network, including pay links, wallets, and Connect onboarding.MIT
- AlicenseAqualityBmaintenanceNon-custodial stablecoin bill payments (airtime, data, electricity, cable, education) on Celo mainnet, reachable via x402 (zero setup, EIP-3009), a linked wallet's PIN-gated MCP/A2A tool catalog, or plain natural language on Telegram/WhatsApp/X.101MIT