Generect Live API MCP Server
OfficialThis server gives AI agents access to the Generect B2B database for finding, qualifying and contacting people and companies, with free exploration and pay-per-result pricing.
Size an audience for free —
count_leads/count_companiesreturn match counts plus a cost estimate before you spend anything.Search leads and companies —
search_leads/search_companiesreturn free thin rows (daily quota) or billed full rows, filtered by titles, seniority, location, industry, headcount, technologies and more.Cheap previews —
preview_leadsgives a low-cost look at real people behind a count.Enrich records —
enrich_lead,enrich_company,get_lead_by_urlandresolve_profile(including anonymousACwAA…LinkedIn links) return full profiles.Get contact data —
generate_emailfinds verified work emails,validate_emailchecks deliverability,find_phonereturns phone numbers.Run bulk jobs —
start_bulk_job(up to 50 records) and freeget_bulk_jobpolling for async email/phone/enrichment work.Manage webhooks — create, list, update, delete and test endpoints that receive bulk-job completion events.
Check account state —
get_balancefor balance, month-to-date spend and per-operation prices;healthfor liveness and credential checks.Stay budget-safe — every response includes a
costblock, calls above a $5 spend ceiling needconfirm_spend_usd, and a test key returns fictional data for free.
Click on "Deploy 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., "@Generect Live API MCP Serversearch for leads with title CEO in SaaS companies"
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.
What it does
Give Claude, ChatGPT, Cursor or your own agent access to the Generect B2B database: people and companies by ICP, emails, phones and full profiles.
Free to explore. Counting an audience is free, and so is a database search with thin rows (who, role, where, which company), up to a daily row quota per account.
Pay for what you keep. Emails are billed only when a valid one is found, phones only when found, full profiles per record found.
No surprise bills. Every tool says up front whether it costs money, every response carries a
costblock with the amount actually charged, and calls above a spend ceiling need an explicit confirmation. Tools that can charge are not marked read-only, so Claude and other hosts ask before running them (choose "Always allow" for the ones you trust); counting, balance and health run without asking.Safe to try. A test key returns realistic fictional data at real speed and charges nothing.
Interactive in the chat. In Claude, ChatGPT and other hosts that support MCP Apps, results come back as cards you can act on: an audience card with prices, a lead table where you pick people and find their emails, company and profile cards, your balance.
Related MCP server: scrapercity-cli
Connect
Get an API key at app.generect.com/settings/api. Clients that support OAuth sign you in without one.
Remote server (recommended)
https://mcp.generect.com/mcp speaks streamable HTTP with OAuth 2.1, so most clients only need the URL. It serves MCP protocol revision 2026-07-28 (stateless, discovered via server/discover) and the 2025 revisions (2025-11-25, 2025-06-18) side by side, so any current client connects without settings.
Claude Code
claude mcp add --transport http generect https://mcp.generect.com/mcpClaude.ai and Claude Desktop: Settings, Connectors, Add custom connector, then paste https://mcp.generect.com/mcp.
Cursor (.cursor/mcp.json) and other JSON-configured clients:
{
"mcpServers": {
"generect": {
"url": "https://mcp.generect.com/mcp"
}
}
}The first connection opens the Generect consent page in the browser. Approve it with the account you are already signed into, and the client receives its own token.
No OAuth in your client? Pass the key as a header, for example with mcp-remote:
{
"mcpServers": {
"generect": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.generect.com/mcp", "--header", "Authorization: Bearer YOUR_API_KEY"]
}
}
}Local server (stdio)
{
"mcpServers": {
"generect": {
"command": "npx",
"args": ["-y", "generect-ultimate-mcp@latest"],
"env": {
"GENERECT_API_KEY": "YOUR_API_KEY"
}
}
}
}Requires Node 20 or newer. Optional: GENERECT_API_BASE (default https://api.generect.com) and GENERECT_TIMEOUT_MS. If Claude Desktop on macOS reports spawn npx ENOENT, set command to the absolute path of npx.
Test mode
Use a test_… key from app.generect.com/settings/api in any of the configs above. Every tool then answers with fictional data, shows what the real call would have cost and charges nothing. Results carry test_mode: true so an agent cannot mistake them for real people. See Test mode.
Interactive results (MCP Apps)
Hosts that support the MCP Apps extension (Claude on web, desktop and mobile, ChatGPT, VS Code, Goose and others) render these tools as interactive views inside the conversation. Other clients get the same text and structured results as before.
Tool | What you see |
| The audience size, your filters, what the next step costs at your prices, and a button to see the first 25 |
| The top people inline; open all of them as a table, filter, select, and find work emails right there. You confirm the maximum before anything is spent, a miss is free, and found emails go back to Claude so it can use them |
| Company cards and a table, with a one-click ask for decision makers at them |
| A profile card with the experience timeline and a find-email button |
| Balance, this month's spend and your per-operation prices |
| Which emails were found and what it cost |
The views follow the host's theme (light and dark), fonts and layout, and work on phones. Results from a test key are labelled as fictional.
Tools
Free
Tool | What it does |
| How many people match an ICP, and what the next step costs at your rates. Start here. |
| The same for companies. |
| People matching an ICP. Free with the default thin rows (database mode, daily quota). |
| Companies matching an ICP. Free with the default thin rows (database mode, daily quota). |
| Balance, your real per-operation prices, and optionally spend by operation or by token. |
| Poll a bulk job (the work was billed at submit time). |
| Manage the webhook endpoints that receive bulk-job completion events. |
| Liveness and credential check against a free endpoint. Safe for monitors. |
Billable
Tool | Billed |
| per returned row |
| per returned row ( |
| per resolved profile, the cheapest paid call; an unresolvable link is free |
| per record found |
| per record found |
| per valid email found |
| per email submitted, whatever the verdict |
| per phone found, the most expensive operation |
| per record, reserved when the job is submitted |
Prices depend on your account tier: get_balance returns yours, and every response reports what was actually charged.
A budget-safe flow
count_leads (free) → search_leads, thin rows (free) → generate_email on the ids you keep (per valid email)
→ enrich_lead / find_phone only where neededThin and full rows
search_leads and search_companies take detail:
left out (default): thin rows while the free tier is available. Once it is not (quota spent, a custom-contract account), the search continues with full rows billed per row and says so in
thin_unavailable."thin": free rows only. Never billed and never escalated to realtime; a spent quota returns a 429."full": the whole record, billed per row.
Thin lead rows carry id, name, job title, seniority, location and company (name, id, industry, country). Thin company rows carry id, name, industry, headcount range, HQ city and country, company type and founding year. Neither carries a LinkedIn URL, domain, contacts or history: generate_email takes the lead id directly, and enrich_lead / enrich_company return the full record.
Database and realtime
Search and enrich run against the Generect database (sub-second, free counts) or a live LinkedIn lookup (5 to 60 seconds, billed counts, every filter). Tools take mode:
auto(default) tries the database first and escalates only if the API says a filter you passed is not supported there. The escalation is reported and is refused above the spend ceiling.databasenever escalates: an unsupported filter is an error, not a bigger bill.realtimegoes live directly. Counting live costs money, socount_*run it only when asked for explicitly.
Filter vocabularies
company_industries and seniorities accept unknown values silently and return zero results, which reads like "this audience does not exist". The server therefore checks values before sending anything: unknown industries, headcount buckets and company types are refused locally with the closest valid names, and mis-cased values are corrected. allow_unlisted_values: true overrides the check.
The full vocabularies are exposed as resources:
generect://vocabulary/industries
generect://vocabulary/seniorities
generect://vocabulary/functions (realtime only)
generect://vocabulary/company-types
generect://vocabulary/headcounts
generect://vocabulary/follower-ranges (realtime only)
generect://account/pricing your per-operation prices
generect://account/balance balance and month-to-date usagePrompts
Workflow prompts appear as slash commands in clients that support them: size_an_audience, build_prospect_list, enrich_my_list and spend_report. Each one starts from the free step.
Spend ceiling
A row cap bounds results, not money. Any call whose worst case exceeds MCP_MAX_SPEND_PER_CALL (default $5) is refused with the exact figure and must be repeated with confirm_spend_usd set to at least that amount. start_bulk_job is checked before it submits, because a bulk job reserves its whole cost up front.
Agent skill
Tools let an agent call Generect; the skill teaches it the procedure above.
npx skills add generect/generect_mcp --skill generect-lead-workflowsSee skills/README.md.
More
Operating and self-hosting the server: logging, OAuth endpoints, security settings, deployment, Docker
If Generect saves you time, a star on this repository helps other people find it.
License
MIT
Available Tools
21 toolscount_companiesCount matching companies (free)ARead-onlyIdempotentInspect
How many companies match an ICP, and what pulling them would cost. Free: this call never spends credits. The first step before search_companies. As with count_leads, a realtime count costs $0.04 at the Tier 0 list price and runs only when mode:"realtime" is passed explicitly.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Data mode. "database" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. "realtime" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. "auto" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick "database" explicitly when you only need a size estimate and cost matters more than freshness. | |
| keywords | No | Free-text keywords across name/description/specialties — realtime only: using it forces the pricier live mode. | |
| locations | No | HQ locations — cities, states or countries. | |
| headcounts | No | Size buckets. Allowed ONLY: "1-10","11-50","51-200","201-500","501-1000","1001-5000","5001-10000","10 000+". | |
| industries | No | Company industries. Must match Generect industry names exactly (e.g. "Software Development"); unknown names are rejected with HTTP 400. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| exclude_ids | No | Exclude companies by LinkedIn id/URN. | |
| technologies | No | Technologies the company uses — realtime only: using it forces the pricier live mode. | |
| company_names | No | Restrict to specific company names — realtime only: using it forces the pricier live mode. | |
| company_types | No | Company types: "Public Company","Privately Held","Non Profit","Government Agency","Educational", … | |
| revenues_range | No | Annual revenue range, single object {min,max} — realtime only: using it forces the pricier live mode. | |
| sub_industries | No | Expand each selected industry to its sub-industries as well (broadens the match). | |
| exclude_domains | No | Exclude companies by domain (e.g. existing customers). | |
| linkedins_links | No | Specific LinkedIn company URLs — realtime only: using it forces the pricier live mode. | |
| headcount_growth | No | Headcount growth in percent — realtime only: using it forces the pricier live mode. | |
| num_of_followers | No | LinkedIn follower buckets: "1-50","51-100","101-1000","1001-5000","5001+" — realtime only: using it forces the pricier live mode. | |
| exclude_locations | No | HQ locations to exclude. | |
| get_max_companies | No | DEPRECATED — accepted but ignored. Always on now: search responses include results_count without asking. | |
| exclude_industries | No | Industries to exclude. | |
| hiring_on_linkedin | No | Only companies actively hiring — realtime only: using it forces the pricier live mode. | |
| fallback_from_leads | No | DEPRECATED — accepted but ignored. Removed. It fabricated lead-derived name aggregates and cost an extra billable query. | |
| department_headcount | No | Department size, e.g. {"name":"engineering","min":10,"max":100} — realtime only: using it forces the pricier live mode. | |
| allow_unlisted_values | No | Escape hatch for the local vocabulary check — see the lead-side field of the same name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| fix | No | |
| why | No | |
| cost | No | |
| mode | No | |
| advice | No | |
| status | No | |
| options | No | |
| test_mode | No | |
| results_count | No | |
| needs_realtime | No | |
| test_mode_notice | No | |
| next_step_estimate | No | |
| vocabulary_warnings | No | |
| blocked_by_vocabulary | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld, so the bar is lower, yet the description still adds real billing behavior: the call never spends credits, and a realtime count costs $0.04 at Tier 0 list price. It omits latency and result shape, but the output schema covers the latter.
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?
Three sentences with the core purpose front-loaded and no filler. The 'As with count_leads' cross-reference is slightly indirect and forces the agent to consult another tool's text to resolve the pricing claim, costing it a point.
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 23-parameter tool with full schema coverage, an output schema, and complete annotations, the description supplies the missing piece an agent most needs before calling: the cost model and its position in the search workflow. Filter-level caveats (realtime-only fields, vocabulary validation) are already carried by the schema.
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 earns an extra point by explaining the cost consequence of the mode parameter (realtime is the only path that bills, at $0.04). It does not add anything about the 20+ filter parameters, which the schema already documents well.
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 a specific operation (count companies matching an ICP) plus a second concrete output (the credit cost of pulling them), and positions itself explicitly as 'the first step before search_companies'. That distinguishes it from both search_companies and count_leads without requiring an agent to open any schema.
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 first step before search_companies' plus the note that realtime runs only when mode:"realtime" is passed explicitly gives clear sequencing and mode guidance. It stops short of naming when NOT to use it (e.g. use search_companies when you actually need rows), so it doesn't reach a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
count_leadsCount matching leads (free)ARead-onlyIdempotentInspect
How many leads match an ICP, and what pulling them would cost at this account's prices. Free: this call never spends credits. It is the only way to size an audience without paying per row, which makes it the first step before search_leads. A realtime count is not free ($0.04 flat at the Tier 0 list price); it runs only when mode:"realtime" is passed explicitly.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Data mode. "database" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. "realtime" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. "auto" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick "database" explicitly when you only need a size estimate and cost matters more than freshness. | |
| strict | No | Fields to match strictly, e.g. ["company_locations"]. | |
| keywords | No | Free-text keywords across headline/summary/skills — realtime only: using it forces the pricier live mode. | |
| personas | No | Advanced raw persona tuples [name, functions, seniorities, prohibits, priority?] — realtime only: using it forces the pricier live mode. | |
| functions | No | Job functions, e.g. ["Sales","Marketing","Engineering"] — realtime only: using it forces the pricier live mode. | |
| job_title | No | DEPRECATED alias for job_titles. Still honoured: it is merged into job_titles. | |
| locations | No | Where the lead lives — matches cities, states and countries, e.g. ["United States","Berlin"]. | |
| company_id | No | Anchor to one company by LinkedIn numeric id. | |
| job_titles | No | Target job titles, OR-matched (e.g. ["CEO","Founder","Owner"]). A lead needs to match only one. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| exclude_ids | No | Skip leads by Generect/Sales-Navigator id. Pass the ids you already received to paginate without duplicates — ordering is not stable, so this is more reliable than offset. | |
| seniorities | No | Seniority at the current employer, e.g. ["Owner","CXO","VP","Director","Manager"]. Current position only. | |
| changed_jobs | No | Only leads who recently changed jobs — realtime only: using it forces the pricier live mode. | |
| company_link | No | Anchor to one company by LinkedIn URL. | |
| company_name | No | Anchor to one company by name (exclusive with company_link/company_id). | |
| company_types | No | Employer types: "Public Company","Privately Held","Non Profit","Government Agency","Educational","Self Employed","Self Owned","Partnership". | |
| exclude_names | No | Skip leads by full name. Works in both modes (the database-mode bug that returned 0 rows was fixed in the API on 2026-08-13, PRO-1333). exclude_ids is still the more reliable way to paginate. | |
| get_max_leads | No | DEPRECATED — accepted but ignored. Always on now: search responses include results_count without asking. | |
| company_filters | No | Optional: count leads only at companies matching these company filters (a two-level ICP). Still free in database mode. | |
| lead_industries | No | DEPRECATED — accepted but ignored. Removed: v1 filters on the employer's industry. Use company_industries. | |
| without_company | No | DEPRECATED — accepted but ignored. No longer needed — v1 filter-only search is the default when no company anchor is set. | |
| years_in_company | No | Time at current company, same buckets as years_in_position — realtime only: using it forces the pricier live mode. | |
| company_locations | No | HQ location of the lead's current employer. | |
| exclude_locations | No | Lead locations to exclude. | |
| filter_empty_vars | No | Drop leads where these fields are empty, e.g. ["profile_photo","job_started_on"]. Useful to raise data quality before paying. | |
| years_in_position | No | Time in current role: 1=<1y, 2=1-2y, 3=3-5y, 4=6-10y, 5=10y+ — realtime only: using it forces the pricier live mode. | |
| company_headcounts | No | Employer size buckets. Allowed ONLY: "1-10","11-50","51-200","201-500","501-1000","1001-5000","5001-10000","10 000+" (note the space in "10 000+"). | |
| company_industries | No | Industry of the current employer. Must match Generect industry names exactly (e.g. "Software Development", "Financial Services"); names are hierarchical and unknown names are rejected with HTTP 400 naming the field. | |
| past_company_names | No | Companies the lead previously worked at (alumni targeting) — realtime only: using it forces the pricier live mode. | |
| posted_on_linkedin | No | Only leads who recently posted on LinkedIn — realtime only: using it forces the pricier live mode. | |
| linkedin_filter_link | No | A LinkedIn / Sales Navigator search URL to lift filters from — realtime only: using it forces the pricier live mode. | |
| allow_unlisted_values | No | Escape hatch. This server checks industry / seniority / headcount / company-type values against the LinkedIn vocabularies before sending, because the API silently returns 0 results for an unknown industry or seniority instead of rejecting it. Set true only when you are sure a value is valid and this server is out of date. | |
| exclude_title_keywords | No | DEPRECATED — accepted but ignored. No v1 equivalent. Narrow job_titles instead, or filter the returned rows yourself. | |
| exclude_company_locations | No | Employer HQ locations to exclude. | |
| exclude_company_headcounts | No | Employer size buckets to exclude. | |
| exclude_company_industries | No | Employer industries to exclude. |
Output Schema
| Name | Required | Description |
|---|---|---|
| fix | No | |
| why | No | |
| cost | No | |
| mode | No | |
| advice | No | |
| status | No | |
| options | No | |
| test_mode | No | |
| results_count | No | |
| needs_realtime | No | |
| test_mode_notice | No | |
| next_step_estimate | No | |
| vocabulary_warnings | No | |
| blocked_by_vocabulary | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description discloses the economics that matter for this API: the call never spends credits, the $0.04 flat realtime price at Tier 0, and the fact that realtime runs only when explicitly requested. The consistency between 'never spends credits' and readOnlyHint=true reinforces trust rather than contradicting it.
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?
Three sentences, front-loaded with the core outcome, then the free/paid distinction, then the realtime cost caveat. Every sentence carries weight; the only mild inefficiency is the slightly convoluted first clause ('what pulling them would cost at this account's prices').
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 36 parameters, a 100% documented schema, and an output schema present, the description does not need to restate filters or return shape. It covers the two things the schema cannot: that the default path is free and that realtime billing is opt-in. A brief note on the two-level ICP (company_filters) would have made it fully complete.
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 and the schema already documents mode, strict, exclude_ids and the rest in depth. The description still adds value the schema does not: the concrete realtime price and the warning that passing mode:'realtime' is what triggers billing, which turns an enum choice into a cost decision.
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 states a specific resource and outcome — how many leads match an ICP and what pulling them would cost — and explicitly separates itself from search_leads ('the first step before search_leads'). Even though it is phrased as a question rather than a verb, an agent can immediately tell this is a sizing/counting tool, not a row-returning one.
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?
It gives clear routing logic: use this first to size an audience for free, then call search_leads to actually pull rows, and avoid mode:'realtime' unless you accept a $0.04 charge. The one gap is that the sibling count_companies (the company-side equivalent) is never mentioned, so the leads-versus-companies choice is left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_webhookCreate a webhook (free)ADestructiveInspect
Register a URL that receives bulk-job completion events, so scheduled or unattended workflows are notified instead of polling. Each event carries the job's results (emails, phone numbers or records) in its body. Free: this call never spends credits.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL that receives the events, http or https. The API refuses a host that resolves to a private or internal address. | |
| events | Yes | Events to subscribe to. | |
| secret | No | Shared secret for HMAC signature verification. | |
| timeout_ms | No | Request timeout in milliseconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| action | No | |
| webhooks | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (destructive/openWorld/readOnly), so the description's real contribution is the event payload content and the credit-cost guarantee, both of which are useful and not encoded anywhere else. It stops short of noting that a previously registered URL is replaced or that the URL is validated against private addresses.
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?
Three sentences, each carrying distinct information: what it registers, what arrives in the event body, and the cost profile. Front-loaded and free of repetition.
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 an output schema present and annotations covering safety, the description covers purpose, payload, and billing, which is enough for correct invocation. The only gap is what happens on re-registration or duplicate URLs.
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% and every parameter, including the SSRF guard on url, is documented in the schema. The description adds no field-level semantics beyond that, so the baseline 3 applies.
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 a specific verb and resource ('Register a URL that receives bulk-job completion events') and scopes it to the bulk-job event family, which an agent can distinguish from the sibling webhook tools (list_webhooks, test_webhook, update_webhook, delete_webhook).
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 'instead of polling' phrasing implies when a caller would want this, but no sibling alternative or exclusion is named and no precondition for using it over test/update is given. Usage is inferable rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_webhookDelete a webhook (free)ADestructiveInspect
Delete a registered webhook; its endpoint stops receiving completion events. Free: this call never spends credits.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Webhook id, from list_webhooks. | |
| timeout_ms | No | Request timeout in milliseconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| action | No | |
| webhooks | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is covered. The description adds useful behavioral context beyond annotations: the endpoint stops receiving completion events, and the call never spends credits.
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?
Two short sentences, front-loaded with the action and its effect. The cost note is brief and relevant, with no wasted phrasing.
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 simple two-parameter schema, full schema description coverage, destructive annotations, and the presence of an output schema, the description is largely complete for correct invocation. It could still say more about selecting this tool over update_webhook or test_webhook, but that is a usage-guidance gap rather than a missing operational detail.
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 description coverage is 100%, so both the required 'id' and optional 'timeout_ms' are already documented in the schema. The description adds no parameter-specific meaning, which is acceptable at the baseline for fully covered schemas.
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 states a specific verb and resource: 'Delete a registered webhook,' and adds the consequence that the endpoint stops receiving completion events. It is clearly distinct from most siblings, but it does not explicitly differentiate itself from related webhook tools such as update_webhook or test_webhook.
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?
It does not say when to use this tool versus alternatives like update_webhook or test_webhook, nor does it mention prerequisites or exclusions. The action is implied by 'Delete,' but no real routing guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
enrich_companyEnrich one companyAInspect
Full profile for one known company, by Generect id, LinkedIn URL, domain or name. Billable: about $0.02 per record found (not-found is refunded) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. Not found costs nothing. Domain is the most reliable identifier after id; name matching is fuzzy.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Generect company id. | |
| mode | No | Data mode. "database" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. "realtime" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. "auto" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick "database" explicitly when a recent cached record is good enough and cost matters more than freshness. | |
| name | No | Company name (fuzzy match). | |
| domain | No | Company domain without protocol, e.g. "stripe.com". | |
| compact | No | Default true: return a small per-company summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| linkedin_url | No | LinkedIn company page URL. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| lead | No | |
| mode | No | |
| found | No | |
| company | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses that the call is billable at ~$0.02 per record found, that not-found is refunded, that account-specific pricing is retrievable via get_balance, and that the actual charge appears in cost.amount_charged_usd. That is exactly the financial context an agent needs before spending.
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?
Front-loaded with identity and price, and dense with useful detail. Mild redundancy: "(not-found is refunded)" is restated by "Not found costs nothing".
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?
An output schema exists, so return contents need not be described, and cost, identifiers, and modes are covered. The one gap is that all seven parameters are optional and the description never says at least one identifier must be supplied.
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 baseline is 3; the description adds genuine value by ranking identifier reliability (id > domain > fuzzy name) and pointing at the cost field. Mode/compact semantics live in the schema rather than the description, so it does not fully exceed 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?
States a concrete verb and resource ("Full profile for one known company") and enumerates the four accepted identifiers. The singular, known-entity framing implicitly separates it from search_companies, but no sibling is named explicitly.
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?
Gives real selection guidance on identifiers — domain is the most reliable after id, name matching is fuzzy — and the schema's mode description explains database vs realtime vs auto. It does not explicitly say when to prefer search_companies or resolve_profile over this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
enrich_leadEnrich one leadAInspect
Full profile for one known person, by Generect id, LinkedIn URL or work email (reverse lookup). Billable: about $0.02 per record found (not-found is refunded) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. Not found costs nothing. The id from a search or preview result is the most accurate identifier. start_bulk_job handles many people at once.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Generect lead id from search/preview. | |
| mode | No | Data mode. "database" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. "realtime" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. "auto" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick "database" explicitly when a record from the last 12 months is good enough and cost matters more than freshness. | |
| No | Work email, for reverse lookup. | ||
| compact | No | Default true: return a small per-lead summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| linkedin_url | No | LinkedIn profile URL. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| lead | No | |
| mode | No | |
| found | No | |
| company | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses billing behavior in detail (about $0.02 per found record, refunded on not-found, account-specific pricing via get_balance, actual spend in cost.amount_charged_usd) plus the auto-mode escalation rule and its spend ceiling — none of which is in the annotations. Annotations cover open-world/non-destructive traits; the description adds the cost and escalation context an agent needs before calling a billable tool.
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?
Front-loaded with purpose and identifiers, then cost, then escalation/routing — a sensible order with no filler. The pricing clauses are dense but each carries decision-relevant information for a billable call.
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?
An output schema exists so return values need no explanation, and the description covers the remaining gaps an agent would care about: cost, refunds, escalation behavior, identifier preference, and the bulk alternative.
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 still adds ranking guidance by saying the `id` is the most accurate identifier and framing email as reverse lookup, which the schema does not state. It does not elaborate on `mode`, `compact`, or `timeout_ms`, but those are already fully documented 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?
States a specific verb+resource ('Full profile for one known person') and enumerates the accepted identifier types, including that email is a reverse lookup. This clearly separates it from list-style siblings like search_leads and preview_leads.
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?
Gives explicit routing guidance: use the `id` from search/preview for accuracy, and use start_bulk_job for many people at once. However, it never distinguishes itself from closer siblings like get_lead_by_url or resolve_profile, which appear to overlap substantially.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_phoneFind a phone number (most expensive)AInspect
Find a phone number for one person. Billable: about $0.4 per phone found (a miss is free) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. The most expensive operation here, roughly 20x an email lookup, so it suits people the user has already qualified rather than a whole list. start_bulk_job takes an approved list.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | Company domain without protocol, e.g. "stripe.com" (name+domain mode). | |
| company | No | Company name or domain (name+company mode). | |
| lead_id | No | Generect lead id from search / preview / enrich results — the cheapest and most accurate identifier. | |
| last_name | No | Last name (name+domain mode). | |
| first_name | No | First name (name+domain mode). | |
| timeout_ms | No | Request timeout in milliseconds. | |
| linkedin_url | No | LinkedIn profile URL. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| result | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the annotations: a concrete price (~$0.4 per hit, misses free), the Tier 0 list-price caveat, the per-account variance and how to check it, and where the actual charge appears in the response (cost.amount_charged_usd). That is exactly the billing disclosure annotations (readOnlyHint=false, destructiveHint=false, openWorldHint=true) do not provide.
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?
Front-loads the purpose, then pricing, then the volume guidance — a sensible order with no filler. The pricing paragraph is slightly long (list price, account rate, response field all in one breath) but each clause carries real decision value.
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 an output schema and annotations, the description covers scope, cost, and volume routing well. The remaining gap is input-side: with zero required parameters, an agent gets no hint here about which identifier combination is valid, relying entirely on schema text.
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 description coverage is 100%, so the schema already explains every parameter including lead_id being "the cheapest and most accurate identifier." The description adds nothing about the name+domain vs name+company modes or the fact that all seven parameters are optional and must be combined, so baseline 3 applies.
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?
Opens with a specific verb and resource scoped to a single person: "Find a phone number for one person." It also implicitly separates itself from the sibling contact tool by referencing "an email lookup" and from list workflows by naming start_bulk_job, so an agent can place it without opening the schema.
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?
Gives an explicit selection rule: it suits already-qualified people "rather than a whole list," and routes list work to start_bulk_job. It also offers get_balance as the alternative for account-specific pricing, covering both the when-to-use and the where-to-look-next questions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_emailFind a verified work emailAInspect
Find and verify a work email. Billable: about $0.02 per VALID email found (a miss is free) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. Identifies the person by lead_id (most accurate), LinkedIn URL or first name, last name and domain. candidates resolves several people in one call; more than 10 go to an async bulk job instead, which returns a job_id for get_bulk_job.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | Company domain without protocol, e.g. "stripe.com" (name+domain mode). | |
| lead_id | No | Generect lead id from search / preview / enrich results — the cheapest and most accurate identifier. | |
| last_name | No | Last name (name+domain mode). | |
| candidates | No | Batch mode. Each entry uses the same identifier rules as the single-person form. | |
| first_name | No | First name (name+domain mode). | |
| timeout_ms | No | Request timeout in milliseconds. | |
| middle_name | No | Middle name (optional, improves pattern matching). | |
| linkedin_url | No | LinkedIn profile URL. |
Output Schema
| Name | Required | Description |
|---|---|---|
| job | No | |
| cost | No | |
| mode | No | |
| dropped | No | |
| results | No | |
| next_step | No | |
| requested | No | |
| submitted | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint=false, openWorldHint=true) by disclosing the cost model: ~$0.02 per valid email, free on a miss, tier list price, per-account variance, and the exact response field cost.amount_charged_usd for actual spend. This is precisely the billing/consumption context an agent needs before calling a metered, non-read-only tool.
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?
Front-loads the purpose in a five-word sentence, then layers billing, identification, and batch routing in a tight block with no filler. Slightly dense — the billing and routing clauses are packed into one paragraph — but every sentence carries information.
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?
An output schema exists, so return values needn't be explained, and the description still calls out cost.amount_charged_usd for the one field agents care about. Billing, identifier modes, and bulk escalation are all covered; the only gap is that with 0 required parameters it never states that at least one identifier must be supplied.
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 description coverage is 100%, so the baseline is 3; the description adds genuine selection guidance by declaring lead_id "most accurate" and spelling out the three identification forms (lead_id, LinkedIn URL, name+domain). It does not document timeout_ms or explain why zero parameters are marked required, but it meaningfully enhances the already-documented 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?
States a specific verb and resource: "Find and verify a work email," which is immediately actionable. It does not explicitly distinguish itself from the closest sibling validate_email (which checks an email you already have), so an agent must infer that boundary from names alone. Clear but not sibling-differentiated.
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?
Explicitly ranks identifier modes ("lead_id (most accurate)"), explains that `candidates` handles several people in one call, and routes requests over 10 to an async bulk job that "returns a job_id for get_bulk_job." It also names get_balance for account-specific pricing, leaving nothing ambiguous about which tool to invoke next.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_balanceBalance, usage and your prices (free)ARead-onlyIdempotentInspect
Account balance, month-to-date usage and this account's own per-operation prices. Free: this call never spends credits. balance_usd is the wallet; grants_usd is bonus and plan credit (sign-up bonus, perks, plan allowance), reported apart. Grants are spent first, but only on the operations each one covers: a promo perk or a plan allowance may not pay for API calls, and a perk never pays for phone numbers, so the two figures do not add up to what the account can spend. Useful before a batch of paid work (what the user can afford) and after it (what was spent). These are the account's real rates; prices in tool descriptions are list prices.
| Name | Required | Description | Default |
|---|---|---|---|
| timeout_ms | No | Request timeout in milliseconds. | |
| include_usage | No | Also return the month-to-date credit usage broken down by operation type. Free. | |
| include_prices | No | Include this account's per-operation prices. Default true. | |
| include_transactions | No | Also return the N most recent transactions (each shows the operation type and dollar amount). | |
| include_token_analytics | No | Also return per-API-token request counts for the last 30 days (by endpoint and status). Free. Useful for answering "which integration is making these calls?". |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| No | ||
| usage | No | |
| test_mode | No | |
| grants_usd | No | |
| balance_usd | No | |
| preview_tier | No | |
| prices_source | No | |
| token_analytics | No | |
| your_prices_usd | No | |
| test_mode_notice | No | |
| recent_transactions | No | |
| used_this_month_usd | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations it discloses cost behavior ('this call never spends credits') and, critically, the spending-order and coverage rules for grants — grants are consumed first, only on covered operation types, and never pay for phone numbers, so balance_usd + grants_usd overstates spendable funds. It also flags that returned prices are the account's real rates versus the list prices shown in other tool descriptions.
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?
Front-loaded with purpose and the free-cost caveat, then the non-obvious grant semantics. Every sentence carries information an agent would otherwise get wrong, though the grant explanation runs long and is denser than needed for a routine balance check.
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?
An output schema exists, so return-shape detail is not required, and the description still explains the two headline fields and why they cannot simply be summed. Combined with zero required params and 100% schema coverage, an agent has everything needed to invoke and interpret this 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 description coverage is 100%, so each of the five flags (include_usage, include_prices, include_transactions, include_token_analytics, timeout_ms) is already documented with its own meaning and default. The description conveys that usage and prices are part of the result but never maps that to the optional flags, so it adds little over 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 opening clause names the exact resource and the three things returned (wallet balance, month-to-date usage, account-specific per-operation prices), plus the cost property ('Free: this call never spends credits'). No sibling in the list covers account/billing state, so it is unambiguous against count_leads, health, etc.
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?
It gives concrete usage contexts: 'before a batch of paid work (what the user can afford) and after it (what was spent)'. That is a clear when-to-use signal. It stops short of naming alternatives or stating when not to call (e.g. whether include_usage makes a separate usage tool unnecessary), so it is not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_bulk_jobPoll a bulk job (free)ARead-onlyIdempotentInspect
Status and results of a bulk job. Free: this call never spends credits. Polling is free (the work was billed at submit time); a few seconds between polls is enough.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | job_id returned by start_bulk_job. | |
| job_type | Yes | Same job_type used at submit. | |
| timeout_ms | No | Request timeout in milliseconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| job | No | |
| cost | No | |
| job_id | No | |
| results | No | |
| job_type | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent, and the description adds genuinely new behavioral context: the call never spends credits and the billable work happened at submit time, so an agent knows repeated polling is safe and cost-free. It does not describe the possible job states (pending/failed/completed) or what happens on an unknown job_id, leaving some behavioral gaps.
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?
Two short sentences, front-loaded with what is returned followed by the cost/polling note. Slight redundancy between 'never spends credits' and 'Polling is free', but nothing is wasted overall.
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?
An output schema exists, so return values need no explanation, and the cost/polling guidance covers the main operational concern. The main missing piece is how to interpret status values and when to stop polling, which is a moderate rather than critical gap.
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 description coverage is 100%, so job_id, job_type and timeout_ms are already documented with their enum values and origin at submit. The description adds no parameter-level meaning, so baseline 3 applies.
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 first sentence names the resource (a bulk job) and what it returns (status and results), which separates it from start_bulk_job by referring to work 'billed at submit time'. It stops short of explicitly naming start_bulk_job as the counterpart, so differentiation is implied rather than stated.
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 gives an actionable polling cadence ('a few seconds between polls is enough') and states the call is free, which implies 'use this to poll after submitting'. However it never states when not to use it, how to know when to stop polling, or names start_bulk_job as the required predecessor.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_lead_by_urlEnrich a lead by LinkedIn URL (alias)AInspect
Alias of enrich_lead for a LinkedIn profile URL, kept for backwards compatibility. Billable: about $0.02 per record found (not-found is refunded) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. enrich_lead does the same and also accepts a Generect id (the most accurate identifier) or an email for reverse lookup.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | LinkedIn profile URL (e.g. https://www.linkedin.com/in/username/). | |
| mode | No | Data mode. "database" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. "realtime" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. "auto" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick "database" explicitly when a recent cached record is good enough and cost matters more than freshness. | |
| posts | No | DEPRECATED — accepted but ignored. Removed: v1 enrich returns the full profile without per-section toggles. | |
| compact | No | Default true: return a small per-lead summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields. | |
| comments | No | DEPRECATED — accepted but ignored. Removed: v1 enrich returns the full profile without per-section toggles. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| inexact_company | No | DEPRECATED — accepted but ignored. Removed: v1 enrich matches on the identifier you pass. | |
| people_also_viewed | No | DEPRECATED — accepted but ignored. Removed: v1 enrich returns the full profile without per-section toggles. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| lead | No | |
| mode | No | |
| found | No | |
| company | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses billing behavior: roughly $0.02 per found record, refunds for not-found results, tiered account-specific pricing, and the exact response field cost.amount_charged_usd that reports actual spend. It also points to get_balance for account pricing. Those details materially help an agent understand cost implications before invocation.
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 front-loaded with the alias identity and then adds pricing and sibling comparison. Every sentence is relevant, though the pricing and cost-reporting detail is somewhat dense and could be trimmed slightly without losing key information.
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 rich input schema, 100% parameter coverage, annotations, and the existence of an output schema, the description supplies the additional context an agent needs: alias status, backward-compatibility purpose, billing implications, and the main alternative. Return value details are appropriately omitted because the output schema covers them.
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 description coverage is 100%, so parameter documentation is already complete. The description reinforces the URL input and notes that enrich_lead additionally accepts id/email, but it adds no meaningful detail about mode, compact, timeout_ms, or the deprecated ignored parameters. Baseline 3 is appropriate.
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 immediately states that this is an alias of enrich_lead scoped to a LinkedIn profile URL. It explicitly distinguishes the tool from enrich_lead, which accepts a Generect id or email, so an agent can identify both the verb and the narrower resource scope without opening the schema.
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?
It explains that the tool is kept for backwards compatibility and that enrich_lead does the same plus accepts id/email, which gives clear context for when enrich_lead is the better sibling. It stops short of an explicit 'use enrich_lead for new integrations' exclusion, so the guidance is strong but not fully prescriptive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
healthServer and credential health (free)ARead-onlyIdempotentInspect
Liveness check. Free: this call never spends credits. Confirms the MCP server is up, reports its version and (unless disabled) verifies the credential against a free account endpoint. It never touches a paid data endpoint, so it is safe for monitors.
| Name | Required | Description | Default |
|---|---|---|---|
| timeout_ms | No | Request timeout in milliseconds. | |
| check_credential | No | Also verify the API token against the free /accounts/me endpoint. Default true. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ms | No | |
| ok | No | |
| cost | No | |
| server | No | |
| account | No | |
| version | No | |
| api_base | No | |
| test_mode | No | |
| balance_usd | No | |
| has_credential | No | |
| credential_error | No | |
| credential_valid | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly/idempotent/openWorld; the description adds the trait that actually matters for an agent's routing decision — zero credit cost and no paid-endpoint contact — plus the default-on credential check against a free endpoint. That is substantive, non-redundant 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?
Short, front-loaded, with the cost guarantee stated immediately after the one-word purpose. Slight redundancy between 'never spends credits' and 'never touches a paid data endpoint', though the latter also introduces the monitor-safety use case.
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 trivial to call (0 required params), annotations cover the safety profile, and an output schema exists to describe what is reported. The description covers the one thing structured fields cannot express — that calling it is free — so nothing an agent needs is missing.
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 both parameters are already fully documented, including the 'Default true' note that 'unless disabled' merely restates. The description adds no format, unit, or edge-case meaning beyond the schema (timeout_ms is never mentioned), so baseline 3 applies.
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 a specific verb and resource ('Liveness check... confirms the MCP server is up, reports its version') plus a secondary behavior (credential verification). This is unmistakably distinct from every sibling, all of which are paid data/enrichment 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?
'Free: this call never spends credits' and 'safe for monitors' give a clear condition for calling it. It stops short of explicitly routing the agent away from siblings (e.g., 'use get_balance for remaining credits, not this'), so it lacks an explicit alternatives clause.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_webhooksList webhooks (free)ARead-onlyIdempotentInspect
List the webhook endpoints registered for bulk-job completion events. Free: this call never spends credits.
| Name | Required | Description | Default |
|---|---|---|---|
| timeout_ms | No | Request timeout in milliseconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| action | No | |
| webhooks | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent, so the description's value-add is the credential-cost disclosure ('never spends credits') and the scope limitation that only bulk-job completion endpoints are returned. It does not address the openWorldHint implication (results can change externally), which keeps it below a 5.
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?
Two short sentences; the scope constraint comes first and the free-call reassurance second. No repetition of the title and 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?
With an output schema present, return values need not be described, and the annotations carry the safety profile. What remains slightly uncovered is pagination/result-size behavior for a potentially open-world list, but otherwise the definition is sufficient to call the tool 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?
There is a single optional parameter (timeout_ms) at 100% schema description coverage, so the schema fully documents it. The description adds nothing about timeout behavior, and per the baseline rule this is a 3.
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?
Names a specific verb and resource (list / webhook endpoints) and narrows the scope to endpoints registered for bulk-job completion events, which is a meaningful qualifier. The verb alone already separates it from create_webhook, delete_webhook, update_webhook and test_webhook, so no explicit sibling routing is needed.
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?
Usage is implied: call this to see which webhooks are registered. The 'Free: this call never spends credits' note is a useful cost signal that lowers the bar for calling it, but there is no explicit when-not or pointer to alternatives (e.g. use test_webhook to verify delivery).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preview_leadsPreview leads (cheapest paid look)AInspect
A cheap look at the actual people behind a count, before a full search. Billable: about $0.002 per returned row at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. Preview rows carry a Generect id, so the usual flow is: preview many, pick the few that fit, then enrich_lead or generate_email only on those. By the API contract preview rows are masked (no LinkedIn URL, domain, email or phone); an account that gets more than that cannot rely on it.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Alias for limit_by. | |
| strict | No | Fields to match strictly, e.g. ["company_locations"]. | |
| compact | No | Default true: return a small per-lead summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields. | |
| keywords | No | Free-text keywords across headline/summary/skills — realtime only: using it forces the pricier live mode. | |
| limit_by | No | Rows to return this call (1–100, default 25). You are billed per returned row, so this number IS the price of the call. | |
| personas | No | Advanced raw persona tuples [name, functions, seniorities, prohibits, priority?] — realtime only: using it forces the pricier live mode. | |
| functions | No | Job functions, e.g. ["Sales","Marketing","Engineering"] — realtime only: using it forces the pricier live mode. | |
| job_title | No | DEPRECATED alias for job_titles. Still honoured: it is merged into job_titles. | |
| locations | No | Where the lead lives — matches cities, states and countries, e.g. ["United States","Berlin"]. | |
| offset_by | No | Rows to skip (pagination). | |
| company_id | No | Anchor to one company by LinkedIn numeric id. | |
| count_only | No | Return just how many leads the preview index holds for these filters and spend nothing. Free. This is a second opinion on count_leads: preview and cached search are different indexes and can disagree. | |
| job_titles | No | Target job titles, OR-matched (e.g. ["CEO","Founder","Owner"]). A lead needs to match only one. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| exclude_ids | No | Skip leads by Generect/Sales-Navigator id. Pass the ids you already received to paginate without duplicates — ordering is not stable, so this is more reliable than offset. | |
| seniorities | No | Seniority at the current employer, e.g. ["Owner","CXO","VP","Director","Manager"]. Current position only. | |
| changed_jobs | No | Only leads who recently changed jobs — realtime only: using it forces the pricier live mode. | |
| company_link | No | Anchor to one company by LinkedIn URL. | |
| company_name | No | Anchor to one company by name (exclusive with company_link/company_id). | |
| company_types | No | Employer types: "Public Company","Privately Held","Non Profit","Government Agency","Educational","Self Employed","Self Owned","Partnership". | |
| exclude_names | No | Skip leads by full name. Works in both modes (the database-mode bug that returned 0 rows was fixed in the API on 2026-08-13, PRO-1333). exclude_ids is still the more reliable way to paginate. | |
| get_max_leads | No | DEPRECATED — accepted but ignored. Always on now: search responses include results_count without asking. | |
| company_filters | No | Optional company-level filters for a two-level ICP. | |
| lead_industries | No | DEPRECATED — accepted but ignored. Removed: v1 filters on the employer's industry. Use company_industries. | |
| without_company | No | DEPRECATED — accepted but ignored. No longer needed — v1 filter-only search is the default when no company anchor is set. | |
| years_in_company | No | Time at current company, same buckets as years_in_position — realtime only: using it forces the pricier live mode. | |
| company_locations | No | HQ location of the lead's current employer. | |
| confirm_spend_usd | No | Explicit approval for an unusually large charge. Calls whose worst case exceeds $5 are refused unless this is set to at least the amount the tool reports. Only set it after the user has agreed to that number. | |
| exclude_locations | No | Lead locations to exclude. | |
| filter_empty_vars | No | Drop leads where these fields are empty, e.g. ["profile_photo","job_started_on"]. Useful to raise data quality before paying. | |
| years_in_position | No | Time in current role: 1=<1y, 2=1-2y, 3=3-5y, 4=6-10y, 5=10y+ — realtime only: using it forces the pricier live mode. | |
| company_headcounts | No | Employer size buckets. Allowed ONLY: "1-10","11-50","51-200","201-500","501-1000","1001-5000","5001-10000","10 000+" (note the space in "10 000+"). | |
| company_industries | No | Industry of the current employer. Must match Generect industry names exactly (e.g. "Software Development", "Financial Services"); names are hierarchical and unknown names are rejected with HTTP 400 naming the field. | |
| past_company_names | No | Companies the lead previously worked at (alumni targeting) — realtime only: using it forces the pricier live mode. | |
| posted_on_linkedin | No | Only leads who recently posted on LinkedIn — realtime only: using it forces the pricier live mode. | |
| linkedin_filter_link | No | A LinkedIn / Sales Navigator search URL to lift filters from — realtime only: using it forces the pricier live mode. | |
| allow_unlisted_values | No | Escape hatch. This server checks industry / seniority / headcount / company-type values against the LinkedIn vocabularies before sending, because the API silently returns 0 results for an unknown industry or seniority instead of rejecting it. Set true only when you are sure a value is valid and this server is out of date. | |
| exclude_title_keywords | No | DEPRECATED — accepted but ignored. No v1 equivalent. Narrow job_titles instead, or filter the returned rows yourself. | |
| exclude_company_locations | No | Employer HQ locations to exclude. | |
| exclude_company_headcounts | No | Employer size buckets to exclude. | |
| exclude_company_industries | No | Employer industries to exclude. |
Output Schema
| Name | Required | Description |
|---|---|---|
| fix | No | |
| cost | No | |
| mode | No | |
| note | No | |
| leads | No | |
| detail | No | |
| status | No | |
| returned | No | |
| companies | No | |
| free_tier | No | |
| test_mode | No | |
| thin_note | No | |
| spend_guard | No | |
| results_count | No | |
| next_page_args | No | |
| requested_rows | No | |
| escalation_note | No | |
| test_mode_notice | No | |
| thin_unavailable | No | |
| vocabulary_warnings | No | |
| blocked_by_vocabulary | No | |
| deprecated_params_ignored | No | |
| escalated_to_realtime_because | No | |
| api_returned_more_than_requested | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context the annotations do not carry: per-row pricing (~$0.002), that per-account rates differ and where to verify them (get_balance) and confirm actual spend (cost.amount_charged_usd), and the contract-level masking of LinkedIn URL, domain, email and phone. This is exactly the billing and output-fidelity information an agent needs before spending money on a non-readOnly tool.
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?
Five sentences, all load-bearing: purpose, price, account-specific price, workflow, and output masking, in roughly decreasing order of importance. The closing sentence ('an account that gets more than that cannot rely on it') is awkwardly and ambiguously phrased and could be stated plainly.
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 41-parameter, billable tool with an output schema and full schema coverage, the description supplies the missing conceptual layer: cost model, spend confirmation path, masking, and the intended multi-step workflow. It leaves the relationship to search_leads and pagination strategy to the schema, which is defensible but a small gap.
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 description coverage is 100% and the parameter descriptions themselves are unusually rich (pricing per limit_by row, realtime-mode triggers, deprecated flags). The description adds no parameter-level meaning beyond what the schema already states, so the baseline 3 applies.
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 frames the tool precisely as a cheap sample of the people behind a count, before a full search, and names the downstream steps (enrich_lead, generate_email). It distinguishes itself from a full search conceptually, but never names search_leads or count_leads directly, leaving the agent to infer which sibling is the 'full search'.
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?
Gives an explicit workflow (preview many, pick the few that fit, then enrich only those) plus the free count_only escape hatch and the caveat that rows are masked so richer accounts cannot be assumed. It stops short of stating the negative case by name, e.g. 'use search_leads when you need unmasked LinkedIn URLs or emails'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_profileResolve an anonymous LinkedIn linkAInspect
Reveal who is behind an anonymous LinkedIn profile link. Billable: about $0.0005 per resolved profile (an unresolvable reference is free; duplicates in one batch are billed per row) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. Takes the obfuscated links that Sales Navigator leaves in exports, CRMs and ad platforms (linkedin.com/in/ACwAA…), plus Sales Navigator lead URLs, bare profile ids and urns, and returns the real profile URL and identity. profiles (up to 50) resolves a batch in one call. The id it returns is the identifier enrich_lead, generate_email and find_phone accept, so this is the cheap first step before a full record. Returns identity only (no location, company or work history; enrich_lead has those). The numeric member id is not accepted as input (LinkedIn answers 403 to it); it comes back as linkedin_id.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Alias for `url` — same accepted values. Use whichever reads better. | |
| url | No | A single LinkedIn person reference: profile URL of any flavour (including /in/ACwAA… and /sales/lead/…), a public identifier, an obfuscated id (ACwAA… or ACoAA…) or an urn. Matched case-insensitively. | |
| compact | No | Default true: return a small per-profile summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields. | |
| profiles | No | Batch mode: 1–50 references, mixed freely. One row per input, in input order, each either a resolved profile or {input, error}. Duplicates are billed per row — deduplicate first. | |
| timeout_ms | No | Request timeout in milliseconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| found | No | |
| profile | No | |
| profiles | No | |
| resolved | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only give the generic readOnly/openWorld/destructive triad, while the description discloses the traits that actually matter here: billability at ~$0.0005/resolved profile, free unresolvable references, per-row billing for duplicates, per-account pricing via get_balance, and where the actual charge appears (cost.amount_charged_usd). That is exactly the context annotations cannot carry.
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?
Front-loaded with purpose, then cost, then inputs, then downstream use — a sensible order with no filler. It is dense and slightly long, with parenthetical billing caveats that take a second read, but every sentence carries information an agent needs.
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 billable resolution tool with an output schema and full param documentation, the description covers inputs, cost model, batch semantics, output identity scope, and the handoff to sibling tools. An agent can decide whether to call it and how to chain it without further discovery.
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 baseline is 3, but the description adds real meaning beyond the schema: it enumerates the accepted input flavours (obfuscated ACwAA links, Sales Nav lead URLs, bare ids, urns), notes the 50-item batch cap, and — crucially — states that the numeric member id is rejected with a 403, a constraint absent from 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 first sentence names a specific verb and resource ('reveal who is behind an anonymous LinkedIn profile link') and the rest scopes it precisely: identity only, no location/company/history. It is clearly distinguishable from enrich_lead, which the description explicitly names as the tool for the deeper fields.
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?
It states when to use it ('the cheap first step before a full record'), names the alternatives and their differing scope (enrich_lead has location/company/work history), and describes the downstream chain (the returned `id` is accepted by enrich_lead, generate_email, find_phone). It also states a when-not: the numeric member id is not accepted as input.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_companiesSearch companies (free thin rows, full rows billed)AInspect
Return companies matching an ICP. Free by default while the account has free thin rows left today (a daily quota; detail "thin" guarantees $0). Thin rows carry no domain; enrich_company adds it for the ones you keep. detail "full" is billable: about $0.02 per returned row (0 rows costs $0) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. Realtime is billed per row too. count_companies sizes the result for free first. headcount_range is a snapshot taken when the record was indexed and can lag the company's current size; the filter itself is applied at query time.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Data mode. "database" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. "realtime" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. "auto" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick "database" explicitly when freshness is not critical and cost matters more than freshness. | |
| limit | No | Alias for limit_by. | |
| detail | No | Row detail for the database search. Thin rows are FREE — id, name, industry, headcount_range, HQ country/city, company_type, founded_year; no LinkedIn URL, domain, contacts or history — up to a daily per-account row quota that resets at 00:00 UTC. Omitted (default): thin while the free tier is available; once it is not (quota spent, a custom-contract account, a server without the tier) the search continues as before — full rows billed per row, marked thin_unavailable in the result, under the spend ceiling. "thin": free rows only — never billed, never escalated to realtime; a spent quota is a 429 and a realtime-only filter is an error. "full": the whole record, billed per row. Browse thin, then spend only on the rows you keep: generate_email takes the lead id directly, enrich_* gives the full record. | |
| offset | No | Alias for offset_by. | |
| compact | No | Default true: return a small per-company summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields. | |
| keywords | No | Free-text keywords across name/description/specialties — realtime only: using it forces the pricier live mode. | |
| limit_by | No | Rows to return this call (1–100, default 25). You are billed per returned row, so this number IS the price of the call. | |
| locations | No | HQ locations — cities, states or countries. | |
| offset_by | No | Rows to skip (pagination). | |
| headcounts | No | Size buckets. Allowed ONLY: "1-10","11-50","51-200","201-500","501-1000","1001-5000","5001-10000","10 000+". | |
| industries | No | Company industries. Must match Generect industry names exactly (e.g. "Software Development"); unknown names are rejected with HTTP 400. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| exclude_ids | No | Exclude companies by LinkedIn id/URN. | |
| technologies | No | Technologies the company uses — realtime only: using it forces the pricier live mode. | |
| company_names | No | Restrict to specific company names — realtime only: using it forces the pricier live mode. | |
| company_types | No | Company types: "Public Company","Privately Held","Non Profit","Government Agency","Educational", … | |
| revenues_range | No | Annual revenue range, single object {min,max} — realtime only: using it forces the pricier live mode. | |
| sub_industries | No | Expand each selected industry to its sub-industries as well (broadens the match). | |
| exclude_domains | No | Exclude companies by domain (e.g. existing customers). | |
| linkedins_links | No | Specific LinkedIn company URLs — realtime only: using it forces the pricier live mode. | |
| headcount_growth | No | Headcount growth in percent — realtime only: using it forces the pricier live mode. | |
| num_of_followers | No | LinkedIn follower buckets: "1-50","51-100","101-1000","1001-5000","5001+" — realtime only: using it forces the pricier live mode. | |
| confirm_spend_usd | No | Explicit approval for an unusually large charge. Calls whose worst case exceeds $5 are refused unless this is set to at least the amount the tool reports. Only set it after the user has agreed to that number. | |
| exclude_locations | No | HQ locations to exclude. | |
| get_max_companies | No | DEPRECATED — accepted but ignored. Always on now: search responses include results_count without asking. | |
| exclude_industries | No | Industries to exclude. | |
| hiring_on_linkedin | No | Only companies actively hiring — realtime only: using it forces the pricier live mode. | |
| fallback_from_leads | No | DEPRECATED — accepted but ignored. Removed. It fabricated lead-derived name aggregates and cost an extra billable query. | |
| department_headcount | No | Department size, e.g. {"name":"engineering","min":10,"max":100} — realtime only: using it forces the pricier live mode. | |
| allow_unlisted_values | No | Escape hatch for the local vocabulary check — see the lead-side field of the same name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| fix | No | |
| cost | No | |
| mode | No | |
| note | No | |
| leads | No | |
| detail | No | |
| status | No | |
| returned | No | |
| companies | No | |
| free_tier | No | |
| test_mode | No | |
| thin_note | No | |
| spend_guard | No | |
| results_count | No | |
| next_page_args | No | |
| requested_rows | No | |
| escalation_note | No | |
| test_mode_notice | No | |
| thin_unavailable | No | |
| vocabulary_warnings | No | |
| blocked_by_vocabulary | No | |
| deprecated_params_ignored | No | |
| escalated_to_realtime_because | No | |
| api_returned_more_than_requested | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the daily free-row quota and its 00:00 UTC reset, exact full-row price (~$0.02), the $0-for-zero-rows rule, where the actual charge is reported (cost.amount_charged_usd), what thin rows omit (no domain), and that headcount_range is an indexing-time snapshot that can lag. This is precisely the billing and data-quality context an agent needs before spending.
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?
Five sentences, cost model front-loaded and no filler. Dense but each sentence carries pricing, quota or data-quality information; the headcount-range caveat at the end is slightly buried for an operational warning.
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?
Output schema exists, so return values needn't be explained, and the description fully covers the cost/quota/detail dimensions that matter most for a 30-parameter billable search. The mode/auto-escalation and spend-ceiling behavior are left entirely to the schema, which is acceptable but means the description alone wouldn't tell an agent how mode selection interacts with the billing story.
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% and the detail enum already documents thin vs full at length, so the description largely restates it. It does add two things not in the schema: thin rows lack domains and enrich_company fills them, and headcount_range is applied at query time despite being an indexed snapshot — but this is marginal against an already-exhaustive 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?
States a specific verb+resource ("Return companies matching an ICP") and immediately frames the cost/detail model that distinguishes it. Sibling differentiation is partial — count_companies is named as the free sizing step, but search_leads/enrich_company are only referenced in passing rather than contrasted.
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?
Gives actionable routing: "count_companies sizes the result for free first" and "Browse thin, then spend only on the rows you keep," which names the cheaper alternative and the pay-only-for-what-you-keep pattern. No explicit when-not-to-use clause, and the database-vs-realtime choice lives in the schema rather than the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_leadsSearch leads (free thin rows, full rows billed)AInspect
Return leads (people) matching an ICP. Free by default while the account has free thin rows left today (a daily quota; detail "thin" guarantees $0). detail "full" is billable: about $0.02 per returned row (0 rows costs $0) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. Realtime, and an automatic escalation to it, are billed per row too. count_leads sizes the audience for free first. Rows never include email or phone; generate_email (which takes the lead id) and find_phone add those for the ids you keep. Ordering is not stable, so pages are fetched by passing the ids you already have in exclude_ids rather than by offset.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Data mode. "database" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. "realtime" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. "auto" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick "database" explicitly when freshness is not critical and cost matters more than freshness. | |
| limit | No | Alias for limit_by. | |
| detail | No | Row detail for the database search. Thin rows are FREE — id, name, job_title, seniority, location, company name/id/industry/country; no LinkedIn URL, domain, contacts or history — up to a daily per-account row quota that resets at 00:00 UTC. Omitted (default): thin while the free tier is available; once it is not (quota spent, a custom-contract account, a server without the tier) the search continues as before — full rows billed per row, marked thin_unavailable in the result, under the spend ceiling. "thin": free rows only — never billed, never escalated to realtime; a spent quota is a 429 and a realtime-only filter is an error. "full": the whole record, billed per row. Browse thin, then spend only on the rows you keep: generate_email takes the lead id directly, enrich_* gives the full record. | |
| offset | No | Alias for offset_by. | |
| strict | No | Fields to match strictly, e.g. ["company_locations"]. | |
| compact | No | Default true: return a small per-lead summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields. | |
| keywords | No | Free-text keywords across headline/summary/skills — realtime only: using it forces the pricier live mode. | |
| limit_by | No | Rows to return this call (1–100, default 25). You are billed per returned row, so this number IS the price of the call. | |
| personas | No | Advanced raw persona tuples [name, functions, seniorities, prohibits, priority?] — realtime only: using it forces the pricier live mode. | |
| functions | No | Job functions, e.g. ["Sales","Marketing","Engineering"] — realtime only: using it forces the pricier live mode. | |
| job_title | No | DEPRECATED alias for job_titles. Still honoured: it is merged into job_titles. | |
| locations | No | Where the lead lives — matches cities, states and countries, e.g. ["United States","Berlin"]. | |
| offset_by | No | Rows to skip (pagination). | |
| company_id | No | Anchor to one company by LinkedIn numeric id. | |
| job_titles | No | Target job titles, OR-matched (e.g. ["CEO","Founder","Owner"]). A lead needs to match only one. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| exclude_ids | No | Skip leads by Generect/Sales-Navigator id. Pass the ids you already received to paginate without duplicates — ordering is not stable, so this is more reliable than offset. | |
| seniorities | No | Seniority at the current employer, e.g. ["Owner","CXO","VP","Director","Manager"]. Current position only. | |
| changed_jobs | No | Only leads who recently changed jobs — realtime only: using it forces the pricier live mode. | |
| company_link | No | Anchor to one company by LinkedIn URL. | |
| company_name | No | Anchor to one company by name (exclusive with company_link/company_id). | |
| company_types | No | Employer types: "Public Company","Privately Held","Non Profit","Government Agency","Educational","Self Employed","Self Owned","Partnership". | |
| exclude_names | No | Skip leads by full name. Works in both modes (the database-mode bug that returned 0 rows was fixed in the API on 2026-08-13, PRO-1333). exclude_ids is still the more reliable way to paginate. | |
| get_max_leads | No | DEPRECATED — accepted but ignored. Always on now: search responses include results_count without asking. | |
| company_filters | No | Optional: only return leads at companies matching these filters (two-level ICP). | |
| lead_industries | No | DEPRECATED — accepted but ignored. Removed: v1 filters on the employer's industry. Use company_industries. | |
| without_company | No | DEPRECATED — accepted but ignored. No longer needed — v1 filter-only search is the default when no company anchor is set. | |
| years_in_company | No | Time at current company, same buckets as years_in_position — realtime only: using it forces the pricier live mode. | |
| company_locations | No | HQ location of the lead's current employer. | |
| confirm_spend_usd | No | Explicit approval for an unusually large charge. Calls whose worst case exceeds $5 are refused unless this is set to at least the amount the tool reports. Only set it after the user has agreed to that number. | |
| exclude_locations | No | Lead locations to exclude. | |
| filter_empty_vars | No | Drop leads where these fields are empty, e.g. ["profile_photo","job_started_on"]. Useful to raise data quality before paying. | |
| years_in_position | No | Time in current role: 1=<1y, 2=1-2y, 3=3-5y, 4=6-10y, 5=10y+ — realtime only: using it forces the pricier live mode. | |
| company_headcounts | No | Employer size buckets. Allowed ONLY: "1-10","11-50","51-200","201-500","501-1000","1001-5000","5001-10000","10 000+" (note the space in "10 000+"). | |
| company_industries | No | Industry of the current employer. Must match Generect industry names exactly (e.g. "Software Development", "Financial Services"); names are hierarchical and unknown names are rejected with HTTP 400 naming the field. | |
| past_company_names | No | Companies the lead previously worked at (alumni targeting) — realtime only: using it forces the pricier live mode. | |
| posted_on_linkedin | No | Only leads who recently posted on LinkedIn — realtime only: using it forces the pricier live mode. | |
| linkedin_filter_link | No | A LinkedIn / Sales Navigator search URL to lift filters from — realtime only: using it forces the pricier live mode. | |
| allow_unlisted_values | No | Escape hatch. This server checks industry / seniority / headcount / company-type values against the LinkedIn vocabularies before sending, because the API silently returns 0 results for an unknown industry or seniority instead of rejecting it. Set true only when you are sure a value is valid and this server is out of date. | |
| exclude_title_keywords | No | DEPRECATED — accepted but ignored. No v1 equivalent. Narrow job_titles instead, or filter the returned rows yourself. | |
| exclude_company_locations | No | Employer HQ locations to exclude. | |
| exclude_company_headcounts | No | Employer size buckets to exclude. | |
| exclude_company_industries | No | Employer industries to exclude. |
Output Schema
| Name | Required | Description |
|---|---|---|
| fix | No | |
| cost | No | |
| mode | No | |
| note | No | |
| leads | No | |
| detail | No | |
| status | No | |
| returned | No | |
| companies | No | |
| free_tier | No | |
| test_mode | No | |
| thin_note | No | |
| spend_guard | No | |
| results_count | No | |
| next_page_args | No | |
| requested_rows | No | |
| escalation_note | No | |
| test_mode_notice | No | |
| thin_unavailable | No | |
| vocabulary_warnings | No | |
| blocked_by_vocabulary | No | |
| deprecated_params_ignored | No | |
| escalated_to_realtime_because | No | |
| api_returned_more_than_requested | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnly false, openWorld true, destructive false) by disclosing pricing (~$0.02/row, 0 rows costs $0), the daily free thin-row quota with 00:00 UTC reset, a 429 on a spent thin quota, the per-call spend ceiling and confirm_spend refusal threshold, realtime escalation cost, and that every response reports cost.amount_charged_usd. It also warns that ordering is unstable — behavior no annotation could convey.
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?
Front-loaded on what is returned and what it costs, then guidance, then the data caveat — a sensible priority order. Slightly dense in the middle (realtime/escalation billing sentence is compressed and needs a second read), but no sentence is 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 43-parameter search tool with an output schema and full annotation coverage, the description covers the things the schema cannot: cost model, free-tier quota behavior, escalation, contact-field gaps and pagination strategy. Nothing needed to call it safely or correctly is missing.
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 description coverage is 100%, so the schema carries mode/detail/limit_by semantics and the baseline is 3. The description still adds rate context the schema lacks — Tier 0 list price vs the account's actual rate via get_balance — plus the pagination rationale behind exclude_ids and the missing-email/phone constraint on returned rows.
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 a specific verb and resource — 'Return leads (people) matching an ICP' — and the title immediately frames the free-vs-billed distinction that separates it from count_leads, enrich_lead and search_companies. An agent can tell what it produces (lead rows, no email/phone) without opening the schema.
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?
Explicitly routes the agent: 'count_leads sizes the audience for free first', 'Browse thin, then spend only on the rows you keep', generate_email/find_phone for contacts on kept ids, and exclude_ids instead of offset for paging. Both the cheap path and the alternatives are named with the condition that selects them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_bulk_jobSubmit a bulk jobAInspect
Submit up to 50 records for asynchronous processing and get a job_id back. Billable at the same per-record rate as the single-record tool, and the whole cost is reserved at submit time: a submitted job keeps running (and charging) even if nobody polls it. Meant for a list the user has approved. get_bulk_job polls it, and a webhook (create_webhook) reports when it finishes.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Enrich jobs only: cached (cheaper) or live. Default "database". | |
| items | Yes | Max 50. email_find/phone_find: {lead_id} | {linkedin_url} | {first_name,last_name,domain|company}. enrich_leads: {id} | {linkedin_url} | {email}. enrich_companies: {id} | {linkedin_url} | {domain} | {name}. | |
| job_type | Yes | What to do with the items. phone_find is by far the most expensive per record. | |
| timeout_ms | No | Request timeout in milliseconds. | |
| confirm_spend_usd | No | Explicit approval for an unusually large charge. Calls whose worst case exceeds $5 are refused unless this is set to at least the amount the tool reports. Only set it after the user has agreed to that number. |
Output Schema
| Name | Required | Description |
|---|---|---|
| job | No | |
| cost | No | |
| mode | No | |
| dropped | No | |
| job_type | No | |
| next_step | No | |
| submitted | No | |
| test_mode | No | |
| reservation_note | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| reserved_worst_case_usd | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral context beyond annotations: billing at the single-record rate, reservation of the whole cost at submit time, and continued charging even if nobody polls the job. This is exactly the kind of billing and lifecycle disclosure an agent needs for a non-destructive but billable asynchronous operation.
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 front-loaded with the core action and result, then covers cost, approval, and follow-up mechanisms in a compact sequence. Every sentence adds useful information without repetition.
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 complexity, output schema, and annotations, the description covers the essential lifecycle: asynchronous submission, job_id, billing reservation, approval expectation, polling via get_bulk_job, and webhook notification. Nothing critical for correct invocation appears to be missing.
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 description coverage is 100%, so parameter details are already well documented in the schema. The description reinforces the 50-record limit and job_id return but does not add parameter-specific meaning beyond what the schema provides.
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 states a specific verb and resource: submit up to 50 records for asynchronous processing and get a job_id back. It clearly distinguishes this bulk asynchronous tool from the single-record tool and from get_bulk_job, which polls the submitted job.
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?
It explains that the tool is meant for a list the user has approved and names get_bulk_job for polling and create_webhook for completion notification. However, it does not explicitly state when to choose this over repeatedly calling the single-record tool, beyond the 50-record batch limit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
test_webhookSend a test webhook event (free)AInspect
Send a test event to a registered webhook endpoint. Free: this call never spends credits.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Webhook id, from list_webhooks. | |
| timeout_ms | No | Request timeout in milliseconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| action | No | |
| webhooks | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=false and openWorldHint=true, so the safety profile is partly covered. The description adds genuinely useful context beyond that: the call never spends credits, which an agent cannot infer from annotations. It stops short of disclosing that a real HTTP request is delivered to the customer's endpoint or what payload is sent.
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?
Two short sentences with zero waste; the action is front-loaded and the cost caveat follows immediately. Nothing is padded or repeated from the schema.
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?
An output schema exists and both params are documented, so the description needn't explain return values. The remaining gap is what the test event actually contains and whether the endpoint's response affects the result — useful but not blocking.
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 description coverage is 100% and both parameters are documented in the schema, including the cross-reference to list_webhooks for the id. The description adds no syntax, defaults, or timeout semantics beyond that, so baseline 3 applies.
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 a specific verb and resource: 'Send a test event to a registered webhook endpoint.' An agent can distinguish it from create_webhook/update_webhook/delete_webhook, though the description never names those siblings explicitly to reinforce the distinction.
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?
Implied usage is clear — verifying a registered webhook works — but there is no explicit when-to-use rule, no prerequisites (does the webhook need to be enabled?), and no stated alternative such as re-sending a real event.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_webhookUpdate a webhook (free)ADestructiveInspect
Change the URL, events or signing secret of a registered webhook. Free: this call never spends credits. A new URL changes where completion events, and the results they carry, are delivered; a new event list changes which events are sent.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Webhook id, from list_webhooks. | |
| url | No | New URL for the events, http or https. The API refuses a host that resolves to a private or internal address. | |
| events | No | New list of events, at least one. | |
| secret | No | New shared secret for HMAC signature verification. | |
| timeout_ms | No | Request timeout in milliseconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| action | No | |
| webhooks | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and openWorldHint=true, and the description adds real value beyond them: the 'never spends credits' cost note and an explanation of the consequences of changing URL (delivery target) and events (what gets sent). It stops short of clarifying irreversibility or that a new secret invalidates existing signature verification, which matters for a destructive mutation.
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?
Front-loads the action, then the cost note, then effects. Mostly tight, though the trailing clause ('and the results they carry') and the URL/event effect sentence lean toward restating the obvious.
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 an output schema present and full schema coverage, the description needs only the behavioral layer, and it largely provides it (cost, effect of changes). It could note irreversibility or secret rotation impact, but is otherwise sufficient to call 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 five parameters, including the private-address refusal for url and the minItems:1 constraint for events. The description only restates the effects of url/events changes, adding marginal meaning beyond 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?
Clear verb (Change) + resource (webhook settings) with the three updatable fields spelled out. 'Registered webhook' implies an existing resource, loosely distinguishing it from create_webhook, but no sibling is named explicitly.
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?
Usage is implied by 'registered webhook' (you need an existing one, id from list_webhooks) and the cost note helps prioritization, but there is no explicit when/when-not guidance or routing against create_webhook/delete_webhook.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_emailValidate email deliverabilityAInspect
Check deliverability of emails you already have. Billable: about $0.005 per email submitted (every address is billed, whatever the verdict) at the Tier 0 list price. Accounts can pay a different rate: get_balance returns this account's prices, and every response reports what was actually spent in cost.amount_charged_usd. This is the one operation where every submitted address is billed: the verdict is the deliverable. An address generate_email returned as valid is already verified, so validating it again only adds cost.
| Name | Required | Description | Default |
|---|---|---|---|
| emails | Yes | Email addresses to validate. Each one is billed. | |
| timeout_ms | No | Request timeout in milliseconds. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cost | No | |
| results | No | |
| submitted | No | |
| test_mode | No | |
| test_mode_notice | No | |
| vocabulary_warnings | No | |
| deprecated_params_ignored | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses per-address billing regardless of verdict, the approximate Tier 0 price ($0.005), that account-specific rates exist and are retrievable via get_balance, and that actual spend appears in cost.amount_charged_usd. The readOnlyHint=false / openWorldHint=true annotations are consistent with a billable external lookup; 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?
Purpose is front-loaded, followed by pricing and then the re-validation caveat. The billing point is restated twice ('every address is billed' and 'every submitted address is billed'), which is slightly redundant but defensible given the cost implication.
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?
An output schema exists, so return values needn't be explained, and the description still names the cost field to look for. Billing, pricing lookup, and the duplicate-validation pitfall are all covered; an agent has everything needed to call it responsibly.
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 description coverage is 100%, including 'Each one is billed' for emails, so the schema already carries parameter meaning. The description reinforces the billing-per-address semantics but adds nothing about timeout_ms or input format. Baseline 3 is appropriate when the schema does the heavy lifting.
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 a specific verb+resource and scope: 'Check deliverability of emails you already have'. The qualifier 'you already have' distinguishes it from the sibling generate_email, which produces addresses rather than validating existing ones.
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?
Explicitly warns against re-validating addresses that generate_email already returned as valid, which is a real when-not-to-use rule. It also routes pricing questions to get_balance. It doesn't contrast with enrich_lead or enrich_company, which may also surface validation-adjacent data, so it stops short of full sibling routing.
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.
6 tool updates
v0.13.0- Added
create_webhook - Added
delete_webhook - Added
list_webhooks - Removed
manage_webhooks - Added
test_webhook - Added
update_webhook
4 tool updates
v0.12.3- Changed
preview_leads4 fields changed- added
Output schema / properties / detailAdded value: +{ + "type": "string" +} - added
Output schema / properties / free_tierAdded value: +{} - added
Output schema / properties / thin_noteAdded value: +{ + "type": "string" +} - added
Output schema / properties / thin_unavailableAdded value: +{ + "type": "string" +}
- Changed
resolve_profile2 fields changed- added
Output schema / properties / foundAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / profileAdded value: +{}
- Changed
search_companies4 fields changed- added
Output schema / properties / detailAdded value: +{ + "type": "string" +} - added
Output schema / properties / free_tierAdded value: +{} - added
Output schema / properties / thin_noteAdded value: +{ + "type": "string" +} - added
Output schema / properties / thin_unavailableAdded value: +{ + "type": "string" +}
- Changed
search_leads4 fields changed- added
Output schema / properties / detailAdded value: +{ + "type": "string" +} - added
Output schema / properties / free_tierAdded value: +{} - added
Output schema / properties / thin_noteAdded value: +{ + "type": "string" +} - added
Output schema / properties / thin_unavailableAdded value: +{ + "type": "string" +}
17 tool updates
v0.12.2- Changed
count_companies12 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / department_headcount / additionalPropertiesRemoved value: -false - removed
Input schema / properties / headcount_growth / additionalPropertiesRemoved value: -false - changed
Input schema / properties / mode / descriptionPrevious value: -"Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when you only need a size estimate and cost matters more than freshness."New value: +"Data mode. \"database\" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. \"realtime\" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. \"auto\" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick \"database\" explicitly when you only need a size estimate and cost matters more than freshness." - removed
Input schema / properties / revenues_range / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / blocked_by_vocabulary / $refRemoved value: -"#/properties/vocabulary_warnings" - added
Output schema / properties / blocked_by_vocabulary / itemsAdded value: +{} - added
Output schema / properties / blocked_by_vocabulary / typeAdded value: +"array" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
count_leads15 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / department_headcount / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / headcount_growth / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / revenues_range / additionalPropertiesRemoved value: -false - changed
Input schema / properties / exclude_names / descriptionPrevious value: -"Skip leads by full name. KNOWN ISSUE: in database mode any non-empty value collapses the result set to 0 (verified 2026-08-09); it behaves correctly in realtime mode. Prefer exclude_ids, or filter names out yourself after the search."New value: +"Skip leads by full name. Works in both modes (the database-mode bug that returned 0 rows was fixed in the API on 2026-08-13, PRO-1333). exclude_ids is still the more reliable way to paginate." - changed
Input schema / properties / mode / descriptionPrevious value: -"Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when you only need a size estimate and cost matters more than freshness."New value: +"Data mode. \"database\" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. \"realtime\" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. \"auto\" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick \"database\" explicitly when you only need a size estimate and cost matters more than freshness." - added
Input schema / properties / personas / itemsAdded value: +{} - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / blocked_by_vocabulary / $refRemoved value: -"#/properties/vocabulary_warnings" - added
Output schema / properties / blocked_by_vocabulary / itemsAdded value: +{} - added
Output schema / properties / blocked_by_vocabulary / typeAdded value: +"array" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
enrich_company6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Input schema / properties / mode / descriptionPrevious value: -"Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when a recent cached record is good enough and cost matters more than freshness."New value: +"Data mode. \"database\" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. \"realtime\" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. \"auto\" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick \"database\" explicitly when a recent cached record is good enough and cost matters more than freshness." - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
enrich_lead6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Input schema / properties / mode / descriptionPrevious value: -"Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when a record from the last 12 months is good enough and cost matters more than freshness."New value: +"Data mode. \"database\" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. \"realtime\" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. \"auto\" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick \"database\" explicitly when a record from the last 12 months is good enough and cost matters more than freshness." - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
find_phone5 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
generate_email7 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / candidates / items / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / itemsAdded value: +{} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
get_balance6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / grants_usdAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
get_bulk_job5 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
get_lead_by_url6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Input schema / properties / mode / descriptionPrevious value: -"Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when a recent cached record is good enough and cost matters more than freshness."New value: +"Data mode. \"database\" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. \"realtime\" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. \"auto\" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick \"database\" explicitly when a recent cached record is good enough and cost matters more than freshness." - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
health5 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
manage_webhooks5 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
preview_leads16 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / department_headcount / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / headcount_growth / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / revenues_range / additionalPropertiesRemoved value: -false - changed
Input schema / properties / exclude_names / descriptionPrevious value: -"Skip leads by full name. KNOWN ISSUE: in database mode any non-empty value collapses the result set to 0 (verified 2026-08-09); it behaves correctly in realtime mode. Prefer exclude_ids, or filter names out yourself after the search."New value: +"Skip leads by full name. Works in both modes (the database-mode bug that returned 0 rows was fixed in the API on 2026-08-13, PRO-1333). exclude_ids is still the more reliable way to paginate." - added
Input schema / properties / personas / itemsAdded value: +{} - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / blocked_by_vocabulary / $refRemoved value: -"#/properties/vocabulary_warnings" - added
Output schema / properties / blocked_by_vocabulary / itemsAdded value: +{} - added
Output schema / properties / blocked_by_vocabulary / typeAdded value: +"array" - added
Output schema / properties / companies / itemsAdded value: +{} - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / leads / itemsAdded value: +{} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
resolve_profile6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / profiles / itemsAdded value: +{} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
search_companies15 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / department_headcount / additionalPropertiesRemoved value: -false - added
Input schema / properties / detailAdded value: +{ + "description": "Row detail for the database search. Thin rows are FREE — id, name, industry, headcount_range, HQ country/city, company_type, founded_year; no LinkedIn URL, domain, contacts or history — up to a daily per-account row quota that resets at 00:00 UTC. Omitted (default): thin while the free tier is available; once it is not (quota spent, a custom-contract account, a server without the tier) the search continues as before — full rows billed per row, marked thin_unavailable in the result, under the spend ceiling. \"thin\": free rows only — never billed, never escalated to realtime; a spent quota is a 429 and a realtime-only filter is an error. \"full\": the whole record, billed per row. Browse thin, then spend only on the rows you keep: generate_email takes the lead id directly, enrich_* gives the full record.", + "enum": [ + "thin", + "full" + ], + "type": "string" +} - removed
Input schema / properties / headcount_growth / additionalPropertiesRemoved value: -false - changed
Input schema / properties / mode / descriptionPrevious value: -"Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when freshness is not critical and cost matters more than freshness."New value: +"Data mode. \"database\" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. \"realtime\" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. \"auto\" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick \"database\" explicitly when freshness is not critical and cost matters more than freshness." - removed
Input schema / properties / revenues_range / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / blocked_by_vocabulary / $refRemoved value: -"#/properties/vocabulary_warnings" - added
Output schema / properties / blocked_by_vocabulary / itemsAdded value: +{} - added
Output schema / properties / blocked_by_vocabulary / typeAdded value: +"array" - added
Output schema / properties / companies / itemsAdded value: +{} - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / leads / itemsAdded value: +{} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
search_leads18 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / department_headcount / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / headcount_growth / additionalPropertiesRemoved value: -false - removed
Input schema / properties / company_filters / properties / revenues_range / additionalPropertiesRemoved value: -false - added
Input schema / properties / detailAdded value: +{ + "description": "Row detail for the database search. Thin rows are FREE — id, name, job_title, seniority, location, company name/id/industry/country; no LinkedIn URL, domain, contacts or history — up to a daily per-account row quota that resets at 00:00 UTC. Omitted (default): thin while the free tier is available; once it is not (quota spent, a custom-contract account, a server without the tier) the search continues as before — full rows billed per row, marked thin_unavailable in the result, under the spend ceiling. \"thin\": free rows only — never billed, never escalated to realtime; a spent quota is a 429 and a realtime-only filter is an error. \"full\": the whole record, billed per row. Browse thin, then spend only on the rows you keep: generate_email takes the lead id directly, enrich_* gives the full record.", + "enum": [ + "thin", + "full" + ], + "type": "string" +} - changed
Input schema / properties / exclude_names / descriptionPrevious value: -"Skip leads by full name. KNOWN ISSUE: in database mode any non-empty value collapses the result set to 0 (verified 2026-08-09); it behaves correctly in realtime mode. Prefer exclude_ids, or filter names out yourself after the search."New value: +"Skip leads by full name. Works in both modes (the database-mode bug that returned 0 rows was fixed in the API on 2026-08-13, PRO-1333). exclude_ids is still the more reliable way to paginate." - changed
Input schema / properties / mode / descriptionPrevious value: -"Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when freshness is not critical and cost matters more than freshness."New value: +"Data mode. \"database\" = Generect's own index: sub-second, free counts, free thin rows (see detail) or cheaper full rows; it accepts a subset of the filters today and names any it rejects. \"realtime\" = live LinkedIn lookup, 5–60s, billed per row, accepts every realtime filter. \"auto\" (default) tries database first and escalates to realtime only if a filter you passed is rejected there (the escalation is reported, and is refused above the per-call spend ceiling). Pick \"database\" explicitly when freshness is not critical and cost matters more than freshness." - added
Input schema / properties / personas / itemsAdded value: +{} - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / blocked_by_vocabulary / $refRemoved value: -"#/properties/vocabulary_warnings" - added
Output schema / properties / blocked_by_vocabulary / itemsAdded value: +{} - added
Output schema / properties / blocked_by_vocabulary / typeAdded value: +"array" - added
Output schema / properties / companies / itemsAdded value: +{} - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / leads / itemsAdded value: +{} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
start_bulk_job6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / items / items / propertyNamesAdded value: +{ + "type": "string" +} - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
- Changed
validate_email5 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / deprecated_params_ignored / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / vocabulary_warnings / itemsAdded value: +{}
17 tool updates
v0.9.0- Added
count_companies - Added
count_leads - Added
enrich_company - Added
enrich_lead - Added
find_phone - Changed
generate_email10 fields changed- added
Input schema / properties / candidatesAdded value: +{ + "description": "Batch mode. Each entry uses the same identifier rules as the single-person form.", + "items": { + "additionalProperties": false, + "description": "One of: {lead_id} | {linkedin_url} | {first_name,last_name,domain}", + "properties": { + "domain": { + "type": "string" + }, + "first_name": { + "type": "string" + }, + "last_name": { + "type": "string" + }, + "lead_id": { + "type": "string" + }, + "linkedin_url": { + "type": "string" + }, + "middle_name": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" +} - changed
Input schema / properties / domain / descriptionPrevious value: -"Company domain without protocol (e.g., generect.com)"New value: +"Company domain without protocol, e.g. \"stripe.com\" (name+domain mode)." - changed
Input schema / properties / first_name / descriptionPrevious value: -"First name of the person"New value: +"First name (name+domain mode)." - changed
Input schema / properties / last_name / descriptionPrevious value: -"Last name of the person"New value: +"Last name (name+domain mode)." - added
Input schema / properties / lead_idAdded value: +{ + "description": "Generect lead id from search / preview / enrich results — the cheapest and most accurate identifier.", + "type": "string" +} - added
Input schema / properties / linkedin_urlAdded value: +{ + "description": "LinkedIn profile URL.", + "type": "string" +} - added
Input schema / properties / middle_nameAdded value: +{ + "description": "Middle name (optional, improves pattern matching).", + "type": "string" +} - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in milliseconds"New value: +"Request timeout in milliseconds." - removed
Input schema / requiredRemoved value: -[ - "first_name", - "last_name", - "domain" -] - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cost": { + "additionalProperties": false, + "properties": { + "amount_charged_usd": { + "type": [ + "number", + "null" + ] + }, + "billed": { + "type": "string" + }, + "note": { + "type": "string" + }, + "operation": { + "type": "string" + } + }, + "type": "object" + }, + "deprecated_params_ignored": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "dropped": { + "type": "number" + }, + "job": {}, + "mode": { + "type": "string" + }, + "next_step": { + "type": "string" + }, + "requested": { + "type": "number" + }, + "results": { + "type": "array" + }, + "submitted": { + "type": "number" + }, + "test_mode": { + "type": "boolean" + }, + "test_mode_notice": { + "type": "string" + }, + "vocabulary_warnings": { + "type": "array" + } + }, + "type": "object" +}
- Added
get_balance - Added
get_bulk_job - Changed
get_lead_by_url13 fields changed- changed
Input schema / properties / comments / descriptionPrevious value: -"Include comments data"New value: +"DEPRECATED — accepted but ignored. Removed: v1 enrich returns the full profile without per-section toggles." - removed
Input schema / properties / comments / typeRemoved value: -"boolean" - added
Input schema / properties / compactAdded value: +{ + "description": "Default true: return a small per-lead summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields.", + "type": "boolean" +} - changed
Input schema / properties / inexact_company / descriptionPrevious value: -"Allow inexact company matching"New value: +"DEPRECATED — accepted but ignored. Removed: v1 enrich matches on the identifier you pass." - removed
Input schema / properties / inexact_company / typeRemoved value: -"boolean" - added
Input schema / properties / modeAdded value: +{ + "description": "Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when a recent cached record is good enough and cost matters more than freshness.", + "enum": [ + "auto", + "database", + "realtime" + ], + "type": "string" +} - changed
Input schema / properties / people_also_viewed / descriptionPrevious value: -"Include people also viewed"New value: +"DEPRECATED — accepted but ignored. Removed: v1 enrich returns the full profile without per-section toggles." - removed
Input schema / properties / people_also_viewed / typeRemoved value: -"boolean" - changed
Input schema / properties / posts / descriptionPrevious value: -"Include posts data"New value: +"DEPRECATED — accepted but ignored. Removed: v1 enrich returns the full profile without per-section toggles." - removed
Input schema / properties / posts / typeRemoved value: -"boolean" - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in milliseconds"New value: +"Request timeout in milliseconds." - changed
Input schema / properties / url / descriptionPrevious value: -"LinkedIn profile URL (e.g., https://www.linkedin.com/in/username/)"New value: +"LinkedIn profile URL (e.g. https://www.linkedin.com/in/username/)." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "company": {}, + "cost": { + "additionalProperties": false, + "properties": { + "amount_charged_usd": { + "type": [ + "number", + "null" + ] + }, + "billed": { + "type": "string" + }, + "note": { + "type": "string" + }, + "operation": { + "type": "string" + } + }, + "type": "object" + }, + "deprecated_params_ignored": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "found": { + "type": "boolean" + }, + "lead": {}, + "mode": { + "type": "string" + }, + "test_mode": { + "type": "boolean" + }, + "test_mode_notice": { + "type": "string" + }, + "vocabulary_warnings": { + "type": "array" + } + }, + "type": "object" +}
- Changed
health4 fields changed- added
Input schema / properties / check_credentialAdded value: +{ + "description": "Also verify the API token against the free /accounts/me endpoint. Default true.", + "type": "boolean" +} - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in milliseconds"New value: +"Request timeout in milliseconds." - removed
Input schema / properties / urlRemoved value: -{ - "description": "LinkedIn profile URL to validate (defaults to a public profile)", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "account": { + "type": [ + "string", + "null" + ] + }, + "api_base": { + "type": "string" + }, + "balance_usd": { + "type": [ + "number", + "null" + ] + }, + "cost": { + "additionalProperties": false, + "properties": { + "amount_charged_usd": { + "type": [ + "number", + "null" + ] + }, + "billed": { + "type": "string" + }, + "note": { + "type": "string" + }, + "operation": { + "type": "string" + } + }, + "type": "object" + }, + "credential_error": {}, + "credential_valid": { + "type": "boolean" + }, + "deprecated_params_ignored": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "has_credential": { + "type": "boolean" + }, + "ms": { + "type": "number" + }, + "ok": { + "type": "boolean" + }, + "server": { + "type": "string" + }, + "test_mode": { + "type": "boolean" + }, + "test_mode_notice": { + "type": "string" + }, + "version": { + "type": "string" + }, + "vocabulary_warnings": { + "type": "array" + } + }, + "type": "object" +}
- Added
manage_webhooks - Added
preview_leads - Added
resolve_profile - Changed
search_companies32 fields changed- added
Input schema / properties / allow_unlisted_valuesAdded value: +{ + "description": "Escape hatch for the local vocabulary check — see the lead-side field of the same name.", + "type": "boolean" +} - changed
Input schema / properties / compact / descriptionPrevious value: -"Return compact summary instead of full JSON"New value: +"Default true: return a small per-company summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields." - added
Input schema / properties / company_namesAdded value: +{ + "description": "Restrict to specific company names — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / company_types / descriptionPrevious value: -"Company types"New value: +"Company types: \"Public Company\",\"Privately Held\",\"Non Profit\",\"Government Agency\",\"Educational\", …" - added
Input schema / properties / confirm_spend_usdAdded value: +{ + "description": "Explicit approval for an unusually large charge. Calls whose worst case exceeds $5 are refused unless this is set to at least the amount the tool reports. Only set it after the user has agreed to that number.", + "type": "number" +} - added
Input schema / properties / department_headcountAdded value: +{ + "additionalProperties": false, + "description": "Department size, e.g. {\"name\":\"engineering\",\"min\":10,\"max\":100} — realtime only: using it forces the pricier live mode.", + "properties": { + "max": { + "type": "number" + }, + "min": { + "type": "number" + }, + "name": { + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" +} - added
Input schema / properties / exclude_domainsAdded value: +{ + "description": "Exclude companies by domain (e.g. existing customers).", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / exclude_idsAdded value: +{ + "description": "Exclude companies by LinkedIn id/URN.", + "items": { + "type": [ + "string", + "number" + ] + }, + "type": "array" +} - added
Input schema / properties / exclude_industriesAdded value: +{ + "description": "Industries to exclude.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / exclude_locationsAdded value: +{ + "description": "HQ locations to exclude.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / fallback_from_leads / descriptionPrevious value: -"If no companies, derive from leads by keywords"New value: +"DEPRECATED — accepted but ignored. Removed. It fabricated lead-derived name aggregates and cost an extra billable query." - removed
Input schema / properties / fallback_from_leads / typeRemoved value: -"boolean" - changed
Input schema / properties / get_max_companies / descriptionPrevious value: -"Get maximum companies"New value: +"DEPRECATED — accepted but ignored. Always on now: search responses include results_count without asking." - removed
Input schema / properties / get_max_companies / typeRemoved value: -"boolean" - added
Input schema / properties / headcount_growthAdded value: +{ + "additionalProperties": false, + "description": "Headcount growth in percent — realtime only: using it forces the pricier live mode.", + "properties": { + "max": { + "type": "number" + }, + "min": { + "type": "number" + } + }, + "type": "object" +} - changed
Input schema / properties / headcounts / descriptionPrevious value: -"Headcount ranges"New value: +"Size buckets. Allowed ONLY: \"1-10\",\"11-50\",\"51-200\",\"201-500\",\"501-1000\",\"1001-5000\",\"5001-10000\",\"10 000+\"." - added
Input schema / properties / hiring_on_linkedinAdded value: +{ + "description": "Only companies actively hiring — realtime only: using it forces the pricier live mode.", + "type": "boolean" +} - changed
Input schema / properties / industries / descriptionPrevious value: -"Industries"New value: +"Company industries. Must match Generect industry names exactly (e.g. \"Software Development\"); unknown names are rejected with HTTP 400." - changed
Input schema / properties / keywords / descriptionPrevious value: -"Keywords"New value: +"Free-text keywords across name/description/specialties — realtime only: using it forces the pricier live mode." - added
Input schema / properties / limitAdded value: +{ + "description": "Alias for limit_by.", + "type": "number" +} - changed
Input schema / properties / limit_by / descriptionPrevious value: -"Number of results to return"New value: +"Rows to return this call (1–100, default 25). You are billed per returned row, so this number IS the price of the call." - added
Input schema / properties / linkedins_linksAdded value: +{ + "description": "Specific LinkedIn company URLs — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / locations / descriptionPrevious value: -"Locations (Countries, e.g \"United States\")"New value: +"HQ locations — cities, states or countries." - added
Input schema / properties / modeAdded value: +{ + "description": "Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when freshness is not critical and cost matters more than freshness.", + "enum": [ + "auto", + "database", + "realtime" + ], + "type": "string" +} - added
Input schema / properties / num_of_followersAdded value: +{ + "description": "LinkedIn follower buckets: \"1-50\",\"51-100\",\"101-1000\",\"1001-5000\",\"5001+\" — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / offsetAdded value: +{ + "description": "Alias for offset_by.", + "type": "number" +} - changed
Input schema / properties / offset_by / descriptionPrevious value: -"Offset for pagination"New value: +"Rows to skip (pagination)." - added
Input schema / properties / revenues_rangeAdded value: +{ + "additionalProperties": false, + "description": "Annual revenue range, single object {min,max} — realtime only: using it forces the pricier live mode.", + "properties": { + "max": { + "type": "number" + }, + "min": { + "type": "number" + } + }, + "required": [ + "min", + "max" + ], + "type": "object" +} - added
Input schema / properties / sub_industriesAdded value: +{ + "description": "Expand each selected industry to its sub-industries as well (broadens the match).", + "type": "boolean" +} - added
Input schema / properties / technologiesAdded value: +{ + "description": "Technologies the company uses — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in milliseconds"New value: +"Request timeout in milliseconds." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "api_returned_more_than_requested": { + "type": "number" + }, + "blocked_by_vocabulary": { + "$ref": "#/properties/vocabulary_warnings" + }, + "companies": { + "type": "array" + }, + "cost": { + "additionalProperties": false, + "properties": { + "amount_charged_usd": { + "type": [ + "number", + "null" + ] + }, + "billed": { + "type": "string" + }, + "note": { + "type": "string" + }, + "operation": { + "type": "string" + } + }, + "type": "object" + }, + "deprecated_params_ignored": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "escalated_to_realtime_because": { + "items": { + "type": "string" + }, + "type": "array" + }, + "escalation_note": { + "type": "string" + }, + "fix": { + "type": "string" + }, + "leads": { + "type": "array" + }, + "mode": { + "type": "string" + }, + "next_page_args": {}, + "note": { + "type": "string" + }, + "requested_rows": { + "type": "number" + }, + "results_count": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": "number" + }, + "spend_guard": {}, + "status": { + "type": "string" + }, + "test_mode": { + "type": "boolean" + }, + "test_mode_notice": { + "type": "string" + }, + "vocabulary_warnings": { + "type": "array" + } + }, + "type": "object" +}
- Changed
search_leads47 fields changed- added
Input schema / properties / allow_unlisted_valuesAdded value: +{ + "description": "Escape hatch. This server checks industry / seniority / headcount / company-type values against the LinkedIn vocabularies before sending, because the API silently returns 0 results for an unknown industry or seniority instead of rejecting it. Set true only when you are sure a value is valid and this server is out of date.", + "type": "boolean" +} - added
Input schema / properties / changed_jobsAdded value: +{ + "description": "Only leads who recently changed jobs — realtime only: using it forces the pricier live mode.", + "type": "boolean" +} - changed
Input schema / properties / compact / descriptionPrevious value: -"Return compact summary instead of full JSON"New value: +"Default true: return a small per-lead summary (including the Generect `id`, which every later step accepts). Set false for the full raw record (~80 fields) — only worth it when you specifically need skills, education or other deep fields." - added
Input schema / properties / company_filtersAdded value: +{ + "additionalProperties": false, + "description": "Optional: only return leads at companies matching these filters (two-level ICP).", + "properties": { + "allow_unlisted_values": { + "description": "Escape hatch for the local vocabulary check — see the lead-side field of the same name.", + "type": "boolean" + }, + "company_names": { + "description": "Restrict to specific company names — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" + }, + "company_types": { + "description": "Company types: \"Public Company\",\"Privately Held\",\"Non Profit\",\"Government Agency\",\"Educational\", …", + "items": { + "type": "string" + }, + "type": "array" + }, + "department_headcount": { + "additionalProperties": false, + "description": "Department size, e.g. {\"name\":\"engineering\",\"min\":10,\"max\":100} — realtime only: using it forces the pricier live mode.", + "properties": { + "max": { + "type": "number" + }, + "min": { + "type": "number" + }, + "name": { + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "exclude_domains": { + "description": "Exclude companies by domain (e.g. existing customers).", + "items": { + "type": "string" + }, + "type": "array" + }, + "exclude_ids": { + "description": "Exclude companies by LinkedIn id/URN.", + "items": { + "type": [ + "string", + "number" + ] + }, + "type": "array" + }, + "exclude_industries": { + "description": "Industries to exclude.", + "items": { + "type": "string" + }, + "type": "array" + }, + "exclude_locations": { + "description": "HQ locations to exclude.", + "items": { + "type": "string" + }, + "type": "array" + }, + "headcount_growth": { + "additionalProperties": false, + "description": "Headcount growth in percent — realtime only: using it forces the pricier live mode.", + "properties": { + "max": { + "type": "number" + }, + "min": { + "type": "number" + } + }, + "type": "object" + }, + "headcounts": { + "description": "Size buckets. Allowed ONLY: \"1-10\",\"11-50\",\"51-200\",\"201-500\",\"501-1000\",\"1001-5000\",\"5001-10000\",\"10 000+\".", + "items": { + "type": "string" + }, + "type": "array" + }, + "hiring_on_linkedin": { + "description": "Only companies actively hiring — realtime only: using it forces the pricier live mode.", + "type": "boolean" + }, + "industries": { + "description": "Company industries. Must match Generect industry names exactly (e.g. \"Software Development\"); unknown names are rejected with HTTP 400.", + "items": { + "type": "string" + }, + "type": "array" + }, + "keywords": { + "description": "Free-text keywords across name/description/specialties — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" + }, + "linkedins_links": { + "description": "Specific LinkedIn company URLs — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "description": "HQ locations — cities, states or countries.", + "items": { + "type": "string" + }, + "type": "array" + }, + "num_of_followers": { + "description": "LinkedIn follower buckets: \"1-50\",\"51-100\",\"101-1000\",\"1001-5000\",\"5001+\" — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" + }, + "revenues_range": { + "additionalProperties": false, + "description": "Annual revenue range, single object {min,max} — realtime only: using it forces the pricier live mode.", + "properties": { + "max": { + "type": "number" + }, + "min": { + "type": "number" + } + }, + "required": [ + "min", + "max" + ], + "type": "object" + }, + "sub_industries": { + "description": "Expand each selected industry to its sub-industries as well (broadens the match).", + "type": "boolean" + }, + "technologies": { + "description": "Technologies the company uses — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" +} - added
Input schema / properties / company_headcountsAdded value: +{ + "description": "Employer size buckets. Allowed ONLY: \"1-10\",\"11-50\",\"51-200\",\"201-500\",\"501-1000\",\"1001-5000\",\"5001-10000\",\"10 000+\" (note the space in \"10 000+\").", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / company_id / descriptionPrevious value: -"LinkedIn company id"New value: +"Anchor to one company by LinkedIn numeric id." - changed
Input schema / properties / company_id / typePrevious value: -"string"New value: +[ + "string", + "number" +] - added
Input schema / properties / company_industriesAdded value: +{ + "description": "Industry of the current employer. Must match Generect industry names exactly (e.g. \"Software Development\", \"Financial Services\"); names are hierarchical and unknown names are rejected with HTTP 400 naming the field.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / company_link / descriptionPrevious value: -"LinkedIn company URL"New value: +"Anchor to one company by LinkedIn URL." - added
Input schema / properties / company_locationsAdded value: +{ + "description": "HQ location of the lead's current employer.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / company_name / descriptionPrevious value: -"Company name"New value: +"Anchor to one company by name (exclusive with company_link/company_id)." - added
Input schema / properties / company_typesAdded value: +{ + "description": "Employer types: \"Public Company\",\"Privately Held\",\"Non Profit\",\"Government Agency\",\"Educational\",\"Self Employed\",\"Self Owned\",\"Partnership\".", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / confirm_spend_usdAdded value: +{ + "description": "Explicit approval for an unusually large charge. Calls whose worst case exceeds $5 are refused unless this is set to at least the amount the tool reports. Only set it after the user has agreed to that number.", + "type": "number" +} - added
Input schema / properties / exclude_company_headcountsAdded value: +{ + "description": "Employer size buckets to exclude.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / exclude_company_industriesAdded value: +{ + "description": "Employer industries to exclude.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / exclude_company_locationsAdded value: +{ + "description": "Employer HQ locations to exclude.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / exclude_idsAdded value: +{ + "description": "Skip leads by Generect/Sales-Navigator id. Pass the ids you already received to paginate without duplicates — ordering is not stable, so this is more reliable than offset.", + "items": { + "type": [ + "string", + "number" + ] + }, + "type": "array" +} - added
Input schema / properties / exclude_locationsAdded value: +{ + "description": "Lead locations to exclude.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / exclude_namesAdded value: +{ + "description": "Skip leads by full name. KNOWN ISSUE: in database mode any non-empty value collapses the result set to 0 (verified 2026-08-09); it behaves correctly in realtime mode. Prefer exclude_ids, or filter names out yourself after the search.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / exclude_title_keywordsAdded value: +{ + "description": "DEPRECATED — accepted but ignored. No v1 equivalent. Narrow job_titles instead, or filter the returned rows yourself." +} - added
Input schema / properties / filter_empty_varsAdded value: +{ + "description": "Drop leads where these fields are empty, e.g. [\"profile_photo\",\"job_started_on\"]. Useful to raise data quality before paying.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / functionsAdded value: +{ + "description": "Job functions, e.g. [\"Sales\",\"Marketing\",\"Engineering\"] — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / get_max_leadsAdded value: +{ + "description": "DEPRECATED — accepted but ignored. Always on now: search responses include results_count without asking." +} - changed
Input schema / properties / job_title / descriptionPrevious value: -"Job title filter (e.g., CEO, CTO, Engineer)"New value: +"DEPRECATED alias for job_titles. Still honoured: it is merged into job_titles." - added
Input schema / properties / job_titlesAdded value: +{ + "description": "Target job titles, OR-matched (e.g. [\"CEO\",\"Founder\",\"Owner\"]). A lead needs to match only one.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / keywordsAdded value: +{ + "description": "Free-text keywords across headline/summary/skills — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / lead_industries / descriptionPrevious value: -"Industry filter (e.g., Technology, Healthcare)"New value: +"DEPRECATED — accepted but ignored. Removed: v1 filters on the employer's industry. Use company_industries." - removed
Input schema / properties / lead_industries / itemsRemoved value: -{ - "type": "string" -} - removed
Input schema / properties / lead_industries / typeRemoved value: -"array" - added
Input schema / properties / limitAdded value: +{ + "description": "Alias for limit_by.", + "type": "number" +} - changed
Input schema / properties / limit_by / descriptionPrevious value: -"Number of results to return"New value: +"Rows to return this call (1–100, default 25). You are billed per returned row, so this number IS the price of the call." - added
Input schema / properties / linkedin_filter_linkAdded value: +{ + "description": "A LinkedIn / Sales Navigator search URL to lift filters from — realtime only: using it forces the pricier live mode.", + "type": "string" +} - changed
Input schema / properties / locations / descriptionPrevious value: -"Location filter (e.g., San Francisco, New York)"New value: +"Where the lead lives — matches cities, states and countries, e.g. [\"United States\",\"Berlin\"]." - added
Input schema / properties / modeAdded value: +{ + "description": "Data mode. \"database\" = cached, sub-second, cheaper, free counts, core filters only. \"realtime\" = live LinkedIn lookup, 5–60s, pricier, supports every filter. \"auto\" (default) tries database first and only escalates to realtime if a filter you passed is unsupported there — an escalation is reported in the response. Pick \"database\" explicitly when freshness is not critical and cost matters more than freshness.", + "enum": [ + "auto", + "database", + "realtime" + ], + "type": "string" +} - added
Input schema / properties / offsetAdded value: +{ + "description": "Alias for offset_by.", + "type": "number" +} - changed
Input schema / properties / offset_by / descriptionPrevious value: -"Offset for pagination"New value: +"Rows to skip (pagination)." - added
Input schema / properties / past_company_namesAdded value: +{ + "description": "Companies the lead previously worked at (alumni targeting) — realtime only: using it forces the pricier live mode.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / personasAdded value: +{ + "description": "Advanced raw persona tuples [name, functions, seniorities, prohibits, priority?] — realtime only: using it forces the pricier live mode.", + "type": "array" +} - added
Input schema / properties / posted_on_linkedinAdded value: +{ + "description": "Only leads who recently posted on LinkedIn — realtime only: using it forces the pricier live mode.", + "type": "boolean" +} - added
Input schema / properties / senioritiesAdded value: +{ + "description": "Seniority at the current employer, e.g. [\"Owner\",\"CXO\",\"VP\",\"Director\",\"Manager\"]. Current position only.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / strictAdded value: +{ + "description": "Fields to match strictly, e.g. [\"company_locations\"].", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / timeout_ms / descriptionPrevious value: -"Request timeout in milliseconds"New value: +"Request timeout in milliseconds." - changed
Input schema / properties / without_company / descriptionPrevious value: -"Search leads without filrest by companies"New value: +"DEPRECATED — accepted but ignored. No longer needed — v1 filter-only search is the default when no company anchor is set." - removed
Input schema / properties / without_company / typeRemoved value: -"boolean" - added
Input schema / properties / years_in_companyAdded value: +{ + "description": "Time at current company, same buckets as years_in_position — realtime only: using it forces the pricier live mode.", + "items": { + "type": "number" + }, + "type": "array" +} - added
Input schema / properties / years_in_positionAdded value: +{ + "description": "Time in current role: 1=<1y, 2=1-2y, 3=3-5y, 4=6-10y, 5=10y+ — realtime only: using it forces the pricier live mode.", + "items": { + "type": "number" + }, + "type": "array" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "api_returned_more_than_requested": { + "type": "number" + }, + "blocked_by_vocabulary": { + "$ref": "#/properties/vocabulary_warnings" + }, + "companies": { + "type": "array" + }, + "cost": { + "additionalProperties": false, + "properties": { + "amount_charged_usd": { + "type": [ + "number", + "null" + ] + }, + "billed": { + "type": "string" + }, + "note": { + "type": "string" + }, + "operation": { + "type": "string" + } + }, + "type": "object" + }, + "deprecated_params_ignored": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "escalated_to_realtime_because": { + "items": { + "type": "string" + }, + "type": "array" + }, + "escalation_note": { + "type": "string" + }, + "fix": { + "type": "string" + }, + "leads": { + "type": "array" + }, + "mode": { + "type": "string" + }, + "next_page_args": {}, + "note": { + "type": "string" + }, + "requested_rows": { + "type": "number" + }, + "results_count": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": "number" + }, + "spend_guard": {}, + "status": { + "type": "string" + }, + "test_mode": { + "type": "boolean" + }, + "test_mode_notice": { + "type": "string" + }, + "vocabulary_warnings": { + "type": "array" + } + }, + "type": "object" +}
- Added
start_bulk_job - Added
validate_email
5 tool updates
v0.1.0- First observed
generate_email - First observed
get_lead_by_url - First observed
health - First observed
search_companies - First observed
search_leads
TDQS
Scored across 21 tools
Most tools have clearly distinct resource/action boundaries, especially between counting, previewing, searching, and enriching. The main confusion is get_lead_by_url, which is explicitly an alias of enrich_lead, plus some conceptual overlap between resolve_profile and enrich_lead.
The set is mostly consistent snake_case verb_noun naming (search_leads, enrich_company, create_webhook), which is easy to scan. Minor deviations are health as a bare noun and get_lead_by_url, whose get_ prefix is semantically inconsistent with the enrich_ family.
At 21 tools the surface is somewhat heavy, though the domain is broad: search, enrichment, email, phone, bulk jobs, webhooks, and account health. The redundant alias get_lead_by_url and the five webhook tools push it beyond the ideal tightly scoped range.
The surface covers the core lead-generation lifecycle: counting, searching, previewing, enriching, email generation/validation, phone lookup, bulk jobs, and webhook management. Minor gaps remain around asynchronous job management, such as canceling or listing bulk jobs, but most workflows are workable.
Maintenance
Related MCP Connectors
Search people and companies, enrich profiles, and find email and phone over MCP.
LeadMagic MCP — wraps the LeadMagic B2B email-finder API (leadmagic.io)
Managed LinkedIn MCP server for AI agents: search, connect, message and enrich on accounts you own.
MCP server for Tomba email finder, verification, and contact enrichment API
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceAn MCP server providing real-time access to comprehensive B2B company and contact data for lead generation and business intelligence. It enables AI tools to search firmographics, discover key contacts, and automate personalized outreach workflows.258MIT

scrapercity-cliofficial
AlicenseBqualityAmaintenanceB2B lead generation MCP server with 20+ lead generation tools - Apollo scraping, Google Maps, email finder, email validator, mobile finder, skip trace, ecommerce store data, and more.25892 npm1MIT- AlicenseNot gradedqualityAmaintenanceMCP server that enables AI agents to discover and qualify B2B leads from Leadbay's knowledge base, with tools for lead research, enrichment, and outreach logging.MIT
- AlicenseAqualityDmaintenanceLead generation MCP server for AI agents. Find emails, verify contacts, enrich profiles, and search prospects using Hunter.io, Apollo.io, and Abstract API.815 npmMIT