Last week I built an MCP server so AI agents could accept payments in Taiwan. This week the same pattern grew into ten countries — one MCP server per country, each wrapping the payment rails that country actually uses:
| Country | MCP endpoint | Local rails |
|---|---|---|
| 🇹🇼 Taiwan | https://mcp.wishpool.app/mcp |
ECPay + NewebPay, convenience stores, government e-invoices |
| 🇯🇵 Japan | https://mcp-jp.wishpool.app/mcp |
konbini コンビニ, PayPay (KOMOJU) |
| 🇰🇷 Korea | https://mcp-kr.wishpool.app/mcp |
cards, KakaoPay / NaverPay (Toss Payments) |
| 🇮🇩 Indonesia | https://mcp-id.wishpool.app/mcp |
GoPay, QRIS, Alfamart cash (Midtrans) |
| 🇮🇳 India | https://mcp-in.wishpool.app/mcp |
UPI — Google Pay / PhonePe / Paytm (Razorpay) |
| 🇧🇷 Brazil | https://mcp-br.wishpool.app/mcp |
Pix, boleto (Mercado Pago) |
| 🇵🇭 Philippines | https://mcp-ph.wishpool.app/mcp |
GCash, Maya (PayMongo) |
| 🇹🇭 Thailand | https://mcp-th.wishpool.app/mcp |
PromptPay QR, TrueMoney (Opn/Omise) |
| 🇲🇾 Malaysia | https://mcp-my.wishpool.app/mcp |
FPX online banking, DuitNow QR (Billplz) |
| 🇻🇳 Vietnam | https://mcp-vn.wishpool.app/mcp |
MoMo wallet QR — zero-setup sandbox demo |
All ten are on the official MCP Registry under app.wishpool/*, MIT-licensed, zero runtime dependencies.
Why per-country servers?
Global processors skip the rails locals actually pay with. A Japanese buyer wants to pay at 7-Eleven. An Indian buyer scans UPI. A Brazilian uses Pix. A Filipino uses GCash. Those rails were built for humans clicking through checkout pages — there is no agent-ready API for "let my customer pay the way they normally pay."
Each server is a stateless translation layer (~500 lines of Node, no database): it turns one country's hosted-checkout API into two or three MCP tools. Same shape everywhere:
-
create_payment_link→ returns a hosted checkout URL for the buyer -
query_payment_status→ pull-based polling, no webhooks needed - (Korea only)
confirm_payment— Toss requires a server-side approval within 10 minutes of buyer authentication, so the flow is exposed honestly as a third tool
Bring-your-own credentials: the merchant's API keys ride along as HTTP headers on every request and are used in memory only. Funds always flow buyer → gateway → merchant. The servers never touch money — which also keeps them clean legally in every jurisdiction.
Designing for weak models
Most MCP clients aren't frontier models — plenty are small local models that skim tool descriptions. So the guidance lives in the tool results, at the right moment, not in documentation nobody reads:
{
"payment_url": "https://...",
"next_steps": [
"1. Give payment_url to the buyer and ask them to open it and pay.",
"2. Call query_payment_status with order_id=KR2607091542XYZ every ~15 seconds.",
"3. When status becomes IN_PROGRESS, immediately call confirm_payment (you have only 10 minutes)."
]
}
Every query_payment_status state carries a one-line next hint: "Buyer authenticated — NOW call confirm_payment", "Link expired — create a new one". A 7B model can follow that.
Verification without opening ten merchant accounts
I didn't register merchant accounts in ten countries (each KYC would take weeks). Instead:
- Spec verification: every request format checked against official docs, and for signature-based gateways, byte-compared against production SDKs.
-
Fake-key live probes: every e2e suite fires a fake key at the real production API and asserts the gateway's own auth error comes back (
UNAUTHORIZED_KEYin Korean from Toss,Authentication failedfrom Razorpay…). That proves the wire path is real. - Zero-setup demos where possible: Taiwan (ECPay's public sandbox) and Vietnam (MoMo's documented public sandbox credentials) do real sandbox transactions end-to-end — try them with no credentials at all.
- A daily canary replays those probes against every gateway and emails me if any fingerprint changes — so if a PSP moves an endpoint, I know before the first user does. This already paid off during the build: PayMongo's legacy Links API turned out to be dead (404 behind the gateway), which the probe caught, and I shipped Checkout Sessions instead.
The rest of the verification is the BYO architecture itself: the first merchant who brings a real key is the live test, failures are loud and readable, and a beacon mails me the moment a real-key call fails for any non-auth reason.
Try it
Point any remote-MCP client (Claude Desktop / Claude Code / Cursor) at the Vietnam or Taiwan endpoint — both work instantly with no credentials:
{
"mcpServers": {
"vietnam-payments": { "type": "http", "url": "https://mcp-vn.wishpool.app/mcp" }
}
}
Ask your agent to "create a 50,000 VND payment link" and watch it come back with a real MoMo sandbox checkout URL.
All repos: github.com/junter1989k-ai — feedback and country requests welcome.
Top comments (0)