diff --git a/app/api/v1/paid/[product]/route.ts b/app/api/v1/paid/[product]/route.ts index 65076eb..5023d9d 100644 --- a/app/api/v1/paid/[product]/route.ts +++ b/app/api/v1/paid/[product]/route.ts @@ -24,7 +24,128 @@ function paymentRequired(req: NextRequest, product: NonNullable2026-01-01'; + case 'api-tools': + return 'AI API x402 paid endpoint language:TypeScript pushed:>2026-01-01'; + case 'mcp': + default: + return 'mcp server tools language:TypeScript pushed:>2026-01-01'; + } +} + +function scoreLead(repo: GitHubRepo, segment: string) { + const text = `${repo.full_name} ${repo.description || ''} ${(repo.topics || []).join(' ')}`.toLowerCase(); + let score = 30; + if (text.includes('mcp')) score += 25; + if (text.includes('x402') || text.includes('paid') || text.includes('payment')) score += 20; + if (text.includes('agent') || text.includes('tool')) score += 15; + if (segment === 'agent-frameworks' && text.includes('framework')) score += 10; + if (segment === 'api-tools' && text.includes('api')) score += 10; + score += Math.min(10, Math.floor(Math.log10(Math.max(1, repo.stargazers_count)) * 5)); + return Math.min(100, score); +} + +function fallbackLeads(segment: string) { + const targets = [ + { + name: 'MCP server vendors with data-heavy tools', + url: 'https://github.com/search?q=mcp+server+tools+language%3ATypeScript&type=repositories', + segment: 'mcp', + score: segment === 'mcp' ? 82 : 70, + reason: 'Already expose agent-callable tools; easiest path to wrap one high-value tool behind x402.', + }, + { + name: 'Agent frameworks with plugin marketplaces', + url: 'https://github.com/search?q=agent+framework+mcp+x402&type=repositories', + segment: 'agent-frameworks', + score: segment === 'agent-frameworks' ? 80 : 68, + reason: 'Can route many downstream agents to paid tools through a single Pyrimid catalog integration.', + }, + { + name: 'AI API wrappers with per-call cost', + url: 'https://github.com/search?q=AI+API+x402+paid+endpoint&type=repositories', + segment: 'api-tools', + score: segment === 'api-tools' ? 78 : 66, + reason: 'Usage-based API value maps cleanly to per-call Base USDC pricing and affiliate distribution.', + }, + ]; + + return targets.sort((a, b) => b.score - a.score); +} + +async function vendorLeadDiscovery(segment: string) { + const query = leadQuery(segment); + const searchUrl = `https://api.github.com/search/repositories?q=${encodeURIComponent(query)}&sort=updated&order=desc&per_page=8`; + + try { + const response = await fetch(searchUrl, { + headers: { + Accept: 'application/vnd.github+json', + 'User-Agent': 'pyrimid-vendor-lead-discovery', + }, + cache: 'no-store', + }); + + if (response.ok) { + const data = (await response.json()) as { items?: GitHubRepo[] }; + const leads = (data.items || []).map((repo) => { + const score = scoreLead(repo, segment); + return { + name: repo.full_name, + url: repo.html_url, + owner: repo.owner?.login || repo.full_name.split('/')[0], + owner_url: repo.owner?.html_url || `https://github.com/${repo.full_name.split('/')[0]}`, + segment, + score, + language: repo.language, + stars: repo.stargazers_count, + forks: repo.forks_count, + updated_at: repo.updated_at, + reason: + score >= 75 + ? 'Strong fit for a paid MCP/API wrapper and Pyrimid catalog listing.' + : 'Potential fit; confirm tool surface, pricing unit, and owner interest before outreach.', + recommended_pitch: 'Offer a no-risk paid endpoint pilot with x402 402 metadata, Base USDC settlement, and affiliateBps for distribution agents.', + }; + }); + + if (leads.length > 0) { + return { + source: 'github-search', + query, + generated_at: new Date().toISOString(), + leads, + }; + } + } + } catch { + // Fall through to deterministic seed leads when GitHub search is unavailable. + } + + return { + source: 'fallback-seed', + query, + generated_at: new Date().toISOString(), + leads: fallbackLeads(segment), + }; +} + +async function payload(productId: string, req: NextRequest, proof: string) { const query = Object.fromEntries(req.nextUrl.searchParams.entries()); switch (productId) { @@ -53,12 +174,22 @@ function payload(productId: string, req: NextRequest, proof: string) { } case 'vendor-lead-discovery': { const segment = query.segment || 'mcp'; + const discovery = await vendorLeadDiscovery(segment); return { segment, - leads: [ - { segment: 'mcp', target: 'MCP servers with paid/data-heavy tools', pitch: 'Add optional x402 payment gate + Pyrimid catalog listing.' }, - { segment: 'agent-frameworks', target: 'Agent frameworks with marketplace/plugin systems', pitch: 'Let builders sell tools to agents with Base USDC settlement.' }, - { segment: 'api-tools', target: 'AI API services with per-call cost', pitch: 'Turn API calls into agent-purchasable products.' }, + ...discovery, + scoring_model: { + base: 30, + mcp_signal: 25, + monetization_signal: 20, + agent_tool_signal: 15, + segment_match: 10, + popularity_cap: 10, + }, + next_actions: [ + 'Open the repo and confirm it exposes a tool/API surface with repeat buyer value.', + 'Pick one endpoint to wrap with an unpaid 402 challenge and a paid response path.', + 'List product metadata in Pyrimid with price_usdc, affiliate_bps, endpoint, method, and output_schema.', ], }; } @@ -128,7 +259,7 @@ export async function GET(req: NextRequest, context: { params: Promise<{ product payment_tx: verification.txHash, payment_amount: verification.amount?.toString(), buyer: verification.buyer, - ...payload(product.product_id, req, proof), + ...(await payload(product.product_id, req, proof)), routed_by: 'pyrimid', links: { docs: 'https://pyrimid.ai/quickstart',