Skip to content
Open
Show file tree
Hide file tree
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
187 changes: 166 additions & 21 deletions app/api/v1/paid/[product]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,170 @@ function paymentRequired(req: NextRequest, product: NonNullable<ReturnType<typeo
);
}

function scoreVendorLead(fit: number, readiness: number, pyrimidFit: number) {
return Math.round((fit * 0.45 + readiness * 0.3 + pyrimidFit * 0.25) * 10) / 10;
}

function vendorLeadDiscovery(segment: string) {
const normalizedSegment = segment.trim().toLowerCase() || 'mcp';
const leadProfiles = [
{
segment: 'mcp',
target: 'MCP servers with data-heavy or compute-heavy tools',
fit: 9,
readiness: 8,
pyrimidFit: 10,
discovery_sources: ['GitHub topic:mcp-server', 'llms.txt files', 'MCP registry listings'],
why_now: 'MCP tools already expose typed actions, so usage-based paid calls can be added without changing the whole product.',
ideal_first_product: 'One premium search, enrich, export, or analyze tool priced per call.',
pitch: 'Add an optional x402 paywall to one high-value tool and list it in Pyrimid so buyer agents can discover and pay in Base USDC.',
risk_notes: ['Avoid tools that handle secrets or private data by default.', 'Prefer endpoints with deterministic outputs and clear per-call value.'],
},
{
segment: 'agent-frameworks',
target: 'Agent frameworks with plugin, marketplace, or tool-calling ecosystems',
fit: 8,
readiness: 7,
pyrimidFit: 9,
discovery_sources: ['GitHub stars and recent commits', 'docs pages with plugin/tool sections', 'examples using external APIs'],
why_now: 'Framework users need monetization paths for tools; a resolver/catalog integration can turn discovery into commissionable purchases.',
ideal_first_product: 'A curated paid-tool resolver example or affiliate catalog plugin.',
pitch: 'Let builders sell tools to agents with Pyrimid catalog discovery and USDC settlement while the framework earns affiliate revenue.',
risk_notes: ['Check maintainers are open to commercial integrations.', 'Start with an example app before proposing core SDK changes.'],
},
{
segment: 'api-tools',
target: 'AI API wrappers, data APIs, scraping APIs, and scoring services',
fit: 8,
readiness: 8,
pyrimidFit: 8,
discovery_sources: ['API docs with paid tiers', 'RapidAPI-style listings', 'x402 discovery resources'],
why_now: 'Per-call costs map cleanly to x402 and buyer agents can compare price, latency, and schema before paying.',
ideal_first_product: 'One low-risk public endpoint with a small JSON response and explicit output schema.',
pitch: 'Package one API call as an agent-purchasable product with Pyrimid metadata, affiliate bps, and a reproducible 402 example.',
risk_notes: ['Skip APIs that require reselling restricted data.', 'Confirm terms allow machine-agent usage and affiliate distribution.'],
},
{
segment: 'devtools',
target: 'Developer tools that already publish CLI, SDK, or hosted API docs',
fit: 7,
readiness: 7,
pyrimidFit: 8,
discovery_sources: ['GitHub releases', 'docs quickstarts', 'pricing pages with usage meters'],
why_now: 'Developers understand pay-per-use APIs and can adopt a tiny x402 route without a sales call.',
ideal_first_product: 'A paid diagnostic, audit, report, or export endpoint.',
pitch: 'Turn a diagnostic result into a paid agent-readable endpoint and use Pyrimid for catalog metadata and affiliate routing.',
risk_notes: ['Keep the first route read-only.', 'Publish free docs plus a paid endpoint so agents can inspect before purchase.'],
},
];

const rankedLeads = leadProfiles
.filter((lead) => normalizedSegment === 'all' || lead.segment === normalizedSegment || lead.target.toLowerCase().includes(normalizedSegment))
.map((lead) => ({
...lead,
fit_score: scoreVendorLead(lead.fit, lead.readiness, lead.pyrimidFit),
pyrimid_integration: {
route_shape: 'GET /api/paid/{tool} returns 402 until X-PAYMENT or X-PAYMENT-TX is supplied',
catalog_fields: ['vendor_id', 'product_id', 'endpoint', 'price_usdc', 'affiliate_bps', 'output_schema'],
suggested_affiliate_bps: lead.segment === 'agent-frameworks' ? 3000 : 4000,
first_outreach_goal: 'Ask for one scoped paid endpoint, not a full platform migration.',
},
}))
.sort((a, b) => b.fit_score - a.fit_score);

return {
segment: normalizedSegment,
scoring_model: {
fit: 'Does the target already expose tool/API value that agents can buy?',
readiness: 'Can a vendor add one paid route without major product work?',
pyrimid_fit: 'Does affiliate catalog discovery make the route more valuable?',
scale: '0-10 weighted score',
},
leads: rankedLeads,
recommended_searches: [
'site:github.com "mcp server" "pricing"',
'site:github.com "llms.txt" "api"',
'site:x402.org "USDC" "discovery"',
'site:docs.* "MCP" "API key"',
],
outreach_template: 'Your tool already has agent-readable value. I can help package one endpoint as x402-paid, add Pyrimid catalog metadata, and test a buyer-agent purchase flow.',
};
}

function mcpServerAudit(url: string) {
let target: URL;
try {
target = new URL(url);
} catch {
target = new URL('https://example.com/mcp');
}

const host = target.hostname.replace(/^www\./, '');
const path = target.pathname === '/' ? '/mcp' : target.pathname;

return {
url: target.toString(),
summary: `${host} can start monetizing by gating one high-value MCP tool behind an x402 402 response while keeping discovery metadata public.`,
recommended_paid_tools: [
{
name: 'search',
price_usdc: '$0.01-$0.05',
value_reason: 'Search tools usually have clear marginal value and predictable response shape.',
route_shape: `GET ${path}/paid/search`,
output_schema_hint: { results: 'array', source_links: 'array', confidence: 'number' },
},
{
name: 'enrich',
price_usdc: '$0.05-$0.15',
value_reason: 'Enrichment combines public data, scoring, or compute into a differentiated result.',
route_shape: `POST ${path}/paid/enrich`,
output_schema_hint: { enrichment: 'object', risk_notes: 'array', next_actions: 'array' },
},
{
name: 'export',
price_usdc: '$0.02-$0.10',
value_reason: 'Exports are easy for buyer agents to justify when they save workflow time.',
route_shape: `GET ${path}/paid/export`,
output_schema_hint: { file_url: 'string', expires_at: 'string', rows: 'number' },
},
],
pricing_strategy: {
first_route: '$0.05 per successful call',
test_mode: 'Keep one free preview endpoint and charge only for full results.',
affiliate_bps: 3000,
rationale: 'Low enough for buyer-agent testing, high enough to make affiliate distribution visible.',
},
x402_route_shape: {
unpaid_response: {
status: 402,
includes: ['accepts[]', 'network=base', 'asset=USDC', 'maxAmountRequired', 'payTo', 'resource'],
},
paid_retry_headers: ['X-PAYMENT', 'X-PAYMENT-TX'],
success_response: ['product_id', 'vendor_id', 'payment_tx', 'buyer', 'result', 'routed_by'],
},
pyrimid_catalog_metadata: {
vendor_id: host.replace(/[^a-z0-9]+/gi, '-').toLowerCase(),
product_id: 'paid-mcp-tool',
endpoint: `${target.origin}${path}/paid/search`,
method: 'GET',
tags: ['mcp', 'x402', 'base-usdc', 'paid-tool'],
output_schema: { type: 'object', properties: { result: { type: 'object' }, routed_by: { const: 'pyrimid' } } },
},
implementation_checklist: [
'Publish a public server card or docs page that explains free vs paid tools.',
'Add a 402 handler that returns machine-readable x402 accepts metadata.',
'Verify Base USDC payment proof before executing the paid tool.',
'List the paid endpoint in the Pyrimid catalog with price and affiliate bps.',
'Add one reproducible curl example for unpaid 402 and paid retry behavior.',
],
risk_notes: [
'Do not put secrets, private user data, or destructive actions behind an automated paid tool without explicit controls.',
'Use fixed low limits while testing buyer-agent traffic.',
'Make preview metadata free so agents can decide whether payment is worthwhile.',
],
};
}

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

Expand Down Expand Up @@ -53,30 +217,11 @@ function payload(productId: string, req: NextRequest, proof: string) {
}
case 'vendor-lead-discovery': {
const segment = query.segment || 'mcp';
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.' },
],
};
return vendorLeadDiscovery(segment);
}
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',
],
},
};
return { audit: mcpServerAudit(url) };
}
case 'x402-integration-plan': {
const service = query.service || 'agent-api';
Expand Down
31 changes: 29 additions & 2 deletions lib/seed-products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,17 @@ export const SEED_PRODUCTS: Omit<SeedProduct, 'indexed_at'>[] = [
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' },
scoring_model: { type: 'object' },
leads: { type: 'array' },
recommended_searches: { type: 'array' },
outreach_template: { type: 'string' },
routed_by: { const: 'pyrimid' },
},
},
monthly_volume: 0,
monthly_buyers: 0,
network: 'base',
Expand All @@ -144,7 +154,24 @@ export const SEED_PRODUCTS: Omit<SeedProduct, 'indexed_at'>[] = [
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: {
summary: { type: 'string' },
recommended_paid_tools: { type: 'array' },
pricing_strategy: { type: 'object' },
x402_route_shape: { type: 'object' },
pyrimid_catalog_metadata: { type: 'object' },
implementation_checklist: { type: 'array' },
risk_notes: { type: 'array' },
},
},
routed_by: { const: 'pyrimid' },
},
},
monthly_volume: 0,
monthly_buyers: 0,
network: 'base',
Expand Down