Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 131 additions & 11 deletions app/api/v1/paid/[product]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,136 @@ function paymentRequired(req: NextRequest, product: NonNullable<ReturnType<typeo
);
}

function slug(input: string) {
const normalized = input
.toLowerCase()
.replace(/^https?:\/\//, '')
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
return normalized.slice(0, 48) || 'mcp-tool';
}

function classifyTarget(rawUrl: string) {
const lower = rawUrl.toLowerCase();

if (lower.includes('github.com')) return 'github-repository';
if (lower.endsWith('/mcp') || lower.includes('/mcp/')) return 'mcp-endpoint';
if (lower.includes('/api/')) return 'api-endpoint';
if (lower.includes('smithery') || lower.includes('glama')) return 'mcp-registry-listing';
return 'unknown';
}

function inferPaidToolCandidates(rawUrl: string) {
const lower = rawUrl.toLowerCase();

const base = [
{
name: 'premium_search',
description: 'Paid semantic search or retrieval with citations.',
suggested_price_usdc: '$0.03-$0.10',
route: '/api/paid/search',
preview_tool: 'preview_search',
},
{
name: 'deep_audit',
description: 'Higher-cost analysis that consumes external APIs, crawling, or model calls.',
suggested_price_usdc: '$0.10-$0.50',
route: '/api/paid/audit',
preview_tool: 'preview_audit',
},
];

if (lower.includes('github') || lower.includes('repo')) {
return [
{
name: 'repo_health_report',
description: 'Paid repository health, security, and monetization report.',
suggested_price_usdc: '$0.05-$0.25',
route: '/api/paid/repo-health',
preview_tool: 'preview_repo_health',
},
...base,
];
}

if (lower.includes('scrap') || lower.includes('search') || lower.includes('crawl')) {
return [
{
name: 'fresh_crawl',
description: 'Paid fresh crawl with extracted markdown and source URLs.',
suggested_price_usdc: '$0.05-$0.20',
route: '/api/paid/fresh-crawl',
preview_tool: 'preview_fresh_crawl',
},
...base,
];
}

return base;
}

function buildMcpServerAudit(rawUrl: string) {
const targetType = classifyTarget(rawUrl);
const vendorId = slug(rawUrl);
const primaryProductId = `${vendorId}-premium-search`;
const candidates = inferPaidToolCandidates(rawUrl);

return {
url: rawUrl,
target_type: targetType,
readiness_score: targetType === 'unknown' ? 54 : 78,
recommended_paid_tools: candidates.map((tool, index) => ({
...tool,
priority: index + 1,
product_id: index === 0 ? primaryProductId : `${vendorId}-${tool.name}`,
why: index === 0
? 'Best first paid surface: clear value, low integration risk, and easy preview flow.'
: 'Useful follow-up once the first paid route is live and measurable.',
})),
pricing: {
model: 'per-call USDC on Base',
starter_price: candidates[0]?.suggested_price_usdc || '$0.05-$0.25',
affiliate_bps: 2500,
note: 'Start cheap enough for buyer agents to test, then add higher-priced deep-analysis tools.',
},
x402_route_shape: {
unpaid_request: `GET ${candidates[0]?.route || '/api/paid/tool'} returns HTTP 402`,
retry_headers: ['X-PAYMENT', 'X-PAYMENT-TX'],
accepts_fields: ['x402Version', 'scheme', 'network', 'asset', 'maxAmountRequired', 'resource', 'payTo'],
network: 'base',
asset: 'USDC',
},
catalog_metadata: {
vendor_id: vendorId,
product_id: primaryProductId,
category: targetType === 'github-repository' ? 'devtools' : 'mcp',
tags: ['mcp', 'x402', 'paid-tools', 'base-usdc'],
endpoint: `https://your-service.example${candidates[0]?.route || '/api/paid/tool'}`,
affiliate_bps: 2500,
output_schema: {
type: 'object',
properties: {
result: { type: 'object' },
routed_by: { const: 'pyrimid' },
},
},
},
risk_notes: [
'Keep a free preview tool so buyer agents can evaluate value before paying.',
'Do not expose secrets, API keys, private repo data, or raw crawler credentials in paid output.',
'Cache expensive upstream calls or set a price that covers model, crawling, and rate-limit costs.',
'Return deterministic JSON with stable keys so agents can safely parse purchased results.',
],
launch_checklist: [
'Add a preview_* MCP tool with schema, sample output, and price.',
'Add one paid HTTP route that returns HTTP 402 with x402 accepts[] metadata.',
'Accept X-PAYMENT or X-PAYMENT-TX on retry and verify payment before returning paid output.',
'Publish llms.txt, agents.txt, and server card links to the paid route.',
'Register vendor and product metadata in the Pyrimid catalog.',
],
};
}

function payload(productId: string, req: NextRequest, proof: string) {
const query = Object.fromEntries(req.nextUrl.searchParams.entries());

Expand Down Expand Up @@ -65,17 +195,7 @@ function payload(productId: string, req: NextRequest, proof: string) {
case 'mcp-server-audit': {
const url = query.url || 'https://example.com/mcp';
return {
audit: {
url,
recommended_paid_tools: ['search', 'enrich', 'export', 'analyze'],
pricing: '$0.01-$0.25 per call depending on compute/data cost',
integration_steps: [
'Add 402 response with x402 accepts[] metadata',
'Register vendor/product in Pyrimid catalog',
'Expose tool schema in MCP server card',
'Add affiliateBps for distribution agents',
],
},
audit: buildMcpServerAudit(url),
};
}
case 'x402-integration-plan': {
Expand Down