diff --git a/app/api/v1/paid/[product]/route.ts b/app/api/v1/paid/[product]/route.ts index 65076eb..7db32e8 100644 --- a/app/api/v1/paid/[product]/route.ts +++ b/app/api/v1/paid/[product]/route.ts @@ -1,6 +1,7 @@ import { NextRequest, NextResponse } from 'next/server'; import { getSeedProduct, paymentRequirement } from '@/lib/seed-products'; import { verifyPyrimidPaymentTx } from '@/lib/payment-verification'; +import { getVendorLeadDiscovery } from '@/lib/vendor-lead-discovery'; function paymentRequired(req: NextRequest, product: NonNullable>) { const requirement = paymentRequirement(product, req.url); @@ -53,14 +54,8 @@ 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.' }, - ], - }; + const limit = Number.parseInt(query.limit || '3', 10); + return getVendorLeadDiscovery(segment, limit); } case 'mcp-server-audit': { const url = query.url || 'https://example.com/mcp'; diff --git a/examples/mcp-paid-tool/README.md b/examples/mcp-paid-tool/README.md index 9755841..c22c745 100644 --- a/examples/mcp-paid-tool/README.md +++ b/examples/mcp-paid-tool/README.md @@ -1,33 +1,308 @@ -# paid MCP tool pattern +# Paid MCP tool pattern for Pyrimid + x402 -Best fit: MCP servers with expensive data, scraping, enrichment, analytics, compliance checks, search, or model calls. +This is a reproducible pattern for turning one valuable MCP/API operation into a paid tool that buyer agents can discover, preview, and purchase through Pyrimid. -## Tool design +Best fit: MCP servers with expensive data, scraping, enrichment, analytics, compliance checks, search, retrieval, or model calls where every invocation has a clear marginal cost or business value. -- Free tool: `preview_*` returns schema, price, sample output, and payment requirement. -- Paid tool: `buy_*` returns HTTP 402/x402 requirement until paid. -- Discovery: publish server card, `llms.txt`, `agents.txt`, and Pyrimid catalog entry. +## Fast mental model -## Minimal product metadata +1. Publish a **free preview tool** so agents can inspect schema, price, sample output, and payment instructions without paying. +2. Publish a **paid HTTP endpoint** behind x402. Unpaid requests return `402 Payment Required` with an `accepts[]` payment requirement. +3. Add a **Pyrimid catalog entry** so agents can find the endpoint, understand the commission split, and route purchases through Pyrimid. +4. After payment, the agent retries with `X-PAYMENT` or `X-PAYMENT-TX`; the server verifies payment and returns the paid result. + +```text +MCP client / agent + ├─ calls preview_vendor_search() for free + ├─ receives price + schema + paid endpoint + ├─ GET /api/paid/vendor-search without payment + ├─ receives HTTP 402 + x402 accepts[] metadata + └─ retries with X-PAYMENT or X-PAYMENT-TX after payment +``` + +## Endpoint shape + +Use a normal HTTPS endpoint for the paid operation and expose it through your MCP tool definition. + +```http +GET https://example.com/api/paid/vendor-search?segment=mcp +``` + +Unpaid response: + +```http +HTTP/1.1 402 Payment Required +Content-Type: application/json +X-PAYMENT-REQUIRED: {"x402Version":2,"scheme":"exact","network":"base",...} +X-Pyrimid-Vendor: vendor-search-co +X-Pyrimid-Product: vendor_search +Cache-Control: no-store +``` ```json { - "vendor_id": "your-mcp-server", - "product_id": "paid_search", - "description": "Paid MCP search result with enriched citations", - "category": "search-scraping", - "tags": ["mcp", "search", "x402", "paid-tools"], - "price_usdc": 50000, + "error": "payment_required", + "message": "Pay $0.25 USDC on Base through Pyrimid, then retry with X-PAYMENT or X-PAYMENT-TX.", + "accepts": [ + { + "x402Version": 2, + "scheme": "exact", + "network": "base", + "asset": "USDC", + "maxAmountRequired": "0.25", + "payTo": "0xc949AEa380D7b7984806143ddbfE519B03ABd68B", + "resource": "https://example.com/api/paid/vendor-search?segment=mcp", + "description": "High-fit MCP vendor lead discovery with scoring and outreach angles.", + "mimeType": "application/json", + "vendorId": "vendor-search-co", + "productId": "vendor_search", + "affiliateBps": 3000, + "protocol": "pyrimid" + } + ], + "docs": "https://pyrimid.ai/quickstart", + "catalog": "https://pyrimid.ai/api/v1/catalog" +} +``` + +Paid response after a verified retry should be regular JSON and should include enough receipt metadata for an agent audit trail: + +```json +{ + "product_id": "vendor_search", + "vendor_id": "vendor-search-co", + "payment_tx": "0x...", + "payment_amount": "250000", + "buyer": "0xBuyerAddress", + "result": { + "segment": "mcp", + "leads": [ + { + "rank": 1, + "target": "MCP servers with paid/data-heavy tools", + "fit_score": 92, + "reason": "Already expose tool interfaces and can price high-cost calls per use." + } + ] + }, + "routed_by": "pyrimid" +} +``` + +## Minimal Pyrimid catalog metadata + +Use stable IDs. Agents will key cache, receipts, and replay checks off these fields. + +```json +{ + "vendor_id": "vendor-search-co", + "vendor_name": "Vendor Search Co", + "vendor_erc8004": false, + "product_id": "vendor_search", + "description": "Paid MCP vendor lead discovery with scored leads, x402 fit, and first outreach angles.", + "category": "growth-data", + "tags": ["mcp", "lead-discovery", "x402", "paid-tools", "base"], + "price_usdc": 250000, + "price_display": "$0.25", "affiliate_bps": 3000, - "endpoint": "https://your-service.com/api/paid/search", + "endpoint": "https://example.com/api/paid/vendor-search?segment=mcp", + "method": "GET", + "output_schema": { + "type": "object", + "properties": { + "result": { + "type": "object", + "properties": { + "segment": { "type": "string" }, + "leads": { "type": "array" } + } + }, + "routed_by": { "const": "pyrimid" } + } + }, "network": "base", - "asset": "USDC" + "asset": "USDC", + "source": "pyrimid-seed", + "sdk_integrated": true +} +``` + +`price_usdc` is in USDC atomic units with 6 decimals (`250000` = `$0.25`). `affiliate_bps` is basis points (`3000` = 30%). + +## MCP tool design + +Expose a free preview tool and a paid purchase tool. The preview should not need wallet access. + +```json +{ + "name": "preview_vendor_search", + "description": "Preview the paid vendor lead discovery tool, output schema, price, and x402 requirement.", + "inputSchema": { + "type": "object", + "properties": { + "segment": { + "type": "string", + "enum": ["mcp", "agent-frameworks", "api-tools"] + } + } + } +} +``` + +```json +{ + "name": "buy_vendor_search", + "description": "Buy the vendor lead discovery result through x402/Pyrimid and return the verified JSON payload.", + "inputSchema": { + "type": "object", + "required": ["segment"], + "properties": { + "segment": { "type": "string" }, + "max_price_usdc": { "type": "string", "default": "0.25" } + } + } } ``` +## Curl reproduction + +Preview the live Pyrimid seed endpoint without paying: + +```bash +curl -i "https://pyrimid.ai/api/v1/paid/vendor-lead-discovery?segment=mcp" +``` + +Expected result: `HTTP/2 402` or `HTTP/1.1 402` with a JSON body containing `accepts[0]` and headers similar to `X-Pyrimid-Vendor` and `X-Pyrimid-Product`. + +Inspect catalog discovery: + +```bash +curl -s "https://pyrimid.ai/api/v1/catalog?query=vendor-lead-discovery&limit=5" | jq '.products[0]' +``` + +After a real payment is made by the caller's wallet/payment facilitator, retry with the proof. Do not fake this in production; verify the transaction server-side. + +```bash +curl -s \ + -H "X-PAYMENT-TX: 0xPAID_TRANSACTION_HASH" \ + "https://example.com/api/paid/vendor-search?segment=mcp" +``` + +## TypeScript snippets + +### 1. Return a 402 requirement from an unpaid endpoint + +```ts +import { NextRequest, NextResponse } from 'next/server'; + +const PRICE_USDC = '0.25'; +const PYRIMID_ROUTER = '0xc949AEa380D7b7984806143ddbfE519B03ABd68B'; + +export function paymentRequired(req: NextRequest) { + const requirement = { + x402Version: 2, + scheme: 'exact', + network: 'base', + asset: 'USDC', + maxAmountRequired: PRICE_USDC, + payTo: PYRIMID_ROUTER, + resource: req.url, + description: 'High-fit MCP vendor lead discovery with scoring and outreach angles.', + mimeType: 'application/json', + vendorId: 'vendor-search-co', + productId: 'vendor_search', + affiliateBps: 3000, + protocol: 'pyrimid', + }; + + return NextResponse.json( + { + error: 'payment_required', + message: `Pay $${PRICE_USDC} USDC on Base through Pyrimid, then retry with X-PAYMENT or X-PAYMENT-TX.`, + accepts: [requirement], + docs: 'https://pyrimid.ai/quickstart', + catalog: 'https://pyrimid.ai/api/v1/catalog', + }, + { + status: 402, + headers: { + 'X-PAYMENT-REQUIRED': JSON.stringify(requirement), + 'X-Pyrimid-Vendor': 'vendor-search-co', + 'X-Pyrimid-Product': 'vendor_search', + 'Cache-Control': 'no-store', + }, + } + ); +} +``` + +### 2. Buyer-agent safe fetch flow + +This keeps wallet/payment handling outside the agent until the user or policy layer approves the spend. + +```ts +type PaymentRequirement = { + x402Version: number; + scheme: string; + network: string; + asset: string; + maxAmountRequired: string; + payTo: string; + resource: string; + vendorId: string; + productId: string; + affiliateBps?: number; +}; + +export async function previewPaidTool(url: string) { + const res = await fetch(url, { cache: 'no-store' }); + const body = await res.json(); + + if (res.status !== 402) return { paid: true, body }; + + const requirement = body.accepts?.[0] as PaymentRequirement | undefined; + return { + paid: false, + requirement, + approvalPrompt: requirement + ? `Approve ${requirement.maxAmountRequired} ${requirement.asset} on ${requirement.network} for ${requirement.productId}?` + : 'Payment required, but no x402 accepts[] metadata was returned.', + }; +} + +export async function fetchAfterApprovedPayment(url: string, paymentTx: string) { + const res = await fetch(url, { + headers: { 'X-PAYMENT-TX': paymentTx }, + cache: 'no-store', + }); + + if (!res.ok) { + throw new Error(`Paid tool failed: ${res.status} ${await res.text()}`); + } + + return res.json(); +} +``` + +## Agent reproduction checklist + +Use this before submitting a new paid MCP tool to Pyrimid. + +- [ ] Free preview path exists and returns schema, price, sample output, and paid endpoint. +- [ ] Unpaid paid-endpoint call returns HTTP 402, not 200. +- [ ] 402 body includes `accepts[0].x402Version`, `scheme`, `network`, `asset`, `maxAmountRequired`, `payTo`, `resource`, `vendorId`, `productId`, and `protocol`. +- [ ] 402 headers include `X-Pyrimid-Vendor`, `X-Pyrimid-Product`, and `Cache-Control: no-store`. +- [ ] Catalog metadata uses stable `vendor_id` and `product_id` values. +- [ ] `price_usdc` uses atomic USDC units; `price_display` is human readable. +- [ ] `affiliate_bps` is intentionally chosen and documented. +- [ ] Paid retry verifies `X-PAYMENT` or `X-PAYMENT-TX` server-side before returning data. +- [ ] Paid response includes `product_id`, `vendor_id`, `payment_tx`, `buyer` if available, `routed_by: "pyrimid"`, and useful result JSON. +- [ ] MCP server card / `llms.txt` / `agents.txt` points agents at the preview and catalog entry. +- [ ] Buyer agents gate wallet spend behind explicit user or policy approval. + ## Why route through Pyrimid? -- Agents can find your tool in one catalog. -- Buyer agents get a standard x402 payment flow. -- Affiliates can route demand to your tool. -- Vendor, affiliate, and protocol fees are visible onchain. +- Agents can find your tool in one catalog instead of scraping separate docs. +- Buyer agents get a standard x402 payment flow and reproducible 402 metadata. +- Affiliates can route demand to your tool without custom rev-share plumbing. +- Vendor, affiliate, and protocol fees are visible through Pyrimid/onchain receipts. diff --git a/lib/seed-products.ts b/lib/seed-products.ts index c47b524..5331e0f 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 vendor lead discovery for agents: returns ranked AI agent/API vendor segments with fit scores, discovery queries, outreach angles, and x402 monetization next steps.', category: 'growth-data', tags: ['vendor-discovery', 'lead-gen', 'ai-api', 'agent-frameworks', 'x402'], price_usdc: 250000, @@ -123,7 +123,37 @@ 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: { + requested_segment: { type: 'string' }, + normalized_segment: { type: 'string' }, + supported_segments: { type: 'array', items: { type: 'string' } }, + scoring_model: { type: 'object' }, + leads: { + type: 'array', + items: { + type: 'object', + properties: { + rank: { type: 'number' }, + segment: { type: 'string' }, + target: { type: 'string' }, + fit_score: { type: 'number' }, + score_breakdown: { type: 'object' }, + why_now: { type: 'string' }, + pyrimid_angle: { type: 'string' }, + suggested_paid_product: { type: 'string' }, + example_discovery_queries: { type: 'array', items: { type: 'string' } }, + first_outreach_angle: { type: 'string' }, + disqualification_flags: { type: 'array', items: { type: 'string' } }, + next_step: { type: 'string' }, + }, + }, + }, + recommended_next_action: { type: 'string' }, + routed_by: { const: 'pyrimid' }, + }, + }, monthly_volume: 0, monthly_buyers: 0, network: 'base', diff --git a/lib/vendor-lead-discovery.ts b/lib/vendor-lead-discovery.ts new file mode 100644 index 0000000..74a2ed4 --- /dev/null +++ b/lib/vendor-lead-discovery.ts @@ -0,0 +1,210 @@ +export type VendorLeadSegment = 'mcp' | 'agent-frameworks' | 'api-tools'; + +export type VendorLead = { + rank: number; + segment: VendorLeadSegment; + target: string; + fit_score: number; + score_breakdown: { + pain: number; + integration_ease: number; + buyer_agent_value: number; + distribution_fit: number; + }; + why_now: string; + pyrimid_angle: string; + suggested_paid_product: string; + example_discovery_queries: string[]; + first_outreach_angle: string; + disqualification_flags: string[]; + next_step: string; +}; + +type LeadTemplate = Omit; + +const SEGMENTS: VendorLeadSegment[] = ['mcp', 'agent-frameworks', 'api-tools']; + +const LEADS_BY_SEGMENT: Record = { + mcp: [ + { + target: 'MCP servers with data-heavy tools', + fit_score: 94, + score_breakdown: { pain: 24, integration_ease: 24, buyer_agent_value: 24, distribution_fit: 22 }, + why_now: 'They already expose tool schemas, so adding a paid HTTP/x402 gate is mostly packaging and verification work.', + pyrimid_angle: 'List the most expensive tool in the Pyrimid catalog with a visible affiliate split for agent distribution.', + suggested_paid_product: 'Paid MCP search, enrichment, audit, export, or compliance check priced at $0.05-$0.50 per call.', + example_discovery_queries: [ + 'site:github.com "mcp server" "search" "api key"', + 'site:smithery.ai mcp data enrichment', + 'site:glama.ai mcp analytics api', + ], + first_outreach_angle: 'Your MCP server already has agent-readable tools; Pyrimid can add paid-tool discovery and Base USDC settlement without changing the free preview flow.', + disqualification_flags: ['purely local tools', 'no hosted endpoint', 'no repeatable paid output', 'unclear data rights'], + next_step: 'Ask for one high-cost tool route and a sample JSON output to turn into a 402-gated endpoint.', + }, + { + target: 'Hosted browser/scraping MCP servers', + fit_score: 89, + score_breakdown: { pain: 25, integration_ease: 20, buyer_agent_value: 23, distribution_fit: 21 }, + why_now: 'Scraping/browser sessions have direct infra cost and buyers understand per-run pricing.', + pyrimid_angle: 'Use Pyrimid as the affiliate layer for agents that recommend scraping tools inside workflows.', + suggested_paid_product: 'Paid scrape-and-summarize or lead-table export with a free schema/sample preview.', + example_discovery_queries: [ + '"browser mcp" hosted scraping pricing', + '"MCP" "scrape" "export" "API"', + '"Playwright MCP" hosted service', + ], + first_outreach_angle: 'Agents need safe paid browser runs; a 402 preview/purchase flow lets them quote cost before spending.', + disqualification_flags: ['ToS-risky scraping only', 'no rate limits', 'no audit log', 'unbounded runtime cost'], + next_step: 'Confirm they can cap runtime/credits per call and return deterministic JSON receipts.', + }, + { + target: 'Vertical research MCP servers', + fit_score: 84, + score_breakdown: { pain: 21, integration_ease: 21, buyer_agent_value: 22, distribution_fit: 20 }, + why_now: 'Research outputs can be sold as discrete calls with clear buyer value.', + pyrimid_angle: 'Catalog the paid research endpoint by vertical so buyer agents can compare price and schema.', + suggested_paid_product: 'Paid market map, diligence brief, vendor shortlist, or risk scan.', + example_discovery_queries: [ + '"MCP server" "market research"', + '"MCP" "due diligence" API', + '"MCP" "vendor" "research"', + ], + first_outreach_angle: 'Your research workflow can keep a free preview while monetizing full JSON reports per call.', + disqualification_flags: ['manual-only fulfillment', 'no source citations', 'no consistent output schema'], + next_step: 'Request a repeatable input schema and one redacted paid-output example.', + }, + ], + 'agent-frameworks': [ + { + target: 'Agent frameworks with plugin/tool marketplaces', + fit_score: 91, + score_breakdown: { pain: 22, integration_ease: 22, buyer_agent_value: 24, distribution_fit: 23 }, + why_now: 'They can embed Pyrimid discovery once and give every builder a paid-tool monetization rail.', + pyrimid_angle: 'Make Pyrimid the default catalog/payment resolver for paid third-party tools.', + suggested_paid_product: 'Framework-level paid-tool resolver with affiliate attribution to the framework.', + example_discovery_queries: [ + '"agent framework" plugin marketplace tools', + '"AI agent" "tool marketplace" SDK', + '"agent framework" MCP integrations paid tools', + ], + first_outreach_angle: 'Pyrimid can turn your tool ecosystem into an agent-commerce channel with transparent affiliate splits.', + disqualification_flags: ['closed ecosystem with no external tools', 'no server-side execution path', 'no marketplace/discovery roadmap'], + next_step: 'Find the plugin/tool owner and propose a resolver demo using one seed paid endpoint.', + }, + { + target: 'No-code agent builders', + fit_score: 86, + score_breakdown: { pain: 20, integration_ease: 21, buyer_agent_value: 22, distribution_fit: 23 }, + why_now: 'No-code users want monetizable tools but usually do not want to build wallet/payment plumbing.', + pyrimid_angle: 'Offer a built-in paid action block backed by Pyrimid catalog metadata.', + suggested_paid_product: 'Paid action templates for enrichment, search, browser runs, and exports.', + example_discovery_queries: [ + '"no-code agent" marketplace tools', + '"AI workflow builder" paid actions', + '"agent builder" "MCP" integrations', + ], + first_outreach_angle: 'A paid action block lets builders charge per call while buyer agents receive standard 402 metadata.', + disqualification_flags: ['no custom HTTP actions', 'consumer-only chatbot positioning', 'no builder monetization'], + next_step: 'Check whether their action builder supports custom headers and JSON response handling.', + }, + { + target: 'Agent hosting/runtime providers', + fit_score: 82, + score_breakdown: { pain: 19, integration_ease: 20, buyer_agent_value: 21, distribution_fit: 22 }, + why_now: 'Runtimes can meter paid external actions and expose receipts in execution logs.', + pyrimid_angle: 'Add Pyrimid receipts to hosted run traces and route affiliate revenue to the runtime or builder.', + suggested_paid_product: 'Hosted paid-action execution with spend caps, receipts, and catalog search.', + example_discovery_queries: [ + '"agent runtime" hosted tools marketplace', + '"agent hosting" MCP tools', + '"AI agent platform" external actions billing', + ], + first_outreach_angle: 'Your runtime already enforces policies; Pyrimid adds a discoverable paid-tool marketplace and x402 receipts.', + disqualification_flags: ['no external network calls', 'no per-run logs', 'no policy/spend controls'], + next_step: 'Ask for a sandbox integration path and a demo with a $0.05 seed endpoint.', + }, + ], + 'api-tools': [ + { + target: 'AI APIs with clear per-call COGS', + fit_score: 90, + score_breakdown: { pain: 24, integration_ease: 23, buyer_agent_value: 22, distribution_fit: 21 }, + why_now: 'Per-call model, enrichment, and data costs map directly to x402 pricing.', + pyrimid_angle: 'Expose one paid endpoint in Pyrimid so agents can discover and pay without a SaaS signup.', + suggested_paid_product: 'Single-purpose enrichment, classification, extraction, or scoring API priced per request.', + example_discovery_queries: [ + '"AI API" enrichment pricing per request', + '"lead enrichment API" "AI" "pricing"', + '"classification API" usage based pricing', + ], + first_outreach_angle: 'Buyer agents often cannot create SaaS accounts mid-run; x402 lets them pay per call with an auditable receipt.', + disqualification_flags: ['requires long onboarding', 'contract-only pricing', 'no JSON API', 'no usage caps'], + next_step: 'Pick one low-risk endpoint and return a 402 preview before requiring any account signup.', + }, + { + target: 'Data enrichment vendors', + fit_score: 87, + score_breakdown: { pain: 23, integration_ease: 21, buyer_agent_value: 22, distribution_fit: 21 }, + why_now: 'Agents frequently need one-off enrichment and do not want monthly subscriptions.', + pyrimid_angle: 'Catalog sample enrichment routes and let affiliates recommend the best vendor per workflow.', + suggested_paid_product: 'Company, contact, agent, repository, or domain enrichment by ID/domain/URL.', + example_discovery_queries: [ + '"company enrichment API" "pay as you go"', + '"contact enrichment" "API" "usage"', + '"domain enrichment API" pricing', + ], + first_outreach_angle: 'Pyrimid can open a new buyer-agent channel for one-off enrichment calls with transparent per-call pricing.', + disqualification_flags: ['PII/consent ambiguity', 'bulk-only minimums', 'no source freshness metadata'], + next_step: 'Verify allowed use cases, output fields, freshness, and one paid-call price.', + }, + { + target: 'Niche compliance/risk APIs', + fit_score: 83, + score_breakdown: { pain: 22, integration_ease: 20, buyer_agent_value: 21, distribution_fit: 20 }, + why_now: 'Risk checks are approval-gated by nature and benefit from receipts and audit trails.', + pyrimid_angle: 'List compact risk-check endpoints with clear schema, disclaimers, and per-call receipts.', + suggested_paid_product: 'Sanctions, license, vendor-risk, repo-risk, or policy check API.', + example_discovery_queries: [ + '"risk check API" usage based', + '"vendor risk API" "pricing"', + '"compliance API" "pay as you go"', + ], + first_outreach_angle: 'Approval-gated agents need auditable paid risk checks before taking external actions.', + disqualification_flags: ['legal advice positioning', 'no explainability', 'no audit trail', 'enterprise-only procurement'], + next_step: 'Ask for a narrow non-legal decision-support endpoint and a sample output schema.', + }, + ], +}; + +export function normalizeVendorLeadSegment(segment: string | undefined): VendorLeadSegment { + const normalized = segment?.trim().toLowerCase(); + return SEGMENTS.includes(normalized as VendorLeadSegment) ? (normalized as VendorLeadSegment) : 'mcp'; +} + +export function getVendorLeadDiscovery(segmentInput: string | undefined, limit = 3) { + const segment = normalizeVendorLeadSegment(segmentInput); + const safeLimit = Number.isFinite(limit) ? Math.min(Math.max(Math.floor(limit), 1), 5) : 3; + const leads = LEADS_BY_SEGMENT[segment] + .slice() + .sort((a, b) => b.fit_score - a.fit_score) + .slice(0, safeLimit) + .map((lead, index): VendorLead => ({ + rank: index + 1, + segment, + ...lead, + })); + + return { + requested_segment: segmentInput || segment, + normalized_segment: segment, + supported_segments: SEGMENTS, + scoring_model: { + max_score: 100, + components: ['pain', 'integration_ease', 'buyer_agent_value', 'distribution_fit'], + note: 'Scores prioritize fast x402/Pyrimid integration paths with clear buyer-agent value.', + }, + leads, + recommended_next_action: leads[0]?.next_step || 'Pick a hosted API/MCP vendor with one repeatable high-value JSON endpoint.', + }; +}