Build a Paid MCP Server: Charge Users from Inside Claude
The Problem: AI Agents That Earn Their Keep
You've built something valuable—a Claude MCP server that helps customers generate reports, design graphics, or run analyses. It works beautifully. Claude users love it. But then reality hits: how do you actually charge them?
Traditional payment flows break the agent experience. You can't embed Stripe forms into an LLM conversation. You can't ask Claude to handle OAuth redirects. The moment your user needs to "leave Claude and open a payment page," you've lost momentum, lost context, and probably lost the sale.
Meanwhile, for Vietnamese merchants and SaaS builders, there's another friction point: payment infrastructure maturity. VietQR standardized QR payments across every bank in Vietnam, but integrating it into an AI agent workflow? That's been missing—until now.
AgentPay VN solves this cleanly: a Python SDK + MCP server that lets Claude agents request payments, generate QR codes, and confirm settlement—all without your code ever touching the money. The funds flow straight to your merchant bank account.
Why MCP Servers Need Payment Flows
Model Context Protocol (MCP) servers are how Claude accesses external tools. Whether you're offering image generation, data processing, or scheduled reports, most high-value features need monetization.
Three reasons payment belongs inside MCP:
- Zero Friction: Users don't context-switch. Payment happens as part of the conversation.
- Agent Awareness: Claude can decide when to charge (e.g., "This report requires 5 credits—I'll generate a payment QR for you").
- Direct Settlement: With VietQR, funds hit your bank account instantly. No escrow, no platform holds.
AgentPay VN specifically: - Never holds funds – your bank receives money directly. - Transparent settlement – bank feeds auto-confirm when cash clears. - Open-source (MIT) – audit everything, deploy anywhere. - Simple 3-step flow – create request → send QR → await confirmation.
Installation & Setup
Step 1: Install the SDK
pip install agentpay-vn
That's it. No API keys to beg for, no dashboard onboarding. The SDK is lightweight (~50KB).
Step 2: Get Your Merchant Info
You'll need: - Merchant ID (issued by your bank when you enable VietQR) - Bank Account Number (where payments land) - Bank Code (VCB, ACB, etc.)
If you don't have VietQR yet, contact your bank. Most Vietnamese banks offer it free.
Step 3: Configure Environment
Create .env:
AGENTPAY_MERCHANT_ID=your_merchant_id
AGENTPAY_BANK_ACCOUNT=1234567890
AGENTPAY_BANK_CODE=VCB
AGENTPAY_WEBHOOK_URL=https://your-domain.com/webhook
Building Your First Paid MCP Server
The Core Flow: 3 Steps to Payment
Every transaction follows this pattern:
create_payment_request()– Generate a payment object with amount, description, and unique ID.send_checkout_url()– Format the QR code URL and send it to Claude (who shows it to the user).await_settlement()– Poll the bank feed until payment confirms.
Code Example: A Report Generation Server
Imagine a service where Claude can generate custom market reports for Vietnamese e-commerce sellers. Each report costs 50,000 VND. Here's how to build it:
# paid_mcp_server.py
import os
import uuid
from datetime import datetime
from agentpay_vn import PaymentClient, PaymentRequest
from mcp.server import Server
from mcp.types import Tool, TextContent
# Initialize the payment client
payment_client = PaymentClient(
merchant_id=os.getenv("AGENTPAY_MERCHANT_ID"),
bank_account=os.getenv("AGENTPAY_BANK_ACCOUNT"),
bank_code=os.getenv("AGENTPAY_BANK_CODE"),
)
# Create MCP server
server = Server("paid-report-generator")
# Store active requests in memory (use Redis/DB in production)
active_requests = {}
@server.call_tool()
def generate_ecommerce_report(product_category: str) -> str:
"""
Generates a custom market report for Vietnamese e-commerce sellers.
Costs 50,000 VND. Initiates payment flow.
"""
# Step 1: Create payment request
request_id = str(uuid.uuid4()) # Unique identifier for this transaction
payment_req = PaymentRequest(
amount=50000, # VND
description=f"Market report: {product_category}",
request_id=request_id,
return_url="https://your-domain.com/report-confirmed",
)
# Create the request with AgentPay
payment_data = payment_client.create_payment_request(payment_req)
# Store for later verification
active_requests[request_id] = {
"category": product_category,
"created_at": datetime.now(),
"status": "pending",
}
# Step 2: Generate checkout URL with embedded QR
checkout_url = payment_client.send_checkout_url(payment_data)
# Return QR to Claude (Claude displays to user)
return f"""
Payment Required: 50,000 VND
Please scan this QR code to pay:
{checkout_url}
Transaction ID: {request_id}
After payment, I'll generate your {product_category} market report within 2 minutes.
"""
@server.call_tool()
def check_payment_status(request_id: str) -> str:
"""
Check if payment has been received for a report request.
"""
if request_id not in active_requests:
return f"No active request found with ID: {request_id}"
# Step 3: Poll the bank feed for settlement confirmation
is_settled = payment_client.await_settlement(
request_id=request_id,
timeout_seconds=300 # Wait up to 5 minutes
)
if is_settled:
active_requests[request_id]["status"] = "paid"
# NOW generate the actual report
category = active_requests[request_id]["category"]
report_content = generate_report_content(category)
return f"""
✅ Payment confirmed!
Here's your market report for {category}:
{report_content}
"""
else:
return "⏳ Payment not yet received. Please verify your transfer and try again."
def generate_report_content(category: str) -> str:
"""Placeholder: Replace with actual report logic."""
return f"""
## Market Report: {category.title()}
**Market Size**: $2.4B (2024 projection)
**Growth Rate**: 18% YoY
**Top Platforms**: Shopee, Lazada, TikTok Shop
[Full report would follow...]
"""
if __name__ == "__main__":
server.run()
Line-by-line breakdown:
- Lines 1-9: Import AgentPay SDK + MCP primitives.
- Lines 11-16: Initialize PaymentClient with credentials from
.env. - Lines 22-24: Tool decorated with
@server.call_tool()makes it callable by Claude. - Lines 27-30: Create a unique
request_id(UUID) for each payment. - Lines 32-38: Build a
PaymentRequestobject: amount, description, and return URL. - Line 41:
create_payment_request()sends the payment object to AgentPay, getting back a QR code payload. - Line 46:
send_checkout_url()formats the QR as a scannable URL string. - Lines 51-58: Return the QR to Claude, who renders it in the chat.
- Lines 60-77: The
check_payment_status()tool lets Claude poll for settlement. - Line 70:
await_settlement()queries the bank feed until payment lands (or timeout). - Lines 72-78: Once confirmed, generate the paid content.
MCP Configuration for Claude
Register this server with Claude via .config/claude_desktop_config.json:
{
"mcpServers": {
"paid-report-generator": {
"command": "python",
"args": ["/path/to/paid_mcp_server.py"],
"env": {
"AGENTPAY_MERCHANT_ID": "your_merchant_id",
"AGENTPAY_BANK_ACCOUNT": "1234567890",
"AGENTPAY_BANK_CODE": "VCB",
"AGENTPAY_WEBHOOK_URL": "https://your-domain.com/webhook"
}
}
}
}
Now restart Claude Desktop, and the generate_ecommerce_report and check_payment_status tools appear in Claude's tool list.
Real-World Walkthrough: The Online Course Bot
Let's trace a real conversation:
User (in Claude): "I want a course on Vietnamese TikTok Shop seller tactics. Do you have anything?"
Claude (via MCP): Calls generate_ecommerce_report("TikTok Shop Seller Masterclass").
MCP Server:
1. Creates PaymentRequest(amount=150000, description="TikTok Shop Masterclass", request_id="abc123").
2. Returns QR code URL.
Claude: "Great! Here's a 150,000 VND course. Scan this QR to unlock it:" [QR code displayed]
User: Scans QR with their banking app → transfers 150,000 VND to your merchant account.
Bank: Processes the transfer within 30 seconds.
MCP Server (awaiting settlement): Detects the incoming transaction via bank feed.
Claude (after poll): "✅ Payment confirmed! Here's your course content: [full curriculum, video links, assignments]"
Your bank account: Now holds 150,000 VND, minus a small interchange fee (~0.5%).
Total time: ~2 minutes. Zero friction. Zero PCI compliance burden (no card data touched).
Advanced Tips & Best Practices
Do's and Don'ts
| ✅ Do | ❌ Don't |
|---|---|
Store request_id + amount in a database for audit trail |
Poll await_settlement() every second (use exponential backoff) |
| Use separate merchant accounts for testing vs. production | Hardcode credentials in code (always use .env or secrets manager) |
| Validate that amount matches your pricing before generating QR | Trust the request_id alone—verify bank amount when settlement arrives |
| Implement a webhook handler for bank notifications | Rely only on client-side polling for high-volume transactions |
| Set generous timeouts (5–10 min) for settlement polling | Assume QR code is valid forever—regenerate if it expires |
Webhook Integration (Production)
For higher reliability, listen for bank webhooks instead of polling:
from flask import Flask, request
app = Flask(__name__)
@app.route("/webhook", methods=["POST"])
def handle_settlement():
"""
Bank posts settlement confirmation here.
"""
payload = request.json
request_id = payload["request_id"]
amount = payload["amount"]
status = payload["status"] # "settled", "failed", etc.
if status == "settled":
# Unlock content for this request_id
unlock_premium_content(request_id)
return {"acknowledged": True}, 200
return {"error": "Unknown status"}, 400
This is more reliable than polling for production workloads.
Handling Failed Payments
if not is_settled:
# Payment timed out or failed
# Keep the request in "pending" state for 24 hours
# Let user retry or refund after 24h
return "⏳ Payment still pending. If you've paid, please wait a few minutes."
Comparison: AgentPay VN vs. Alternatives
| Factor | AgentPay VN | Stripe | PayPal |
|---|---|---|---|
| VietQR Support | ✅ Native | ❌ Needs workaround | ❌ Limited |
| Settlement Speed | Instant (bank-direct) | 2-7 days | 1-3 days |
| Holds Money? | ❌ No | ✅ Yes (escrow) | ✅ Yes |
| Setup Complexity | 5 min | 30 min | 20 min |
| MCP Integration | ✅ Built-in SDK | ❌ Manual HTTP calls | ❌ Manual HTTP calls |
| Vietnam-Optimized | ✅ Yes | ⚠️ Foreign entity | ⚠️ Foreign entity |
| Open-Source | ✅ MIT | ❌ Proprietary | ❌ Proprietary |
FAQ
Q: Does AgentPay ever hold my money?
A: No. The payment QR points directly at your merchant bank account. AgentPay only orchestrates the flow—the bank handles settlement. Your funds arrive in your account within minutes of the user's transfer.
Q: What if a user scans the QR but doesn't complete payment?
A: The await_settlement() call will timeout (default 5 minutes). Claude can then offer to regenerate the QR or suggest alternative payment methods. No charge occurs without confirmed settlement.
Q: Can I use AgentPay for non-VietQR payments?
A: Currently, AgentPay VN is optimized for VietQR (the national standard). For international payments, integrate Stripe or PayPal separately, though you'll lose the in-conversation flow benefits.
Q: Is there a fee?
A: AgentPay's SDK is free (MIT open-source). You pay only the bank's VietQR interchange fee (typically 0.3–0.5% per transaction), which is far lower than Stripe (2.9%) or PayPal (3.5%).
Key Takeaways
- Monetize inside Claude: Payment flows no longer break the agent experience. Users stay in the conversation.
- Three-step integration:
create_payment_request()→send_checkout_url()→await_settlement()– that's the entire flow. - Direct to your bank: No escrow, no platform holds. Funds land instantly in your merchant account.
- VietQR native: Purpose-built for Vietnamese merchants and users. Lowest fees in the region.
- Open-source: Audit the code, deploy on your infra, own your payment stack.
- Perfect for SaaS + AI: Reports, courses, analysis, design work – anything Claude generates can now be monetized.
Getting Started
Ready to build? Here's your launch checklist:
- Install:
pip install agentpay-vn - Register MCP server: Add config to Claude Desktop (
claude_desktop_config.json) - Set
.env: Merchant ID, bank account, bank code - Code your first tool: Use the report generator example as a template
- Test: Chat with Claude, trigger a payment request, verify settlement
- Deploy: Run on a server, configure webhooks for production reliability
Full documentation and examples: https://agentpay.servicesai.vn/v1/docs
GitHub repo (star it!): https://github.com/phuocdu/agentpay-vn
Your AI agent is now ready to earn its keep. 🚀