From f3f8b38f43e342113ec01b847727311ff3220dd0 Mon Sep 17 00:00:00 2001 From: HMS091 Bot Date: Thu, 4 Jun 2026 00:26:35 +0000 Subject: [PATCH] fix: MYA job #24 submission: paid MCP tool guide with x402 and Py Closes #51 Bounty submission. --- .../sell-paid-mcp-tool-with-x402-pyrimid.md | 412 ++++++++++++++++++ 1 file changed, 412 insertions(+) create mode 100644 guides/sell-paid-mcp-tool-with-x402-pyrimid.md diff --git a/guides/sell-paid-mcp-tool-with-x402-pyrimid.md b/guides/sell-paid-mcp-tool-with-x402-pyrimid.md new file mode 100644 index 0000000..70a47c0 --- /dev/null +++ b/guides/sell-paid-mcp-tool-with-x402-pyrimid.md @@ -0,0 +1,412 @@ +# Sell a Paid MCP Tool with x402 and Pyrimid + +This guide walks you through creating, listing, and selling a paid MCP (Model Context Protocol) tool using Pyrimid's x402 payment infrastructure. By the end, you'll have a working paid endpoint that agents can discover, pay for, and use — all without manual billing. + +## Table of Contents + +1. [Overview](#overview) +2. [Prerequisites](#prerequisites) +3. [Step 1: Define Your Paid MCP Tool](#step-1-define-your-paid-mcp-tool) +4. [Step 2: Create the Paid API Route](#step-2-create-the-paid-api-route) +5. [Step 3: Register in the Catalog](#step-3-register-in-the-catalog) +6. [Step 4: Add Agent Discovery Files](#step-4-add-agent-discovery-files) +7. [Step 5: Test with No-Spend Curl](#step-5-test-with-no-spend-curl) +8. [Step 6: Integrate Browser SDK](#step-6-integrate-browser-sdk) +9. [No-Spend Test Checklist](#no-spend-test-checklist) +10. [Production Checklist](#production-checklist) + +## Overview + +Pyrimid uses the **x402** protocol to enable pay-per-use API calls. When an agent or user hits a paid endpoint without payment, the server responds with `402 Payment Required` and includes payment metadata in headers and body. The client then resolves payment via a browser wallet or agent resolver, and retries with a signed payment token. + +### How It Works + +``` +Client Pyrimid Server + | | + |--- GET /api/v1/paid/my-tool ------>| + | | + |<-- 402 Payment Required ----------| + | Headers: | + | X-Payment-Required: true | + | X-Pyrimid-Network: base | + | X-Pyrimid-Product: my-tool | + | X-Pyrimid-Vendor: vendor_id | + | Body: { accepts[], payTo, ... } | + | | + |--- (User pays via wallet) -------->| + | | + |--- GET (with payment token) ------>| + | | + |<-- 200 OK + tool response --------| +``` + +## Prerequisites + +- Node.js 18+ +- A Pyrimid-compatible server (this guide uses the Pyrimid demo server) +- Basic understanding of HTTP and JSON +- A browser with a Web3 wallet (for testing payments) + +## Step 1: Define Your Paid MCP Tool + +First, define your tool's metadata. This will be registered in the Pyrimid catalog. + +### Tool Shape + +```json +{ + "id": "mya-agent-enrichment", + "name": "MYA Agent Enrichment", + "description": "Enriches agent profiles with on-chain activity data", + "price_usdc_atomic": 100000, + "price_usdc": 0.10, + "network": "base", + "asset": "USDC", + "endpoint": "/api/v1/paid/mya-agent-enrichment", + "tags": ["agent", "enrichment", "onchain"], + "affiliate_bps": 297, + "vendor_id": "vendor_pyrimid_demo" +} +``` + +### Price Units + +- **Atomic units**: USDC on Base uses 6 decimal places. `100000` atomic = `0.10` USDC. +- **affiliate_bps**: Basis points (1 bps = 0.01%). `297` bps = 2.97% affiliate commission. + +## Step 2: Create the Paid API Route + +Create a route that returns `402 Payment Required` when called without payment. + +### Route Implementation (Next.js App Router) + +```typescript +// app/api/v1/paid/[product]/route.ts +import { NextRequest, NextResponse } from 'next/server'; +import { getProductFromCatalog } from '@/lib/catalog'; +import { generatePaymentChallenge } from '@/lib/payment-verification'; + +export async function GET( + request: NextRequest, + { params }: { params: { product: string } } +) { + const product = getProductFromCatalog(params.product); + + if (!product) { + return NextResponse.json( + { error: 'Product not found' }, + { status: 404 } + ); + } + + // Check for valid payment token + const paymentToken = request.headers.get('x-payment-token'); + + if (!paymentToken) { + // Generate 402 response with payment metadata + const paymentChallenge = generatePaymentChallenge(product); + + return NextResponse.json( + { + accepts: ['USDC'], + payTo: product.vendor_wallet, + vendorId: product.vendor_id, + productId: product.id, + affiliateBps: product.affiliate_bps, + docs: `/docs/${product.id}`, + catalog: '/api/v1/catalog', + ...paymentChallenge + }, + { + status: 402, + headers: { + 'X-Payment-Required': 'true', + 'X-Pyrimid-Network': product.network, + 'X-Pyrimid-Product': product.id, + 'X-Pyrimid-Vendor': product.vendor_id, + 'Content-Type': 'application/json' + } + } + ); + } + + // Verify payment token + const isValid = await verifyPaymentToken(paymentToken, product); + + if (!isValid) { + return NextResponse.json( + { error: 'Invalid payment token' }, + { status: 402 } + ); + } + + // Return the actual tool response + const result = await executeTool(product.id, request); + + return NextResponse.json(result); +} +``` + +## Step 3: Register in the Catalog + +Add your product to the catalog so agents can discover it. + +### Catalog Entry + +```typescript +// lib/seed-products.ts +export const seedProducts = [ + { + id: 'mya-agent-enrichment', + name: 'MYA Agent Enrichment', + description: 'Enriches agent profiles with on-chain activity data', + price_usdc_atomic: 100000, + network: 'base', + asset: 'USDC', + endpoint: '/api/v1/paid/mya-agent-enrichment', + tags: ['agent', 'enrichment', 'onchain'], + affiliate_bps: 297, + vendor_id: 'vendor_pyrimid_demo', + vendor_wallet: '0x...', // Your USDC wallet on Base + active: true + }, + // ... other products +]; +``` + +### Catalog API Route + +```typescript +// app/api/v1/catalog/route.ts +import { NextResponse } from 'next/server'; +import { seedProducts } from '@/lib/seed-products'; + +export async function GET() { + const catalog = seedProducts + .filter(p => p.active) + .map(({ vendor_wallet, ...rest }) => rest); // Hide wallet addresses + + return NextResponse.json({ + products: catalog.length, + items: catalog + }); +} +``` + +## Step 4: Add Agent Discovery Files + +Create discovery files so AI agents can find your paid MCP tool. + +### `.well-known/agent.json` + +```json +{ + "name": "MYA Agent Enrichment", + "description": "Paid MCP tool for agent enrichment", + "url": "https://your-domain.com", + "endpoints": { + "paid": "/api/v1/paid/mya-agent-enrichment", + "catalog": "/api/v1/catalog" + }, + "payment": { + "protocol": "x402", + "network": "base", + "asset": "USDC" + } +} +``` + +### `.well-known/x402.json` + +```json +{ + "version": "0.2", + "payment": { + "required": true, + "network": "base", + "asset": "USDC", + "accepted_tokens": ["USDC"] + }, + "endpoints": [ + { + "path": "/api/v1/paid/mya-agent-enrichment", + "method": "GET", + "price_usdc_atomic": 100000, + "description": "Enrich agent profiles" + } + ] +} +``` + +### `agents.txt` + +``` +https://your-domain.com/.well-known/agent.json +``` + +### `llms.txt` + +```markdown +# LLMs.txt for MYA Agent Enrichment + +## Paid Endpoints + +- `/api/v1/paid/mya-agent-enrichment` - Enrich agent profiles (0.10 USDC) +- `/api/v1/catalog` - List all available paid tools + +## Payment + +This service uses x402 protocol on Base network. Pay with USDC. +``` + +## Step 5: Test with No-Spend Curl + +Test your endpoint without actually spending money. The server should return `402 Payment Required` with proper headers. + +### Test Command + +```bash +curl -i https://your-domain.com/api/v1/paid/mya-agent-enrichment +``` + +### Expected Response + +``` +HTTP/2 402 +x-payment-required: true +x-pyrimid-network: base +x-pyrimid-product: mya-agent-enrichment +x-pyrimid-vendor: vendor_pyrimid_demo +content-type: application/json + +{ + "accepts": ["USDC"], + "payTo": "0x...", + "vendorId": "vendor_pyrimid_demo", + "productId": "mya-agent-enrichment", + "affiliateBps": 297, + "docs": "/docs/mya-agent-enrichment", + "catalog": "/api/v1/catalog" +} +``` + +### Verification + +Run the verification script: + +```bash +npm run check +``` + +Expected output: + +```json +{ + "products": 24, + "sample_product": "mya-agent-enrichment", + "sample_price_usdc_atomic": 100000, + "sample_affiliate_commission_atomic": 29700, + "affiliate_id": "af_codex_commerce_scout" +} +``` + +## Step 6: Integrate Browser SDK + +For browser-based payments, use the Pyrimid SDK resolver. + +### Installation + +```html + +``` + +### Usage Example + +```typescript +import { PyrimidResolver } from 'https://esm.sh/@pyrimid/sdk@0.2.6/resolver?bundle'; + +async function callPaidTool() { + const resolver = new PyrimidResolver({ + network: 'base', + asset: 'USDC' + }); + + try { + // First attempt - will get 402 + const response = await fetch('/api/v1/paid/mya-agent-enrichment'); + + if (response.status === 402) { + const paymentInfo = await response.json(); + + // Resolve payment via browser wallet + const paymentToken = await resolver.resolvePayment(paymentInfo); + + // Retry with payment token + const paidResponse = await fetch('/api/v1/paid/mya-agent-enrichment', { + headers: { + 'x-payment-token': paymentToken + } + }); + + return await paidResponse.json(); + } + + return await response.json(); + } catch (error) { + console.error('Payment failed:', error); + throw error; + } +} +``` + +## No-Spend Test Checklist + +- [ ] `curl -i` returns HTTP 402 +- [ ] Response includes `X-Payment-Required: true` header +- [ ] Response includes `X-Pyrimid-Network` header +- [ ] Response includes `X-Pyrimid-Product` header +- [ ] Response includes `X-Pyrimid-Vendor` header +- [ ] Response body contains `accepts[]` array +- [ ] Response body contains `payTo` address +- [ ] Response body contains `vendorId` +- [ ] Response body contains `productId` +- [ ] Response body contains `affiliateBps` +- [ ] Response body contains `docs` URL +- [ ] Response body contains `catalog` URL +- [ ] Catalog endpoint returns product list +- [ ] `.well-known/agent.json` is accessible +- [ ] `.well-known/x402.json` is accessible +- [ ] `agents.txt` is accessible +- [ ] `llms.txt` is accessible +- [ ] `npm run check` passes + +## Production Checklist + +- [ ] Set up a real USDC wallet on Base network +- [ ] Configure environment variables (`VENDOR_WALLET`, `NETWORK_RPC_URL`) +- [ ] Enable HTTPS (required for wallet connections) +- [ ] Set up proper error handling and logging +- [ ] Add rate limiting to prevent abuse +- [ ] Implement payment verification (check transaction on-chain) +- [ ] Set up monitoring for failed payments +- [ ] Add affiliate tracking if using affiliate program +- [ ] Write API documentation +- [ ] Test with real wallet and small payment +- [ ] Deploy to production environment +- [ ] Monitor first few transactions manually + +## Companion Demo + +See the full working demo at: +- **Demo site**: https://yzangeren.github.io/pyrimid-agent-commerce-demo/ +- **Source code**: https://github.com/yZangEren/pyrimid-agent-commerce-demo +- **Commit**: https://github.com/yZangEren/pyrimid-agent-commerce-demo/commit/f05ba42 + +## Support + +For questions or issues: +- Pyrimid GitHub: https://github.com/pyrimid-ai/pyrimid +- Issue tracker: https://github.com/pyrimid-ai/pyrimid/issues