Build a Paid MCP Server: Charge Users Inside Claude
The Problem: Your MCP Server Works, But Who Pays?
You've built an MCP server that provides real value—maybe it generates images, runs analyses, or accesses premium data. Your Claude users love it. But here's the friction point: how do you monetize it?
Traditional payment gateways require redirects, browser windows, and manual confirmation flows. That breaks the magic of Claude's seamless context. You end up with:
- Users abandoning mid-conversation to complete checkout
- Complex OAuth/webhook management
- No native payment UI inside Claude
- Merchant account setup delays
- Risk of handling user funds (you don't want that liability)
Today, there's a cleaner way: AgentPay VN lets your MCP server generate a VietQR payment link, embed it in Claude's context, and settle straight to your bank account—no middleman holding your money, no complex integrations.
Why VietQR + MCP Is a Winning Combo
VietQR is Vietnam's instant payment standard. It's ubiquitous, frictionless, and secure. When combined with an MCP server, you unlock a flow that feels native to Claude:
- User requests a premium feature inside Claude conversation
- Your MCP server generates a QR code (3-line Python call)
- User scans and pays via their banking app
- Settlement confirmed via bank feed → feature unlocked
- No redirect, no tab-switching, minimal friction
AgentPay VN handles the complexity—it's open-source (MIT license), Python-native, and specifically designed for this agent-first workflow.
What You're NOT Getting
- ❌ AgentPay holding your money in escrow
- ❌ Dependency on a third-party payment processor
- ❌ Complex webhook retry logic
- ❌ PCI compliance headaches
What You ARE Getting
- ✅ Direct bank settlement (your account, your rules)
- ✅ 3-line Python payment flow
- ✅ Claude-native MCP integration
- ✅ Open-source transparency (MIT license)
- ✅ Bank feed confirmation (pull, don't push)
Installation & Setup: 5 Minutes to Your First Payment
Step 1: Install AgentPay VN
pip install agentpay-vn
Verify installation:
python -c "import agentpay_vn; print(agentpay_vn.__version__)"
Step 2: Configure Your Merchant Account
You'll need: - VietQR merchant ID (register at your bank or via VietQR portal) - Bank account details (verified account where payments settle) - Optional: Merchant name, logo, transaction reference pattern
Store these in environment variables:
export VIETQR_MERCHANT_ID="your_merchant_id"
export MERCHANT_BANK_ACCOUNT="your_account_number"
export MERCHANT_BANK_CODE="970012" # Example: VIETCOMBANK
Step 3: Deploy the MCP Server
AgentPay VN ships with a pre-built MCP server:
agentpay-mcp --port 3000
This starts a local MCP server on http://localhost:3000 that Claude can call.
Building Your First Paid Feature: The Code
Let's build a real scenario: an image enhancement bot that charges $2 USD (~50,000 VND) per premium enhancement.
Example 1: Payment Request Flow
from agentpay_vn import PaymentGateway, PaymentRequest
import json
import time
# Initialize gateway with your credentials
gateway = PaymentGateway(
merchant_id="MERCHANT_ID",
bank_account="1234567890",
bank_code="970012"
)
# User requests premium image enhancement
def create_premium_enhancement_payment():
"""Create a payment request for premium image processing."""
# Step 1: Define the payment
payment = PaymentRequest(
amount=50000, # 50,000 VND (~$2 USD)
currency="VND",
description="Premium Image Enhancement - 4K Upscaling",
reference_id="enhance_img_001", # Unique ID for this request
merchant_name="ImagePro Bot",
expiry_seconds=300 # QR valid for 5 minutes
)
# Step 2: Generate VietQR payload
qr_data = gateway.create_payment_request(payment)
# qr_data contains:
# - qr_code_url: Direct link to PNG QR image
# - qr_string: Raw QR content (for embedding)
# - checkout_url: Human-readable payment link
# - payment_id: Internal tracking ID
return {
"status": "awaiting_payment",
"amount": 50000,
"currency": "VND",
"qr_code": qr_data["qr_code_url"],
"payment_id": qr_data["payment_id"],
"expires_at": qr_data["expires_at"]
}
# Create the payment
payment_info = create_premium_enhancement_payment()
print(json.dumps(payment_info, indent=2))
Line-by-line breakdown:
- Lines 8-12: Initialize gateway with merchant credentials from environment
- Lines 16-28: Create a PaymentRequest object with amount, description, and reference ID
- Line 31: Call create_payment_request() to generate VietQR code
- Line 33-40: Returns structured payment info including QR code URL
The QR code is now ready to show the user. They scan it with their banking app, confirm the 50,000 VND transfer, and your bank account receives the money.
Example 2: Confirm Settlement & Unlock Feature
import asyncio
from agentpay_vn import PaymentGateway
gateway = PaymentGateway(
merchant_id="MERCHANT_ID",
bank_account="1234567890",
bank_code="970012"
)
async def wait_for_payment_settlement(payment_id: str, timeout: int = 600):
"""
Poll bank feed to confirm payment settlement.
Returns True when 50,000 VND deposit is detected.
"""
start_time = time.time()
check_interval = 5 # Poll every 5 seconds
while (time.time() - start_time) < timeout:
# Check bank feed for incoming transfer matching payment_id
settlement = await gateway.await_settlement(
payment_id=payment_id,
expected_amount=50000
)
if settlement["status"] == "confirmed":
# Payment received! Unlock the feature
return {
"success": True,
"transaction_id": settlement["transaction_id"],
"amount_received": settlement["amount"],
"timestamp": settlement["settled_at"]
}
# Not yet confirmed, wait and retry
await asyncio.sleep(check_interval)
# Timeout reached
return {"success": False, "error": "Payment not received within timeout"}
# In your MCP handler
async def handle_premium_enhancement_request(image_url, payment_id):
# Wait for payment to settle
settlement = await wait_for_payment_settlement(payment_id)
if settlement["success"]:
# Process premium enhancement
enhanced_image = process_4k_upscaling(image_url)
return {
"status": "completed",
"image_url": enhanced_image,
"paid_at": settlement["timestamp"]
}
else:
return {"status": "payment_timeout", "error": settlement["error"]}
# Call it
result = asyncio.run(
handle_premium_enhancement_request(
"https://example.com/image.jpg",
"enhance_img_001"
)
)
print(result)
Key points:
- Lines 11-35: await_settlement() polls your bank feed (via bank API) for incoming transfers
- Line 22: Matches incoming transfer amount and reference ID
- Lines 24-28: Returns settlement confirmation with transaction ID
- Lines 33-45: Once payment is confirmed, unlock premium feature (e.g., 4K upscaling)
- No webhook complexity: You pull data from the bank, not push/handle webhooks
Claude MCP Configuration: Connect Your Server
Now configure Claude to call your MCP server. Add this to ~/.claude/mcp_servers.json:
{
"mcpServers": {
"agentpay-image-bot": {
"command": "python",
"args": ["-m", "agentpay_vn.mcp_server"],
"env": {
"VIETQR_MERCHANT_ID": "your_merchant_id",
"MERCHANT_BANK_ACCOUNT": "1234567890",
"MERCHANT_BANK_CODE": "970012",
"FEATURE_PRICING": "{\"premium_enhancement\": 50000, \"batch_processing\": 150000}"
}
}
}
}
Clause will now recognize tools like create_payment and confirm_settlement.
Real-World Walkthrough: Online Course Bot
Imagine you're building an AI tutoring agent that offers: - Free tier: Basic concept explanations - Premium tier: Personalized problem sets, live code review ($5/month = ~125,000 VND)
User interaction:
User: "I'm stuck on async/await in Python."
Bot: "Here's a free explanation...\n\nWant me to generate 10 personalized
practice problems with solutions? That's a premium feature ($5).\n\n[QR Code Image]\n
Scan to pay. Once settled, I'll generate your problem set."
User: Scans QR → Pays from banking app
Bot: (Polls settlement) → "Payment confirmed! Here are your 10 problems..."
Code snippet:
class TutoringAgent:
def __init__(self, gateway):
self.gateway = gateway
self.user_limits = {} # Track free tier usage
async def handle_request(self, user_id, request_type):
if request_type == "basic_explanation":
return await self.free_tier_explanation()
elif request_type == "problem_set":
# Check if user already paid this month
if self.user_has_active_subscription(user_id):
return await self.generate_problems(user_id)
# Create payment for problem set
payment = await self.gateway.create_payment_request(
PaymentRequest(
amount=125000,
description="Premium Problem Set - Python Async/Await",
reference_id=f"course_{user_id}_{int(time.time())}"
)
)
return {
"status": "payment_required",
"message": "Unlock 10 personalized problems",
"qr_code": payment["qr_code_url"],
"payment_id": payment["payment_id"]
}
This pattern scales to SaaS, consulting bots, data access, and more.
Common Patterns: Do's and Don'ts
| Do | Don't |
|---|---|
| ✅ Show QR code before asking user to pay | ❌ Auto-charge without confirmation |
| ✅ Set 5-10 min QR expiry (user pays quickly) | ❌ Keep QR valid for 24+ hours (security risk) |
✅ Store payment_id and transaction_id for audit |
❌ Rely on memory; lose receipts on restart |
| ✅ Poll bank feed every 5-10 seconds | ❌ Expect instant settlement (banks take 30-60s) |
| ✅ Provide fallback for payment timeout | ❌ Hang forever waiting for payment |
| ✅ Include merchant name in payment description | ❌ Use generic "Payment" (confuses users) |
Advanced Tips
Tip 1: Batch Payments for Team Features
# Charge $10 once for a 5-person team
payment = gateway.create_payment_request(
PaymentRequest(
amount=250000, # ~$10
description="Team License - 5 seats - valid 1 year",
reference_id=f"team_license_{team_id}"
)
)
Tip 2: Retry Logic for Network Hiccups
async def robust_await_settlement(payment_id, retries=3):
for attempt in range(retries):
try:
return await gateway.await_settlement(payment_id)
except ConnectionError:
if attempt < retries - 1:
await asyncio.sleep(2 ** attempt) # Exponential backoff
else:
raise
Tip 3: Log Everything for Reconciliation
import logging
logger = logging.getLogger("payments")
logger.info(f"Payment created: {payment_id}, amount: {amount}")
logger.info(f"Settlement confirmed: {payment_id}, txn: {transaction_id}")
# Later: Export logs to CSV for accounting
FAQ
Q: Is AgentPay VN safe? Does it hold my money? A: No—AgentPay VN is open-source (MIT license) and never touches your money. The QR code points directly to your merchant bank account. Settlement happens via your bank's infrastructure, not a third party.
Q: Can I use this outside Vietnam? A: VietQR is Vietnam-specific. If you're outside Vietnam, you'd need a Vietnamese bank account. The SDK is global-ready; regional support depends on your payment method.
Q: How fast does payment settle?
A: Most Vietnamese banks settle within 30-90 seconds during business hours. The await_settlement() function polls your bank feed and detects transfers automatically.
Q: What if a user scans the QR but closes it? A: The QR expires after your configured time (default 5-10 minutes). They can generate a new payment request. All payment requests are logged, so you can always reconcile.
Q: Do I need a webhook endpoint? A: No. AgentPay VN uses a pull model—you poll the bank feed. This is simpler and more reliable than managing webhooks.
Key Takeaways
- 🎯 VietQR + MCP = frictionless payments inside Claude without redirects or third-party escrow
- 🔧 3-line Python flow:
create_payment_request()→await_settlement()→ unlock feature - 💳 Bank settlement: Money goes straight to your account; you own the relationship
- 📦 Open-source: MIT license, full control, no vendor lock-in
- 📊 Pull, don't push: Stable polling beats webhook complexity
- 💰 Real-world use cases: Tier features (premium problems, data access, processing), one-time charges (report generation, consulting), or subscriptions
- 🔐 No PCI compliance burden: You never handle payment methods; users pay via their banking app
Get Started Now
Your first paid MCP server is 5 minutes away:
# 1. Install
pip install agentpay-vn
# 2. Start MCP server
agentpay-mcp --port 3000
# 3. Add to Claude config (see JSON above)
# 4. Build your payment flow (see code examples)
Resources: - 📚 Full Documentation: https://agentpay.servicesai.vn/v1/docs - 🔗 GitHub Repository: https://github.com/phuocdu/agentpay-vn - 💬 Questions? Check the docs or open an issue on GitHub
Monetize your AI agents today. No PCI compliance, no escrow, no redirects—just clean, agent-first payment flows.