score_lead
Score LinkedIn leads by analyzing fit, intent, and urgency to prioritize prospects and recommend offers for sales teams.
Instructions
Score a LinkedIn lead based on fit (ICP match), intent (burnout signals), and urgency (crisis markers). Returns priority P1-P4 and recommended offer.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Lead's full name | |
| title | No | Job title / headline | |
| company | No | Company name | |
| post_snippet | No | Text from their LinkedIn post | |
| linkedin_url | No | LinkedIn profile URL |
Implementation Reference
- src/index.ts:86-152 (handler)Implementation of the scoreLead function which calculates scores based on fit, intent, and urgency signals.
function scoreLead(lead: LeadInput): ScoredLead { const titleLower = (lead.title || "").toLowerCase(); const postLower = (lead.post_snippet || "").toLowerCase(); const companyLower = (lead.company || "").toLowerCase(); // FIT (0-30) let fit = 0; if (ICP_ROLES.some((r) => titleLower.includes(r))) fit += 20; if (HIGH_RISK_INDUSTRIES.some((i) => titleLower.includes(i) || companyLower.includes(i))) fit += 7; if (titleLower.length > 10 && titleLower.includes("|")) fit += 3; // INTENT (0-40) let intent = 0; const personalBurnout = [ "j'ai failli", "j'ai craque", "j'etais epuise", "j'ai tout arrete", "j'ai du m'arreter", "mon burnout", "mon epuisement", ]; if (personalBurnout.some((s) => postLower.includes(s))) { intent += 30; } else if (BURNOUT_KEYWORDS.some((k) => postLower.includes(k))) { intent += 15; } if (postLower.includes("aide") || postLower.includes("besoin") || postLower.includes("solution")) { intent += 10; } // URGENCY (0-30) let urgency = 0; const urgentMarkers = ["en peux plus", "a bout", "craque", "urgence", "au bord", "insomnie"]; if (urgentMarkers.some((m) => postLower.includes(m))) urgency += 20; if (["j'ai", "j'etais", "mon", "ma", "je"].some((p) => postLower.includes(p))) urgency += 10; const total = fit + intent + urgency; let priority: ScoredLead["priority"]; let recommended_offer: string; if (total >= 60) { priority = "P1-hot"; recommended_offer = "Coaching Decouverte 297€"; } else if (total >= 35) { priority = "P2-warm"; recommended_offer = "Kit Anti-Burnout 47€"; } else if (total >= 20) { priority = "P3-nurture"; recommended_offer = "Guide 7 Jours (gratuit)"; } else { priority = "P4-cold"; recommended_offer = "Newsletter"; } const reasons: string[] = []; if (fit >= 20) reasons.push("ICP role match"); if (intent >= 30) reasons.push("personal burnout signal"); else if (intent >= 15) reasons.push("burnout keyword detected"); if (urgency >= 20) reasons.push("urgent markers"); return { ...lead, fit_score: fit, intent_score: intent, urgency_score: urgency, total_score: total, priority, recommended_offer, reasoning: reasons.length > 0 ? reasons.join(" + ") : "Low signals", }; } - src/index.ts:302-338 (registration)Tool registration for 'score_lead', which invokes the scoreLead function and formats the result.
server.registerTool( "score_lead", { title: "Score a Lead", description: "Score a LinkedIn lead based on fit (ICP match), intent (burnout signals), " + "and urgency (crisis markers). Returns priority P1-P4 and recommended offer.", inputSchema: { name: z.string().describe("Lead's full name"), title: z.string().optional().describe("Job title / headline"), company: z.string().optional().describe("Company name"), post_snippet: z.string().optional().describe("Text from their LinkedIn post"), linkedin_url: z.string().optional().describe("LinkedIn profile URL"), }, annotations: { readOnlyHint: true, openWorldHint: false, destructiveHint: false }, }, async ({ name, title, company, post_snippet, linkedin_url }) => { const scored = scoreLead({ name, title, company, post_snippet, linkedin_url }); const output = [ `Lead: ${scored.name}`, `Title: ${scored.title || "N/A"}`, `Company: ${scored.company || "N/A"}`, "", `Fit Score: ${scored.fit_score}/30`, `Intent Score: ${scored.intent_score}/40`, `Urgency Score: ${scored.urgency_score}/30`, `TOTAL: ${scored.total_score}/100`, "", `Priority: ${scored.priority}`, `Recommended Offer: ${scored.recommended_offer}`, `Reasoning: ${scored.reasoning}`, ].join("\n"); return { content: [{ type: "text" as const, text: output }] }; }, );