DEV Community

junter1989k-ai
junter1989k-ai

Posted on

AI agents can now accept payments in 10 countries — Pix, UPI, GCash, PromptPay, konbini, KakaoPay (one MCP server each)

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:

  1. create_payment_link → returns a hosted checkout URL for the buyer
  2. query_payment_status → pull-based polling, no webhooks needed
  3. (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)."
  ]
}
Enter fullscreen mode Exit fullscreen mode

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_KEY in Korean from Toss, Authentication failed from 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" }
  }
}
Enter fullscreen mode Exit fullscreen mode

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)