Skip to main content
Glama
gomessoaresemmanuel-cpu

linkedin-prospection-mcp

Score a Lead

score_lead
Read-only

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
NameRequiredDescriptionDefault
nameYesLead's full name
titleNoJob title / headline
companyNoCompany name
post_snippetNoText from their LinkedIn post
linkedin_urlNoLinkedIn profile URL

Implementation Reference

  • 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 }] };
      },
    );
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations establish readOnlyHint=true (safe operation). Description adds valuable behavioral context beyond annotations: discloses the three-factor scoring algorithm (fit/intent/urgency), specifies return format (P1-P4 priority tiers), and mentions recommended offer generation. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero waste. First sentence establishes scoring methodology; second discloses return values. Front-loaded with critical information (P1-P4 priority, specific signals like burnout). No redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Adequately compensates for missing output schema by explicitly stating return values (priority tiers P1-P4 and offer recommendations). Covers the 5 parameters sufficiently given 100% schema coverage. Minor gap: does not mention that only 'name' is required while other fields are optional, though this is discoverable in schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, providing complete documentation for all 5 parameters (name, title, company, post_snippet, linkedin_url). Description frames these as 'LinkedIn lead' data but does not add syntax, format constraints, or semantic relationships beyond what the schema already provides. Baseline 3 appropriate given high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description provides specific verb (Score) + resource (LinkedIn lead) + distinct methodology (fit/intent/urgency with specific signals like burnout/crisis markers). Clearly distinguishes from sibling 'find_leads' (discovery) and 'manage_lead' (CRUD) by specifying analytical scoring function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context for when to use through specific scoring dimensions (ICP match, burnout signals, crisis markers), implying this is for nuanced prioritization scenarios. Lacks explicit 'when-not' or direct comparison to sibling 'qualify_leads', but the three specific criteria provide sufficient contextual differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gomessoaresemmanuel-cpu/linkedin-prospection-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server