Build a Paid MCP Server: Charge Users from Claude

2026-06-28 · AgentPay VN

mcpai-agentspaymentspythonvietqr

The Problem: Your AI Agent Creates Value—But Can't Get Paid

Imagine you've built an exceptional Claude-powered MCP server. It drafts contracts, analyzes legal documents, generates investment reports—work that normally costs hundreds per hour. Users love it. But here's the catch: they never pay.

Software-as-a-service models assume recurring subscriptions. Agents, however, live inside Claude and other LLMs. Users invoke them for discrete tasks. How do you charge for a single contract draft? A one-time document review? A homework helper that works 5 minutes per day?

Traditional payment processors (Stripe, PayPal) require user accounts, redirects, and friction. By the time your agent redirects a user to a checkout page, the conversation thread dies. The user disappears.

AgentPay VN solves this: generate a QR code, embed it in the chat, user scans and pays—in 10 seconds flat. The agent resumes immediately upon settlement confirmation. No accounts. No redirects. No abandonment.


Why VietQR? Why AgentPay VN?

VietQR (Việt QR) is Vietnam's instant bank-to-bank payment standard. Scan once, money lands in your account in seconds. It's the infrastructure that powers every Shopee, Grab, and café in Vietnam.

AgentPay VN wraps this power into three lines of Python:

request = create_payment_request(amount=50000, description="Contract analysis")
checkout_url = request.checkout_url  # Send this to Claude as a clickable QR link
await await_settlement(request.id)    # Block until payment confirmed

Key facts: - Open-source MIT license – full transparency, zero vendor lock-in - No escrow – money goes straight to your bank account - Bank-verified settlement – instant confirmation via bank feed - MCP-ready – Claude integration in ~50 lines of config

If your users are in Vietnam or Southeast Asia, this is the fastest payment path to production.


Architecture: How It Works

Three-step flow:

  1. Create Payment Request → AgentPay generates a unique checkout URL pointing to your merchant bank account
  2. Send Checkout Link → Agent embeds the link or QR code in the Claude chat
  3. Await Settlement → Agent waits for bank confirmation, then proceeds (unlock file, generate next section, etc.)

Critical: AgentPay never touches the money. It's middleware between your Claude agent and the banking system. You retain full custody. This is not a payment processor in the traditional sense—it's a bridge.


Step 1: Install and Configure AgentPay VN

Local Setup

pip install agentpay-vn

Then set environment variables:

export AGENTPAY_MERCHANT_ID="your_merchant_id"
export AGENTPAY_API_KEY="your_api_key"
export AGENTPAY_BANK_ACCOUNT="your_vietqr_link"

Get these from https://agentpay.servicesai.vn/v1/docs (free registration for testing).

MCP Server Registration

Create a file claude_config.json in your project:

{
  "mcpServers": {
    "agentpay": {
      "command": "agentpay-mcp",
      "args": ["serve"],
      "env": {
        "AGENTPAY_MERCHANT_ID": "your_merchant_id",
        "AGENTPAY_API_KEY": "your_api_key",
        "AGENTPAY_BANK_ACCOUNT": "https://pay.vietqr.io/xxx"
      }
    }
  }
}

Add this to Claude's MCP configuration. Restart Claude Desktop. You now have three new tools: - create_payment_request(amount, description, user_id) - check_payment_status(request_id) - await_settlement(request_id, timeout_seconds)


Step 2: Build Your Paid Agent (Code Walkthrough)

Let's build a paid homework helper. Users pay ₫50,000 (~$2 USD) per problem solved.

Handler Function

from agentpay_vn import create_payment_request, await_settlement
import time

async def solve_homework_problem(problem_text: str, user_id: str):
    """
    Solve a homework problem only after payment confirmed.
    """

    # Step 1: Create payment request
    # amount_vnd=50000 (₫50,000), description shown on QR screen
    payment_req = create_payment_request(
        amount_vnd=50000,
        description="Homework problem solution",
        metadata={"user_id": user_id, "problem_hash": hash(problem_text)}
    )

    # Step 2: Tell the user to pay
    # In Claude, this becomes a clickable link + QR code
    print(f"🔒 Solution locked. Pay here to unlock: {payment_req.checkout_url}")
    print(f"Payment ID: {payment_req.id}")

    # Step 3: Wait for settlement (block until confirmed)
    # timeout_seconds=300 = 5 minute window; adjust for your UX
    try:
        settlement = await_settlement(
            request_id=payment_req.id,
            timeout_seconds=300
        )
        print(f"✅ Payment confirmed! Settlement ID: {settlement.id}")
    except TimeoutError:
        print("❌ Payment not received within 5 minutes. Try again.")
        return None

    # Step 4: Solve the problem (payment confirmed)
    solution = solve_with_claude(problem_text)
    return solution

def solve_with_claude(problem_text: str) -> str:
    """
    Placeholder: call Claude API to generate solution.
    """
    return f"Solution to '{problem_text[:50]}...' [Premium content unlocked]\n\nStep 1...\nStep 2...\n"

Line-by-line breakdown:

  1. create_payment_request() – generates a unique checkout URL linked to your bank account. The metadata dict stores context (who paid, what for) for reconciliation.
  2. The checkout_url is what you send to Claude. The user scans the QR code with their phone, authenticates with their bank, and ₫50,000 transfers instantly.
  3. await_settlement() is a blocking call. It polls AgentPay's bank feed until the exact amount lands in your account. Then it returns.
  4. Once settlement succeeds, you proceed—unlock the content, continue the conversation, etc.

Integrate into MCP Tool

In your MCP server's tools.py:

from mcp.server.models import Tool, TextContent
from mcp.types import ToolUseBlock

TOOLS = [
    {
        "name": "solve_homework",
        "description": "Solve a math or physics problem. Requires ₫50,000 payment.",
        "inputSchema": {
            "type": "object",
            "properties": {
                "problem": {
                    "type": "string",
                    "description": "The homework problem to solve"
                }
            },
            "required": ["problem"]
        }
    }
]

async def handle_tool_call(tool_name: str, arguments: dict):
    if tool_name == "solve_homework":
        result = await solve_homework_problem(
            problem_text=arguments["problem"],
            user_id="claude_user_id"  # Extract from context
        )
        return result

When Claude invokes solve_homework, your agent shows the payment QR, waits for settlement, then returns the solution.


Real-World Example: A Café Loyalty Agent

Imagine a Slack bot for a Vietnamese café chain. Customers text:

"Buy me a coffee at the Nguyen Hue branch"

The agent responds:

"Sure! Your order: 1x Espresso (₫45,000). Scan to pay: [QR code]. Estimated pickup: 12 minutes."

Customer scans. Money goes to the café's Vietcombank account. Agent receives settlement confirmation within 3 seconds. It automatically: 1. Notifies the barista (via kitchen display system) 2. Sends a pickup reminder to the customer 3. Logs the transaction for loyalty points

No Stripe fees. No PayPal disputes. No user account creation. Just: scan → pay → brew.


Do's and Don'ts

Do Don't
Set timeout_seconds based on real behavior (300 for patient users, 60 for impatient) Don't rely on await_settlement() in a 1-second response; it will timeout
Store request.id in a database for reconciliation and refunds Don't lose the request ID; you'll need it to dispute or refund
Use metadata to tag payments by user, feature, or content Don't store sensitive data (passwords, SSNs) in metadata
Test with small amounts (₫1,000) first Don't go live with real money without testing the full flow
Catch TimeoutError and retry gracefully Don't spam users with repeat payment links; offer alternatives
Verify settlement before delivering premium content Don't trust the checkout_url alone; always confirm with await_settlement()

Advanced: Tiered Pricing and Retries

For a more sophisticated agent, implement pricing tiers:

PRICES = {
    "basic": 20000,      # ₫20k – high school homework
    "advanced": 100000,  # ₫100k – university essays
    "premium": 500000    # ₫500k – research papers
}

async def solve_homework_tiered(problem: str, tier: str, user_id: str):
    amount = PRICES.get(tier, PRICES["basic"])

    # Create + display payment
    payment = create_payment_request(
        amount_vnd=amount,
        description=f"Homework solution ({tier})"
    )
    print(f"Pay ₫{amount:,} → {payment.checkout_url}")

    # Wait with retry logic
    max_attempts = 3
    for attempt in range(1, max_attempts + 1):
        try:
            await_settlement(payment.id, timeout_seconds=300)
            break  # Success
        except TimeoutError:
            if attempt < max_attempts:
                print(f"Attempt {attempt} failed. Retrying...")
                time.sleep(10)
            else:
                print("Payment failed after 3 attempts. Canceling.")
                return None

    # Proceed with solution
    return generate_solution(problem, tier)

FAQ

Q: What if the user's bank is down? A: await_settlement() will timeout after your specified duration (default 300s). The payment request remains valid; the user can retry. Your agent should gracefully offer a retry link.

Q: Can I offer refunds? A: AgentPay doesn't handle refunds (it's a payment bridge, not a processor). You'll refund manually via your bank or a separate refund tool. Log the original transaction ID for reconciliation.

Q: Does this work outside Vietnam? A: VietQR is Vietnam-only. Users must have Vietnamese bank accounts. If you need global payments, consider Stripe for non-VN users and AgentPay VN for Vietnam.

Q: What are the fees? A: AgentPay VN itself has no fees (it's open-source). Your bank may charge a small transaction fee per QR payment (typically ₫1,000–5,000). Check with your merchant bank.


Key Takeaways


Get Started Now

  1. Install: pip install agentpay-vn
  2. Read the docs: https://agentpay.servicesai.vn/v1/docs
  3. Explore the source: https://github.com/phuocdu/agentpay-vn
  4. Register for a test merchant account and deploy your first paid agent today.

Your Claude agents are valuable. Now they can get paid for it—in seconds, with a QR code.

Get started →

← All posts