72bpm-leadgen-mcp-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@72bpm-leadgen-mcp-serverdiscover SaaS companies in Berlin"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
72BPM Lead-Gen MCP Server
An MCP server that turns discovery → enrichment → scoring → outreach into callable tools, scoped to 72BPM's four practice areas:
SaaS Product Development
E-mobility (EV) Applications & Infrastructure
IoT Platforms
AI Agent Creation
Why no LinkedIn API/scraper?
LinkedIn's Terms of Service prohibit automated scraping, and LinkedIn actively detects and blocks it — both technically (rate limits, IP bans) and legally. Rather than build something that breaks on day one and creates legal exposure, this server:
Crawls companies' own public websites directly (careers pages, blog posts, about pages) — fully fair game, standard practice.
Uses a real search engine (Brave Search API) to read back publicly indexed snippets — including of LinkedIn company/people pages — the same way a human researcher googling
site:linkedin.com/company acmewould. This is a search-engine query, not a scrape of linkedin.com itself.Reads public job postings the same way.
If your team later gets access to LinkedIn's official Talent/Sales
Navigator API (via their Partner Program) or a compliant data provider,
swap src/services/searchProvider.ts — every tool depends only on that
one file's webSearch() function.
Related MCP server: Commonality MCP Server
Tools
Tool | Purpose |
| Search-based candidate discovery for one category + region |
| Crawl a company's site + indexed LinkedIn/job signal, matched against all 4 categories |
| Weighted 0-100 fit score + tier (hot/warm/cold) + confidence for one category |
| Search-based candidate engineering contact (CTO/VP Eng/etc.) — unverified, always double-check before outreach |
| Drafts 2 outreach email variants using the value-lead framework |
| Simple pipeline tracking (JSON file by default) |
Typical workflow: discover → enrich → score → find_contact →
generate_pitch → save_lead, then update_lead as deals progress.
Setup
npm install
cp .env.example .env
# edit .env and set BRAVE_API_KEY (free tier: https://brave.com/search/api/)
npm run buildRun locally (stdio) — for Claude Desktop / Claude Code
npm startAdd to your Claude Desktop / Claude Code MCP config:
{
"mcpServers": {
"72bpm-leadgen": {
"command": "node",
"args": ["/absolute/path/to/72bpm-leadgen-mcp-server/dist/index.js"],
"env": {
"BRAVE_API_KEY": "your-key-here"
}
}
}
}Run as a hosted server (streamable HTTP) — for team-wide access
TRANSPORT=http PORT=3000 npm start
# or: npm run start:httpExposes POST /mcp (the MCP endpoint) and GET /health. Point your
team's MCP clients at https://your-host/mcp. Deploy behind your normal
reverse proxy/TLS termination — this server does not handle auth itself,
so put it behind your existing auth layer if exposing it beyond your VPN.
Customizing the ICP signals
src/constants.ts holds the weighted signal dictionary per category
(ICP_SIGNALS). These are the phrases the scoring engine looks for and how
many points each is worth. Tune them as you learn what actually converts —
e.g. if "battery swapping" mentions never turn into real deals, drop its
weight; if a new signal phrase keeps showing up in your best deals, add it.
Tier thresholds (tierFromScore) and confidence thresholds
(confidenceFromSourceCount) live in the same file.
Customizing outreach voice
src/tools/pitch.ts has one AUTHORITY_LINES entry per category — the
"parallel domain authority" sentence 72BPM's pitches lean on. Edit these to
match your team's actual case studies as they accumulate; specific,
verifiable claims outperform generic ones.
Known limitations (by design, not oversights)
No paid enrichment APIs (Apollo/Clearbit/Crunchbase/BuiltWith) — you said you don't have those yet. The signal quality here is real but bounded by what's publicly crawlable. If you add API keys later, this is the natural next upgrade — add a new
services/client and feed its text intomatchSignals()alongside the site crawl.Contact finding is unverified —
leadgen_find_contactparses search snippet text, which is sometimes ambiguous. It's a research shortcut, not a verified contact database. Always confirm before sending outreach.Pipeline storage is a JSON file — fine for one person or a small team running the stdio server locally. For the hosted HTTP deployment with multiple concurrent users, swap
src/services/storage.tsfor a real database (Postgres/SQLite) — every other tool only depends on the four functions that file exports.Brave Search rate limits apply — the free tier is fine for exploration but will need a paid tier for high-volume prospecting.
Project structure
src/
├── index.ts # Entry point, dual transport (stdio/HTTP)
├── constants.ts # ICP signal weights, category labels, thresholds
├── types.ts # Shared TypeScript types
├── services/
│ ├── searchProvider.ts # Brave Search API wrapper (swap for another provider here)
│ ├── webCrawler.ts # Company-site crawler (robots.txt-aware)
│ ├── companyIntel.ts # Combines crawl + search into cached text bundles
│ ├── scoring.ts # Weighted signal matching + scoring
│ └── storage.ts # JSON-file lead pipeline (swap for a DB for hosted use)
└── tools/
├── discover.ts
├── enrich.ts
├── score.ts
├── contact.ts
├── pitch.ts
└── pipeline.tsAvailable Tools
8 toolsleadgen_discover_companiesDiscover Candidate CompaniesARead-only
Searches the public web for companies showing technical ICP signals for one of 72BPM's four practice areas, and returns a de-duplicated, signal-ranked candidate list.
This tool does NOT scrape LinkedIn or any social platform directly. It queries a real search engine (Brave Search) the same way a human researcher would, and reads back only the public snippet text already indexed. Use leadgen_enrich_company next to go deeper on any promising candidate.
Args:
category ('saas' | 'e_mobility' | 'iot' | 'ai_agents'): which practice area to prospect for
region (string, optional): geographic focus, e.g. "India", "UAE"
extra_keywords (string[], optional): up to 5 extra terms to narrow the search
max_results (number): 1-20, default 8
Returns: JSON with schema: { "category": string, "category_label": string, "queries_used": string[], "candidates": [ { "name": string, // best-guess company/page name from search result title "domain": string | null, // extracted domain, use with leadgen_enrich_company "matched_signals": string[],// ICP phrases found in the search snippet itself "sources": [{ "title": string, "url": string, "snippet": string }] } ], "count": number }
Examples:
Use when: "Find e-mobility companies in India working on payment sync" -> category="e_mobility", region="India", extra_keywords=["payment sync"]
Use when: "Who's building multi-agent systems in the UAE" -> category="ai_agents", region="UAE"
Don't use when: you already have a company name and just want its tech profile (use leadgen_enrich_company instead)
Error Handling:
Returns an error message if BRAVE_API_KEY is not configured, with a link to get one
Returns "No candidates found" with the queries tried if the search turned up nothing usable
| Name | Required | Description | Default |
|---|---|---|---|
| region | No | Optional region/country/city to focus the search, e.g. 'India', 'UAE', 'Dubai'. | |
| category | Yes | Which 72BPM practice area to prospect for: 'saas', 'e_mobility', 'iot', or 'ai_agents'. | |
| max_results | No | Maximum candidate companies to return (1-20, default 8). | |
| extra_keywords | No | Optional extra technical or business keywords to narrow the search further. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (read-only, open-world, non-destructive), the description discloses the mechanism ('queries a real search engine (Brave Search)... reads back only the public snippet text'), explicitly states it does NOT scrape LinkedIn, and explains error handling (missing BRAVE_API_KEY, no candidates found). This adds significant behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although the description is longer than average, it is tightly structured with clear sections: purpose, args, returns, examples, error handling. The content is front-loaded with the core purpose, and every section adds necessary information without filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 4 parameters, no output schema in structured fields, and external dependencies, the description is remarkably complete. It covers purpose, mechanism, parameter semantics, full return schema, examples, error handling, and the recommended next tool. This gives an agent everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value by providing concrete examples that map natural language to parameter values ('Find e-mobility companies in India...' → category, region, extra_keywords) and explains how the returned 'domain' integrates with leadgen_enrich_company. This goes beyond the schema's property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Searches') and clearly states the resource (public web) and the output (de-duplicated, signal-ranked candidate list for one of four practice areas). It distinguishes itself from sibling tools by explicitly directing users to leadgen_enrich_company for deeper enrichment and providing a 'Don't use when' example.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides concrete 'Use when' examples with natural-language-to-parameter mappings and a clear negative case ('Don't use when: you already have a company name...'). It also recommends the next step (leadgen_enrich_company), giving explicit guidance on when to use this tool vs alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
leadgen_enrich_companyEnrich Company Technical ProfileARead-only
Builds a technical profile for a specific company by crawling its own public website (homepage, /careers, /about, /blog, /engineering) and cross-referencing an indexed LinkedIn snippet plus public job postings — all via legitimate, ToS-compliant sources (no LinkedIn scraping).
Returns which ICP signal phrases were found, for ALL FOUR practice areas at once, so you can see if a company is a multi-category fit (e.g. an IoT hardware company also hiring for LLM-based ops automation).
Args:
company_name (string): required
domain (string, optional): website domain; enrichment is much richer with it, but LinkedIn/job-posting signal still works without it
Returns: JSON with schema: { "company_name": string, "domain": string | null, "crawled_pages": string[], // URLs successfully crawled "crawl_errors": string[], // pages skipped/failed, with reason "linkedin_snippet": { "title": string, "url": string, "snippet": string } | null, "job_posting_hits": [{ "title": string, "url": string, "snippet": string }], "signals_by_category": { "": { "matched": [{ "phrase": string, "weight": number, "found_in": string[] }], "missing": string[] } } }
Examples:
Use when: "What's ElectreeFi's tech stack look like?" -> company_name="ElectreeFi", domain="electreefi.com"
Use when: you have a candidate from leadgen_discover_companies and want the full picture before scoring
Don't use when: you just want a single category's numeric fit score (use leadgen_score_lead — it's cheaper and more direct)
Error Handling:
If domain is unreachable, crawl_errors will explain why but the tool still returns LinkedIn/job-posting signal
Returns an error if BRAVE_API_KEY is missing and no domain was provided (nothing to enrich from)
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | Company's website domain, e.g. 'electreefi.com'. Omit if unknown — LinkedIn/job data will still be gathered. | |
| company_name | Yes | Company name, e.g. 'ElectreeFi'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=true, etc.), the description adds substantial behavioral context: legitimate/ToS-compliant sources, partial results when domain is unreachable, error conditions for BRAVE_API_KEY, and the multi-category coverage. It transparently documents limitations and edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with sections (overview, Args, Returns, Examples, Error Handling). Every section contributes necessary information, and the return JSON schema is essential given no output schema. The first sentence front-loads the core purpose, and the length is justified by the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description fully equips the agent to use the tool: it explains what enrichment covers, provides a detailed return schema, error handling, and explicit examples. Despite no output schema in annotations, the description carries the burden and fulfills it completely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides complete descriptions for both parameters (100% coverage). The description adds value by explaining the impact of the optional domain parameter ('enrichment is much richer with it') and showing example values in context. This goes beyond the schema's basic type/length constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Builds a technical profile for a specific company by crawling its own public website... and cross-referencing an indexed LinkedIn snippet plus public job postings.' It uses specific verbs and resources, and distinguishes from siblings by explicitly naming leadgen_score_lead as an alternative for single-category scoring.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance with 'Use when' examples and a 'Don't use when' section that names the alternative tool (leadgen_score_lead). It also clarifies when to include the optional domain parameter, making the decision framework complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
leadgen_find_contactFind Candidate Engineering ContactARead-only
Searches public, search-engine-indexed snippets (not a LinkedIn scrape) for a likely engineering decision-maker at a company — CTO, VP Engineering, Head of Engineering, etc.
IMPORTANT: results are UNVERIFIED candidates parsed from search snippet text. They are a starting point for manual confirmation (open the profile URL yourself, or verify via a mutual connection / company site team page), not a guaranteed accurate contact. Never send outreach based solely on this tool's output without a human sanity-check.
Args:
company_name (string): required
role_hint (string, optional): a specific title to prioritize, e.g. "Head of Engineering". Defaults to trying CTO, VP Engineering, Head of Engineering, Engineering Lead, Director of Engineering.
Returns: JSON with schema: { "company_name": string, "candidates": [ { "name_guess": string | null, "title_guess": string | null, "profile_url": string | null, "snippet": string, "verified": false // always false — see IMPORTANT note above } ], "count": number }
Examples:
Use when: "Who leads engineering at ElectreeFi?" -> company_name="ElectreeFi"
Use when: "Find their Head of Data" -> company_name="Acme Corp", role_hint="Head of Data"
Don't use when: you need a verified email address (this tool does not find or guess emails)
Error Handling:
Returns "No candidates found" if search turns up nothing matching common engineering-leadership titles
Returns an error if BRAVE_API_KEY is not configured
| Name | Required | Description | Default |
|---|---|---|---|
| role_hint | No | Preferred title to look for, e.g. 'CTO'. Defaults to trying several common engineering-leadership titles. | |
| company_name | Yes | Company name to search for. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, openWorldHint, etc.), the description discloses critical behavioral traits: results are UNVERIFIED candidates parsed from snippets, the 'verified' field is always false, and the tool never finds emails. It also explains error handling for missing API keys and empty searches, giving the agent a full picture of caveats and failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured into sections: overview, IMPORTANT note, Args, Returns, Examples, and Error Handling. Every section serves a purpose, and the first sentence establishes the core function. The Returns JSON block is somewhat verbose but compensates for the lack of an output schema, so it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (2 params, 1 required) and rich annotations, the description goes beyond the minimum by supplying return format, error cases, default behavior, and usage examples. The lack of an output schema is fully compensated by the inline JSON schema, making the tool's behavior and expected output completely clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes both parameters (100% coverage), so the baseline is 3. The description adds value by listing the default titles tried when role_hint is omitted, and by providing concrete example mappings from natural language to parameter values. This goes beyond the schema's generic description but does not fully transform parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb phrase: 'Searches public, search-engine-indexed snippets... for a likely engineering decision-maker at a company.' It clearly identifies the resource (public snippets), the target role (CTO, VP Engineering, etc.), and the output (candidates). It also distinguishes itself from a LinkedIn scrape, setting it apart from common contact-finder tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'Use when' examples ('Who leads engineering at ElectreeFi?') and an explicit 'Don't use when' exclusion (need a verified email address). It also advises manual confirmation before outreach. However, it does not name sibling tools as alternatives (e.g., leadgen_enrich_company for verified data), so it falls just short of the top score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
leadgen_generate_pitchGenerate Outreach PitchARead-onlyIdempotent
Drafts two personalized outreach email variants for a qualified lead, following 72BPM's value-lead framework: lead with a specific technical friction point (not a sales pitch), show parallel domain authority for the relevant practice area, and close with a low-friction peer-to-peer call to action.
This tool does NOT send anything — it only drafts text for you to review and send yourself.
Args:
company_name (string): required
category ('saas' | 'e_mobility' | 'iot' | 'ai_agents'): required, determines which authority/experience line is used
friction_point (string): required — the specific technical gap to lead with. Pull this from leadgen_enrich_company's matched_signals or crawled content; generic friction points make for generic (worse) pitches
contact_name (string, optional): personalizes the greeting
contact_title (string, optional): for your own reference / future use
sender_name (string, default "[Your name]"): signs the email
Returns: JSON with schema: { "company_name": string, "category": string, "variants": [ { "label": string, "subject": string, "body": string } ] }
Examples:
Use when: you've scored a lead as "hot" and identified its top missing/matched signal, and want ready-to-edit email drafts
Don't use when: you haven't identified a real, specific friction point yet — generic pitches convert poorly; go back to leadgen_enrich_company first
Error Handling:
Returns a validation error if friction_point is missing or too short — this tool refuses to draft a pitch with nothing specific to say
| Name | Required | Description | Default |
|---|---|---|---|
| category | Yes | Which 72BPM practice area this pitch is for. | |
| sender_name | No | Sender's name to sign the email with. | [Your name] |
| company_name | Yes | Company being pitched. | |
| contact_name | No | Recipient's name, if known (from leadgen_find_contact or manual research). | |
| contact_title | No | Recipient's title, if known. | |
| friction_point | Yes | The specific technical friction point to lead with, ideally pulled from leadgen_enrich_company or leadgen_score_lead output — e.g. 'their own FAQ states OCPP payment integrations take 2-6 weeks'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, and the description adds crucial context: 'This tool does NOT send anything — it only drafts text for you to review and send yourself.' It also discloses validation behavior: 'Returns a validation error if friction_point is missing or too short — this tool refuses to draft a pitch with nothing specific to say.' These details go well beyond the structured metadata.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, args, returns, examples, error handling) and front-loads the core purpose. Despite its length, every section earns its place by providing necessary operational detail for a tool with a specialized framework. No fluff or repetition of schema property names.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite lacking an output schema, the description includes an inline JSON example of the return structure, covers error behavior, defines the framework's principles, and gives practical usage guidance. For a six-parameter tool with a specified framework, this description fully equips an agent to select and invoke it correctly without reference to external documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description enhances this by explaining the strategic role of key parameters, e.g., category 'determines which authority/experience line is used' and friction_point should be 'pulled from leadgen_enrich_company's matched_signals or crawled content.' It also warns that 'generic friction points make for generic (worse) pitches,' adding guidance not present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Drafts two personalized outreach email variants for a qualified lead' using a specific framework. It distinguishes itself from pipeline siblings (discovery, enrichment, scoring, contact-finding, lead management) by focusing on content generation, not data retrieval or lead manipulation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: 'Use when: you've scored a lead as "hot" and identified its top missing/matched signal' and 'Don't use when: you haven't identified a real, specific friction point yet... go back to leadgen_enrich_company first.' This gives clear when-to-use, when-not-to-use, and points to the appropriate alternative tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
leadgen_list_leadsList Pipeline LeadsARead-onlyIdempotent
Lists saved leads from the pipeline, optionally filtered by category, tier, or status.
Args:
category, tier, status (all optional): filter the results
Returns: JSON: { "leads": StoredLead[], "count": number } where StoredLead has fields: id, companyName, domain, category, region, score, tier, status, notes, contact, createdAt, updatedAt
Examples:
Use when: "Show me all hot e-mobility leads" -> category="e_mobility", tier="hot"
Use when: "What's still uncontacted?" -> status="new"
| Name | Required | Description | Default |
|---|---|---|---|
| tier | No | ||
| status | No | ||
| category | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context by specifying the return format ('JSON: { "leads": StoredLead[], "count": number }') and the fields of StoredLead, which helps the agent understand what the tool produces. It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a one-sentence summary, an Args section, a Returns section, and Examples. Every element adds value and there is no unnecessary verbosity. The use of code blocks and examples makes it easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description fully documents the return structure. It covers the optional parameters, provides usage examples, and given the simple nature of the tool (list with filters) and the rich annotations, the description is complete enough for an agent to use it correctly. Sibling tools are also distinguishable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description compensates by explaining that category, tier, and status are optional filters, and provides examples showing how each filter can be used. It also describes the StoredLead fields, which clarifies what the filters operate on. This goes beyond the raw schema enums, though it could be more explicit about the meaning of each parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Lists saved leads from the pipeline, optionally filtered by category, tier, or status.' This uses a specific verb ('lists') and resource ('saved leads from the pipeline'), and distinguishes from sibling tools like discover, enrich, score, save, update, which perform different actions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides concrete usage examples: 'Use when: "Show me all hot e-mobility leads" -> category="e_mobility", tier="hot"' and 'Use when: "What's still uncontacted?" -> status="new"'. This gives clear context for when to use the tool and how to map natural language queries to parameters, though it does not explicitly mention alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
leadgen_save_leadSave Lead to PipelineA
Persists a qualified lead to the local pipeline store (a JSON file under ./data by default; see README for swapping in a real database for hosted/multi-user deployments).
Args:
company_name (string): required
domain, region (string, optional)
category ('saas' | 'e_mobility' | 'iot' | 'ai_agents'): required
score (number 0-100, optional): from leadgen_score_lead
tier ('hot' | 'warm' | 'cold', optional): from leadgen_score_lead
notes (string, optional)
contact_name, contact_title, contact_profile_url (string, optional): from leadgen_find_contact
Returns: the saved lead record including its generated "id", which you'll need for leadgen_update_lead.
Examples:
Use when: you've scored a company as hot/warm and want to track it for follow-up
Don't use when: you're just browsing candidates (save only once you're tracking it for real)
| Name | Required | Description | Default |
|---|---|---|---|
| tier | No | ||
| notes | No | ||
| score | No | ||
| domain | No | ||
| region | No | ||
| category | Yes | ||
| company_name | Yes | ||
| contact_name | No | ||
| contact_title | No | ||
| contact_profile_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the sparse annotations (readOnlyHint=false), the description discloses storage location (local JSON file), persistence behavior, and that it returns a generated 'id' needed for leadgen_update_lead. This is rich behavioral context not available elsewhere.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with an Args list, Returns note, and Examples section. Every sentence adds value—no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 10 parameters, no output schema, and minimal annotations, the description covers all critical aspects: persistence semantics, storage details, return value, and usage context. It is complete enough for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but description fully compensates by listing each parameter with required/optional status and origin (e.g., 'from leadgen_score_lead', 'from leadgen_find_contact'). This adds meaning beyond the bare types/enums in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: "Persists a qualified lead to the local pipeline store." This uses a specific verb ('persists') and resource ('lead'), and distinguishes it from siblings like leadgen_update_lead (updating existing leads) and leadgen_list_leads (listing).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is provided: "Use when: you've scored a company as hot/warm and want to track it for follow-up" and "Don't use when: you're just browsing candidates." This clearly states when to use vs. avoid.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
leadgen_score_leadScore Lead FitARead-only
Computes a weighted 0-100 ICP fit score for one company against one 72BPM practice area, with a tier (hot/warm/cold) and a confidence level based on how many independent public sources corroborated the signal.
Internally this reuses the same public-source gathering as leadgen_enrich_company (and shares its short-lived cache, so calling enrich then score on the same company won't double the network calls).
Args:
company_name (string): required
domain (string, optional): website domain — scoring is more reliable with it
category ('saas' | 'e_mobility' | 'iot' | 'ai_agents'): required, which practice area to score against
Returns: JSON with schema: { "company_name": string, "category": string, "category_label": string, "score": number, // 0-100 "tier": "hot" | "warm" | "cold", "confidence": "low" | "medium" | "high", // based on # of independent sources with matches "matched_signals": [{ "phrase": string, "weight": number, "found_in": string[] }], "missing_high_value_signals": string[], // top signals NOT found — good discovery-call questions "rationale": string }
Tier thresholds: score >= 55 = hot, >= 30 = warm, else cold. Confidence: 3+ independent sources = high, 2 = medium, 0-1 = low. Treat "low confidence + hot tier" as promising but unverified — worth a human look before outreach.
Examples:
Use when: "Is Acme Corp a good IoT lead?" -> company_name="Acme Corp", domain="acme.com", category="iot"
Don't use when: you want the full multi-category breakdown (use leadgen_enrich_company instead)
Error Handling:
Returns an error if BRAVE_API_KEY is missing and domain gathers nothing
Returns score=0, tier="cold", confidence="low" (not an error) if the company has no public signal at all — that's a valid, informative result
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | Company's website domain, if known. | |
| category | Yes | Which practice area to score fit against: 'saas', 'e_mobility', 'iot', or 'ai_agents'. | |
| company_name | Yes | Company name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even with readOnlyHint=true, the description adds rich behavioral context: it shares a cache with leadgen_enrich_company, explains tier and confidence thresholds, defines the low-confidence+hot-tier caveat, and details error handling (including the score=0/cold/low no-signal case). No contradictions 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections (Args, Returns, thresholds, Examples, Error Handling). Every sentence adds operational or decision-relevant detail, and the first sentence front-loads the core purpose. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is moderately complex (3 params, no output schema in the tool definition, error cases, thresholds). The description compensates by providing a full return schema, threshold values, confidence semantics, cache-sharing behavior, and error handling. Contextually complete for an AI agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all parameters. The description adds value by specifying that domain makes scoring 'more reliable,' clarifying that category is a practice area, and providing a concrete example mapping natural language to parameter values. This goes beyond the schema's basic 'Company name' / 'Which practice area' descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Computes a weighted 0-100 ICP fit score for one company against one 72BPM practice area.' It clearly distinguishes this from sibling tools by explaining the single-category scoring focus and pointing to leadgen_enrich_company for multi-category breakdowns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'Use when' and 'Don't use when' examples with a concrete query and a named alternative: 'Don't use when: you want the full multi-category breakdown (use leadgen_enrich_company instead).' This is model-level guidance for when to select this tool versus a sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
leadgen_update_leadUpdate Pipeline LeadAIdempotent
Updates a saved lead's status and/or notes — e.g. after sending outreach or getting a reply.
Args:
lead_id (string, uuid): required, from leadgen_save_lead or leadgen_list_leads
status ('new'|'researching'|'contacted'|'replied'|'qualified'|'disqualified', optional)
notes (string, optional)
At least one of status or notes must be provided.
Returns: the updated lead record, or an error if lead_id doesn't exist.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | ||
| status | No | ||
| lead_id | Yes | The lead's id, returned by leadgen_save_lead or leadgen_list_leads. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety profile (not read-only, not destructive, idempotent). Description adds that it returns the updated lead record or an error if lead_id doesn't exist, plus the at-least-one constraint. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Format is front-loaded with purpose, uses a structured Args list, constraint line, and return statement. Every sentence earns its place; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-param update tool with no output schema, it covers return values and error behavior, usage examples, and constraints. Slightly sparse on notes semantics, but overall adequate given annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is low (33%); description repeats the lead_id source (already in schema) and enum values for status, but adds no meaning for notes beyond type. The only new info is the at-least-one requirement, which is more a usage rule than parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States clearly it updates a saved lead's status and/or notes, with examples of when (after outreach/reply). Distinguishes from siblings like save_lead (create) and list_leads (read).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context (after outreach/reply) and a hard constraint (at least one of status/notes required). Does not explicitly name alternatives, but the example plus sibling set make the intended use evident.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
8 tool updates
v1.0.0- First observed
leadgen_discover_companies - First observed
leadgen_enrich_company - First observed
leadgen_find_contact - First observed
leadgen_generate_pitch - First observed
leadgen_list_leads - First observed
leadgen_save_lead - First observed
leadgen_score_lead - First observed
leadgen_update_lead
TDQS
Each tool has a distinct phase in the lead-gen workflow: discover finds candidates, enrich profiles a company, score quantifies fit, find_contact locates people, generate_pitch writes emails, and save/list/update manage the pipeline. Even the similar enrich vs. score are clearly differentiated by multi-category vs. single-category output.
All tools follow the exact pattern leadgen_<verb>_<noun> with clear, consistent verbs (discover, enrich, score, find, generate, save, list, update). The prefix unifies the namespace and the verb_noun structure makes each tool's purpose predictable.
8 tools is well-scoped for a specialized lead-generation workflow. Each tool covers a necessary step without redundancy or bloat, and the count is within the ideal range for a focused MCP server.
The lifecycle is nearly complete: discovery, enrichment, scoring, contact finding, pitch generation, and pipeline CRUD (save/list/update). The only notable gap is the absence of a delete/archive tool for leads, though the status field can handle disqualification, so agents can work around this.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Marketo MCP server for AI. 130 tools to operate Marketo from Claude, Cursor, or ChatGPT.
MCP server for VC pitch-deck scoring, thesis-fit matching, and deal-flow management.
API-first CRM for LLMs - contacts, companies, deals and activities over a native MCP server.
Cross-product MCP server for CRM, LeadKit, ProjectKit, Bookio. 10 action types, MIT open spec.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server for qualifying and responding to inbound leads in seconds using a multi-agent AI pipeline.1MIT
- AlicenseNot gradedqualityBmaintenanceMCP-native sales intelligence server enabling prospect enrichment, LinkedIn scraping, and CRM push to HubSpot/Salesforce via natural language.12Mozilla Public 2.0
- FlicenseAqualityBmaintenanceAI-powered B2B outbound sales automation pipeline exposed as an MCP server that transforms natural language goals into qualified sales intelligence and personalized emails.9-
- FlicenseNot gradedqualityCmaintenanceCustom MCP server for HubSpot CRM providing ICP segmentation, scoring, duplicate detection, Data Quality Score, and lifecycle stage automation. Exposes 39 tools to enhance HubSpot's native capabilities.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/Yadukrishnan117/72bpm-leadgen-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server