From ba43e02e86904676a406748cb50936212eea2701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8chico10117=C2=A8?= Date: Mon, 25 May 2026 05:08:34 +0100 Subject: [PATCH] Improve paid seed product outputs --- app/api/v1/paid/[product]/route.ts | 398 +++++++++++++++++++++++++++-- lib/seed-products.ts | 52 +++- 2 files changed, 431 insertions(+), 19 deletions(-) diff --git a/app/api/v1/paid/[product]/route.ts b/app/api/v1/paid/[product]/route.ts index 65076eb..e23ec2c 100644 --- a/app/api/v1/paid/[product]/route.ts +++ b/app/api/v1/paid/[product]/route.ts @@ -24,7 +24,360 @@ function paymentRequired(req: NextRequest, product: NonNullable; + notes: string[]; +}; + +const DISCOVERY_SEGMENTS: Record = { + mcp: { + label: 'MCP servers and paid tools', + githubQueries: [ + 'topic:mcp-server language:TypeScript pushed:>2026-01-01', + '"Model Context Protocol" "tools/list" pushed:>2026-01-01', + ], + fallback: [ + { + name: 'MCP server vendors with data-heavy tools', + url: 'https://github.com/search?q=topic%3Amcp-server&type=repositories', + segment: 'mcp', + fit_score: 73, + matched_signals: ['tool schema', 'server distribution', 'agent buyer fit'], + suggested_product: 'Paid MCP enrichment/search/export tool', + integration_path: ['publish mcp.json', 'add x402 challenge to high-cost tools', 'list product in Pyrimid catalog'], + outreach: 'Your MCP server already has agent-readable tools. Pyrimid can turn expensive tools into Base USDC paid calls with affiliate routing.', + }, + ], + }, + 'agent-frameworks': { + label: 'Agent frameworks and plugin ecosystems', + githubQueries: [ + 'topic:ai-agents topic:plugins language:TypeScript pushed:>2026-01-01', + '"agent marketplace" "plugin" "MCP" pushed:>2026-01-01', + ], + fallback: [ + { + name: 'Agent frameworks with plugin marketplaces', + url: 'https://github.com/search?q=ai+agent+marketplace+plugin&type=repositories', + segment: 'agent-frameworks', + fit_score: 68, + matched_signals: ['plugin ecosystem', 'third-party developers', 'distribution need'], + suggested_product: 'Paid plugin catalog with affiliate splits', + integration_path: ['add Pyrimid SDK resolver', 'surface paid products in plugin search', 'attribute affiliateBps per sale'], + outreach: 'Your framework can let builders sell tools to agents instead of only installing free plugins.', + }, + ], + }, + 'api-tools': { + label: 'AI APIs and data tools', + githubQueries: [ + '"x402" "USDC" "API" pushed:>2026-01-01', + '"paid API" "agent" "Base" pushed:>2026-01-01', + ], + fallback: [ + { + name: 'AI API services with usage-based cost', + url: 'https://github.com/search?q=%22x402%22+%22API%22&type=repositories', + segment: 'api-tools', + fit_score: 70, + matched_signals: ['per-call value', 'compute/data cost', 'buyer-agent fit'], + suggested_product: 'Paid JSON API route with x402 retry', + integration_path: ['return unpaid 402 metadata', 'verify Base USDC tx/proof', 'register endpoint in Pyrimid'], + outreach: 'Your API has per-call value. Pyrimid adds agent-readable pricing, settlement, and reseller commission without a subscription flow.', + }, + ], + }, + x402: { + label: 'Existing x402 sellers', + githubQueries: [ + '"X-PAYMENT" "Base" "USDC" pushed:>2026-01-01', + '"payment_required" "x402" "USDC" pushed:>2026-01-01', + ], + fallback: [ + { + name: 'Existing x402 endpoints without catalog distribution', + url: 'https://github.com/search?q=%22X-PAYMENT%22+%22USDC%22&type=code', + segment: 'x402', + fit_score: 82, + matched_signals: ['x402 already present', 'Base USDC compatible', 'catalog gap'], + suggested_product: 'Pyrimid-listed x402 endpoint with affiliateBps', + integration_path: ['map existing 402 metadata to product record', 'add affiliate attribution', 'publish catalog entry'], + outreach: 'You already speak x402. Pyrimid can add discovery and affiliate distribution so agents can find and resell the endpoint.', + }, + ], + }, +}; + +function clampScore(score: number) { + return Math.max(0, Math.min(100, Math.round(score))); +} + +function compactText(value: string) { + return value.replace(/\s+/g, ' ').trim(); +} + +function uniqueStrings(values: string[]) { + return Array.from(new Set(values.filter(Boolean))); +} + +function scoreRepository(repo: any, segment: string) { + const haystack = `${repo.name || ''} ${repo.description || ''} ${(repo.topics || []).join(' ')}`.toLowerCase(); + let score = 35; + const signals: string[] = []; + + for (const [term, label, points] of [ + ['mcp', 'MCP signal', 16], + ['x402', 'x402 signal', 18], + ['agent', 'agent-facing', 10], + ['api', 'API surface', 8], + ['payment', 'payment language', 8], + ['tool', 'tool interface', 7], + ['base', 'Base mention', 8], + ] as const) { + if (haystack.includes(term)) { + score += points; + signals.push(label); + } + } + + if (segment === 'x402' && haystack.includes('x402')) score += 12; + if ((repo.stargazers_count || 0) >= 50) { + score += 6; + signals.push('existing developer attention'); + } + if (repo.pushed_at && Date.parse(repo.pushed_at) > Date.now() - 1000 * 60 * 60 * 24 * 90) { + score += 8; + signals.push('recently maintained'); + } + + return { score: clampScore(score), signals: uniqueStrings(signals) }; +} + +async function fetchGithubLeadCandidates(segment: string): Promise { + const config = DISCOVERY_SEGMENTS[segment] || DISCOVERY_SEGMENTS.mcp; + const results: VendorLead[] = []; + + for (const query of config.githubQueries) { + try { + const url = new URL('https://api.github.com/search/repositories'); + url.searchParams.set('q', query); + url.searchParams.set('sort', 'updated'); + url.searchParams.set('order', 'desc'); + url.searchParams.set('per_page', '4'); + + const response = await fetch(url, { + headers: { + accept: 'application/vnd.github+json', + 'user-agent': 'pyrimid-vendor-lead-discovery', + }, + signal: AbortSignal.timeout(4500), + }); + if (!response.ok) continue; + + const data = await response.json(); + for (const repo of Array.isArray(data.items) ? data.items : []) { + const scored = scoreRepository(repo, segment); + results.push({ + name: repo.full_name, + url: repo.html_url, + segment, + fit_score: scored.score, + matched_signals: scored.signals, + suggested_product: segment === 'agent-frameworks' + ? 'Paid plugin/tool marketplace listing' + : segment === 'x402' + ? 'Pyrimid affiliate listing for an existing x402 endpoint' + : 'Paid MCP/API tool with Base USDC settlement', + integration_path: [ + 'identify one high-value endpoint/tool', + 'return 402 metadata before expensive execution', + 'publish Pyrimid product metadata with affiliateBps', + 'add a no-payment preview so buyer agents can evaluate fit', + ], + outreach: `Pyrimid fit: ${repo.full_name} shows ${scored.signals.join(', ') || 'agent/API'} signals. Package one high-value call as an x402 product and let distribution agents earn affiliate commission.`, + }); + } + } catch { + continue; + } + } + + const deduped = new Map(); + for (const lead of [...results, ...config.fallback]) { + const existing = deduped.get(lead.url); + if (!existing || lead.fit_score > existing.fit_score) deduped.set(lead.url, lead); + } + + return Array.from(deduped.values()) + .sort((a, b) => b.fit_score - a.fit_score) + .slice(0, 8); +} + +async function inspectTarget(rawUrl: string): Promise { + const notes: string[] = []; + let target: URL; + + try { + target = new URL(rawUrl.startsWith('http') ? rawUrl : `https://${rawUrl}`); + } catch { + return { + target_url: rawUrl, + fetched_ok: false, + sample_size: 0, + signals: {}, + notes: ['Target is not a valid URL. Provide an https URL or GitHub repository URL.'], + }; + } + + const candidates = [ + target.toString(), + new URL('/.well-known/mcp.json', target.origin).toString(), + new URL('/.well-known/x402.json', target.origin).toString(), + new URL('/llms.txt', target.origin).toString(), + new URL('/agents.txt', target.origin).toString(), + ]; + + if (target.hostname === 'github.com') { + const parts = target.pathname.split('/').filter(Boolean); + if (parts.length >= 2) { + candidates.unshift(`https://raw.githubusercontent.com/${parts[0]}/${parts[1]}/HEAD/README.md`); + } + } + + for (const candidate of uniqueStrings(candidates)) { + try { + const response = await fetch(candidate, { + headers: { accept: 'application/json,text/plain,text/markdown,*/*', 'user-agent': 'pyrimid-mcp-server-audit' }, + signal: AbortSignal.timeout(4500), + }); + const text = compactText((await response.text()).slice(0, 12000)); + const lower = text.toLowerCase(); + + if (!response.ok || !text) { + notes.push(`${candidate} returned ${response.status}`); + continue; + } + + return { + target_url: target.toString(), + fetched_url: candidate, + fetched_ok: true, + content_type: response.headers.get('content-type'), + sample_size: text.length, + signals: { + mcp: lower.includes('mcp') || lower.includes('model context protocol') || lower.includes('tools/list'), + x402: lower.includes('x402') || lower.includes('x-payment') || lower.includes('payment_required'), + paid_language: lower.includes('price') || lower.includes('paid') || lower.includes('usdc') || lower.includes('subscription'), + tool_schema: lower.includes('tool') || lower.includes('input_schema') || lower.includes('json-rpc'), + catalog_metadata: lower.includes('llms.txt') || lower.includes('agents.txt') || lower.includes('openapi') || lower.includes('server.json'), + base_usdc: lower.includes('base') && lower.includes('usdc'), + risk_language: lower.includes('secret') || lower.includes('token') || lower.includes('key') || lower.includes('privacy'), + }, + notes, + }; + } catch { + notes.push(`${candidate} could not be fetched`); + } + } + + return { + target_url: target.toString(), + fetched_ok: false, + sample_size: 0, + signals: {}, + notes, + }; +} + +function buildAuditRecommendations(inspection: TargetInspection) { + const signals = inspection.signals; + const readiness = clampScore( + 20 + + (signals.mcp ? 20 : 0) + + (signals.tool_schema ? 15 : 0) + + (signals.catalog_metadata ? 15 : 0) + + (signals.x402 ? 20 : 0) + + (signals.base_usdc ? 10 : 0) - + (inspection.fetched_ok ? 0 : 15) + ); + + return { + readiness_score: readiness, + recommended_paid_tools: [ + { + name: 'search', + price_usdc: '$0.01-$0.05', + why: 'Low-cost discovery call that buyer agents can use before purchasing heavier work.', + route_shape: 'GET /api/x402/search?q=...', + }, + { + name: 'enrich', + price_usdc: '$0.05-$0.25', + why: 'Adds structured value and maps well to usage-based pricing.', + route_shape: 'POST /api/x402/enrich', + }, + { + name: 'export', + price_usdc: '$0.10-$0.50', + why: 'Batch output is easier to meter and justify with a higher per-call price.', + route_shape: 'POST /api/x402/export', + }, + ], + x402_route_guidance: { + unpaid_response: 'Return 402 with accepts[] metadata, Base network, USDC asset, exact amount, and resource URL before expensive execution.', + paid_retry: 'Verify X-PAYMENT or X-PAYMENT-TX, then execute the selected MCP/API tool once.', + cache_policy: 'Use Cache-Control: private, no-store on payment challenges and paid responses.', + }, + pyrimid_catalog_metadata: { + vendorId: 'stable vendor slug', + productId: 'stable product slug', + affiliateBps: 1000, + endpoint: inspection.target_url, + output_schema: { type: 'object', properties: { result: { type: 'object' }, routed_by: { const: 'pyrimid' } } }, + preview_url: inspection.fetched_url || inspection.target_url, + }, + risk_notes: [ + signals.risk_language + ? 'Docs mention secrets/tokens; keep paid previews secret-free and never echo private credentials.' + : 'No obvious secret-handling language found in the fetched sample.', + signals.x402 + ? 'Existing x402 language found; prioritize catalog/distribution metadata instead of rebuilding payment handling.' + : 'No x402 signal found; add a minimal payment challenge wrapper before full SDK integration.', + inspection.fetched_ok + ? 'Fetched public surface successfully; verify production route behavior with a no-payment probe.' + : 'Public fetch failed; ask vendor for a stable MCP/HTTP endpoint before estimating integration work.', + ], + launch_checklist: [ + 'Publish /.well-known/mcp.json or server.json with tool metadata.', + 'Publish llms.txt or agents.txt that names paid tools and pricing.', + 'Add a no-payment preview route for buyer-agent evaluation.', + 'Add x402 Base USDC challenge and verification around expensive tools.', + 'Register product metadata in Pyrimid with affiliateBps and output schema.', + ], + }; +} + +async function payload(productId: string, req: NextRequest, proof: string) { const query = Object.fromEntries(req.nextUrl.searchParams.entries()); switch (productId) { @@ -53,28 +406,43 @@ function payload(productId: string, req: NextRequest, proof: string) { } case 'vendor-lead-discovery': { const segment = query.segment || 'mcp'; + const normalizedSegment = DISCOVERY_SEGMENTS[segment] ? segment : 'mcp'; + const leads = await fetchGithubLeadCandidates(normalizedSegment); 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.' }, + segment: normalizedSegment, + segment_label: DISCOVERY_SEGMENTS[normalizedSegment].label, + generated_at: new Date().toISOString(), + lead_source: 'GitHub Search API with curated fallback', + scoring_model: { + max_score: 100, + signals: ['mcp', 'x402', 'agent', 'api', 'payment', 'tool', 'base', 'recently maintained', 'developer attention'], + recommended_threshold: 65, + }, + leads, + pyrimid_catalog_template: { + vendor_id: '', + product_id: '', + network: 'base', + asset: 'USDC', + affiliate_bps: 1000, + endpoint: '', + output_schema: { type: 'object', properties: { result: { type: 'object' } } }, + }, + next_actions: [ + 'Pick the highest-scoring lead with a public API/tool surface.', + 'Open a lightweight issue or PR proposing one paid endpoint and Pyrimid catalog metadata.', + 'Ask for an accepted patch or merged PR before claiming a bounty payout.', ], }; } case 'mcp-server-audit': { const url = query.url || 'https://example.com/mcp'; + const inspection = await inspectTarget(url); 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', - ], + inspected: inspection, + ...buildAuditRecommendations(inspection), }, }; } @@ -128,7 +496,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', diff --git a/lib/seed-products.ts b/lib/seed-products.ts index c47b524..756b04c 100644 --- a/lib/seed-products.ts +++ b/lib/seed-products.ts @@ -115,7 +115,7 @@ export const SEED_PRODUCTS: Omit[] = [ vendor_name: 'Pyrimid Growth', vendor_erc8004: false, product_id: 'vendor-lead-discovery', - description: 'Paid vendor lead discovery for agents: returns high-fit AI agent/API vendors to contact for x402 monetization.', + description: 'Paid live vendor lead discovery for agents: scores MCP, x402, agent-framework, and AI API repositories for Pyrimid monetization fit.', category: 'growth-data', tags: ['vendor-discovery', 'lead-gen', 'ai-api', 'agent-frameworks', 'x402'], price_usdc: 250000, @@ -123,7 +123,33 @@ export const SEED_PRODUCTS: Omit[] = [ affiliate_bps: 4000, endpoint: `${SEED_PRODUCT_BASE}/vendor-lead-discovery?segment=mcp`, method: 'GET', - output_schema: { type: 'object', properties: { leads: { type: 'array' }, routed_by: { const: 'pyrimid' } } }, + output_schema: { + type: 'object', + properties: { + segment: { type: 'string' }, + segment_label: { type: 'string' }, + lead_source: { type: 'string' }, + scoring_model: { type: 'object' }, + leads: { + type: 'array', + items: { + type: 'object', + properties: { + name: { type: 'string' }, + url: { type: 'string' }, + fit_score: { type: 'number' }, + matched_signals: { type: 'array', items: { type: 'string' } }, + suggested_product: { type: 'string' }, + integration_path: { type: 'array', items: { type: 'string' } }, + outreach: { type: 'string' }, + }, + }, + }, + pyrimid_catalog_template: { type: 'object' }, + next_actions: { type: 'array', items: { type: 'string' } }, + routed_by: { const: 'pyrimid' }, + }, + }, monthly_volume: 0, monthly_buyers: 0, network: 'base', @@ -136,7 +162,7 @@ export const SEED_PRODUCTS: Omit[] = [ vendor_name: 'Pyrimid Growth', vendor_erc8004: false, product_id: 'mcp-server-audit', - description: 'Paid MCP monetization audit: tells an MCP server how to add paid tools, x402 pricing, and affiliate routing.', + description: 'Paid MCP/API monetization audit: inspects a submitted URL or repo and returns paid tools, pricing, x402 route shape, catalog metadata, and risks.', category: 'devtools', tags: ['mcp', 'audit', 'monetization', 'paid-tools', 'x402', 'developer-tools'], price_usdc: 100000, @@ -144,7 +170,25 @@ export const SEED_PRODUCTS: Omit[] = [ affiliate_bps: 4000, endpoint: `${SEED_PRODUCT_BASE}/mcp-server-audit?url=https://example.com/mcp`, method: 'GET', - output_schema: { type: 'object', properties: { audit: { type: 'object' }, routed_by: { const: 'pyrimid' } } }, + output_schema: { + type: 'object', + properties: { + audit: { + type: 'object', + properties: { + url: { type: 'string' }, + inspected: { type: 'object' }, + readiness_score: { type: 'number' }, + recommended_paid_tools: { type: 'array' }, + x402_route_guidance: { type: 'object' }, + pyrimid_catalog_metadata: { type: 'object' }, + risk_notes: { type: 'array', items: { type: 'string' } }, + launch_checklist: { type: 'array', items: { type: 'string' } }, + }, + }, + routed_by: { const: 'pyrimid' }, + }, + }, monthly_volume: 0, monthly_buyers: 0, network: 'base',