Skip to main content
Glama

Salesbot - B2B outreach LinkedIn MCP Server with CRM and email

search_linkedin_people

Default tool for finding people on LinkedIn from criteria (company, role, department). With a ready search URL use search_linkedin_navigator; for one known profile URL use upsert_linkedin_contact. Search LinkedIn people. RECOMMENDED FOR PROSPECTING: set decisionMakers:true, provide company, departments and limit 20-30. Salesbot resolves the company, performs ONE company-scoped provider search (Sales Navigator also applies seniority), then ranks the returned senior employees locally by department. This is broader and safer than retrying exact titles. Use title/titles only when an exact role is required. EXISTING CONNECTIONS reads only the local cache and consumes zero search quota. The workspace setting selects Standard/Classic or Sales Navigator automatically. Respect retry_after; never immediately retry a protected or timed-out request. On LINKEDIN_PROVIDER_TIMEOUT use search_google_xray, then retry LinkedIn only after the stated delay.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoMax results (default 10; capped automatically at 20 Classic or 30 Sales Navigator)
titleNoSingle job title to search for (e.g. 'CEO'). Use `titles` instead when you have a priority order.
titlesNoUp to 3 ordered plain job titles. With explicit companyId each title is sent as top-level keywords with CURRENT COMPANY applied. A raw batch with no role-relevant headlines counts as a miss. Classic may return the third title in remaining_titles because its safety budget permits only 2 provider searches. Run later batches only after retry_after.
companyNoCompany NAME for diagnostics, resolution, and guarded keyword fallback (e.g. 'Doosan'). Keep this a string; the provider company array is constructed internally.
networkNoIgnored for company-role searches. Existing-connections mode always applies 1st-degree internally.
keywordsNoFree keyword phrase for existing-connections mode, e.g. 'fleet manager'. Requires connectionsOnly: true.
locationNoTarget geography. For Czech prospecting pass 'Czech Republic' or 'Czechia'; applied together with the company filter.
companyIdNoNumeric LinkedIn company ID. Also provide `company`: in Sales Navigator mode Salesbot validates/re-resolves the ID against the Sales Navigator parameter directory before applying CURRENT COMPANY.
locationIdNoRaw LinkedIn geography ID. Prefer location unless you already know the correct ID.
departmentsNoBusiness areas used to rank decision makers. Example: ['finance','operations','facility']. Used with decisionMakers:true.
decisionMakersNoRecommended company prospecting mode. Performs one company-scoped search for senior employees and ranks them locally; requires company. Do not combine with title/titles.
connectionsOnlyNoWhen true, search the owner's synchronized 1st-degree connection cache locally. Requires keywords and performs zero LinkedIn searches.
companyLinkedInUrlNoThe company's LinkedIn page, e.g. https://www.linkedin.com/company/mizzox. Best taken from the company's own website (read_company_website returns it as linkedin_company_pages). Salesbot resolves it to the numeric companyId and the exact company name, so you do not need companyId.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / companyLinkedInUrl
      Added value: +{
      +  "description": "The company's LinkedIn page, e.g. https://www.linkedin.com/company/mizzox. Best taken from the company's own website (read_company_website returns it as linkedin_company_pages). Salesbot resolves it to the numeric companyId and the exact company name, so you do not need companyId.",
      +  "type": "string"
      +}
  2. Changed2 schema fields changed
    • changedInput schema / properties / location / description
      Previous value: -"Ignored for company-role and existing-connections searches."New value: +"Target geography. For Czech prospecting pass 'Czech Republic' or 'Czechia'; applied together with the company filter."
    • changedInput schema / properties / locationId / description
      Previous value: -"Ignored for company-role and existing-connections searches."New value: +"Raw LinkedIn geography ID. Prefer location unless you already know the correct ID."
  3. Changed2 schema fields changed
    • addedInput schema / properties / decisionMakers
      Added value: +{
      +  "description": "Recommended company prospecting mode. Performs one company-scoped search for senior employees and ranks them locally; requires company. Do not combine with title/titles.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / departments
      Added value: +{
      +  "description": "Business areas used to rank decision makers. Example: ['finance','operations','facility']. Used with decisionMakers:true.",
      +  "items": {
      +    "enum": [
      +      "finance",
      +      "facility",
      +      "fleet",
      +      "operations",
      +      "logistics",
      +      "procurement",
      +      "hr",
      +      "it",
      +      "sales",
      +      "management"
      +    ],
      +    "type": "string"
      +  },
      +  "maxItems": 8,
      +  "type": "array"
      +}
  4. Changed2 schema fields changed
    • changedInput schema / properties / titles / description
      Previous value: -"Ordered plain job titles. With explicit companyId each title is sent as top-level keywords with CURRENT COMPANY applied. A raw batch with no role-relevant headlines counts as a miss. Maximum two provider searches; extra titles return in remaining_titles."New value: +"Up to 3 ordered plain job titles. With explicit companyId each title is sent as top-level keywords with CURRENT COMPANY applied. A raw batch with no role-relevant headlines counts as a miss. Classic may return the third title in remaining_titles because its safety budget permits only 2 provider searches. Run later batches only after retry_after."
    • addedInput schema / properties / titles / maxItems
      Added value: +3
  5. Changed1 schema field changed
    • changedInput schema / properties / companyId / description
      Previous value: -"Trusted numeric LinkedIn company ID. When explicitly supplied it is applied internally as Unipile CURRENT COMPANY `company:[companyId]`; do not pass an array."New value: +"Numeric LinkedIn company ID. Also provide `company`: in Sales Navigator mode Salesbot validates/re-resolves the ID against the Sales Navigator parameter directory before applying CURRENT COMPANY."
  6. Changed1 schema field changed
    • changedInput schema / properties / limit / description
      Previous value: -"Max results (1-50, default 10)"New value: +"Max results (default 10; capped automatically at 20 Classic or 30 Sales Navigator)"
  7. Changed1 schema field changed
    • changedInput schema / properties / connectionsOnly / description
      Previous value: -"When true, search only the connected LinkedIn account's existing 1st-degree connections. Requires keywords and performs exactly one LinkedIn search."New value: +"When true, search the owner's synchronized 1st-degree connection cache locally. Requires keywords and performs zero LinkedIn searches."
  8. Changed8 schema fields changed
    • changedInput schema / properties / company / description
      Previous value: -"Company NAME for the search box (e.g. 'Škoda Auto', 'EXCALIBUR ARMY'). Resolved to a canonical LinkedIn company title for the keywords string and for company_candidates — NOT applied as Unipile CURRENT COMPANY filter. Optional but strongly recommended."New value: +"Company NAME for diagnostics, resolution, and guarded keyword fallback (e.g. 'Doosan'). Keep this a string; the provider company array is constructed internally."
    • changedInput schema / properties / companyId / description
      Previous value: -"Raw LinkedIn company ID. Optional; used to skip name lookup if you already cached it. The ID is NOT sent as a Unipile company[] filter. The keyword query still uses the company NAME."New value: +"Trusted numeric LinkedIn company ID. When explicitly supplied it is applied internally as Unipile CURRENT COMPANY `company:[companyId]`; do not pass an array."
    • addedInput schema / properties / connectionsOnly
      Added value: +{
      +  "description": "When true, search only the connected LinkedIn account's existing 1st-degree connections. Requires keywords and performs exactly one LinkedIn search.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / keywords
      Added value: +{
      +  "description": "Free keyword phrase for existing-connections mode, e.g. 'fleet manager'. Requires connectionsOnly: true.",
      +  "type": "string"
      +}
    • changedInput schema / properties / location / description
      Previous value: -"Ignored. Search clones the LinkedIn search box (keywords only), not the location filter."New value: +"Ignored for company-role and existing-connections searches."
    • changedInput schema / properties / locationId / description
      Previous value: -"Ignored. Search clones the LinkedIn search box (keywords only), not the location filter."New value: +"Ignored for company-role and existing-connections searches."
    • changedInput schema / properties / network / description
      Previous value: -"Ignored. Search clones the LinkedIn search box (keywords only), not the network filter."New value: +"Ignored for company-role searches. Existing-connections mode always applies 1st-degree internally."
    • changedInput schema / properties / titles / description
      Previous value: -"Ordered job titles for the LinkedIn search box. Title 1 is used as keywords \"<Company> <Title>\"; title 2 is tried only if title 1 returns 0 people (max 2 Unipile searches). Extra titles are not searched and come back in remaining_titles. Plain titles, e.g. ['CFO','Finanční ředitel']. Always pass `company`."New value: +"Ordered plain job titles. With explicit companyId each title is sent as top-level keywords with CURRENT COMPANY applied. A raw batch with no role-relevant headlines counts as a miss. Maximum two provider searches; extra titles return in remaining_titles."
  9. Changed8 schema fields changed
    • changedInput schema / properties / company / description
      Previous value: -"Company NAME (e.g. 'Škoda Auto', 'EXCALIBUR ARMY'). Resolved to a LinkedIn company ID and applied as Unipile CURRENT COMPANY filter. Required unless companyId is set."New value: +"Company NAME for the search box (e.g. 'Škoda Auto', 'EXCALIBUR ARMY'). Resolved to a canonical LinkedIn company title for the keywords string and for company_candidates — NOT applied as Unipile CURRENT COMPANY filter. Optional but strongly recommended."
    • changedInput schema / properties / companyId / description
      Previous value: -"Raw LinkedIn company ID. Optional; skips name lookup and is sent as Unipile company[]. Use after picking from company_candidates."New value: +"Raw LinkedIn company ID. Optional; used to skip name lookup if you already cached it. The ID is NOT sent as a Unipile company[] filter. The keyword query still uses the company NAME."
    • changedInput schema / properties / limit / description
      Previous value: -"Max results after seniority rank (1-10, default 5). Use 2 or 3 for top decision-makers."New value: +"Max results (1-50, default 10)"
    • changedInput schema / properties / location / description
      Previous value: -"Ignored. Roster search does not apply a location AND-filter."New value: +"Ignored. Search clones the LinkedIn search box (keywords only), not the location filter."
    • changedInput schema / properties / locationId / description
      Previous value: -"Ignored. Roster search does not apply a location AND-filter."New value: +"Ignored. Search clones the LinkedIn search box (keywords only), not the location filter."
    • changedInput schema / properties / network / description
      Previous value: -"Ignored. Roster search does not apply a network AND-filter."New value: +"Ignored. Search clones the LinkedIn search box (keywords only), not the network filter."
    • changedInput schema / properties / title / description
      Previous value: -"Optional. Boosts rank if the headline matches this title; not sent to Unipile as a filter."New value: +"Single job title to search for (e.g. 'CEO'). Use `titles` instead when you have a priority order."
    • changedInput schema / properties / titles / description
      Previous value: -"Optional titles used only as an in-memory rank boost (e.g. ['CFO','Finanční ředitel']). Not required. Always pass `company`."New value: +"Ordered job titles for the LinkedIn search box. Title 1 is used as keywords \"<Company> <Title>\"; title 2 is tried only if title 1 returns 0 people (max 2 Unipile searches). Extra titles are not searched and come back in remaining_titles. Plain titles, e.g. ['CFO','Finanční ředitel']. Always pass `company`."
  10. Changed8 schema fields changed
    • changedInput schema / properties / company / description
      Previous value: -"Company NAME for the search box (e.g. 'Škoda Auto', 'EXCALIBUR ARMY'). Resolved to a canonical LinkedIn company title for the keywords string and for company_candidates — NOT applied as Unipile CURRENT COMPANY filter. Optional but strongly recommended."New value: +"Company NAME (e.g. 'Škoda Auto', 'EXCALIBUR ARMY'). Resolved to a LinkedIn company ID and applied as Unipile CURRENT COMPANY filter. Required unless companyId is set."
    • changedInput schema / properties / companyId / description
      Previous value: -"Raw LinkedIn company ID. Optional; used to skip name lookup if you already cached it. The ID is NOT sent as a Unipile company[] filter. The keyword query still uses the company NAME."New value: +"Raw LinkedIn company ID. Optional; skips name lookup and is sent as Unipile company[]. Use after picking from company_candidates."
    • changedInput schema / properties / limit / description
      Previous value: -"Max results (1-50, default 10)"New value: +"Max results after seniority rank (1-10, default 5). Use 2 or 3 for top decision-makers."
    • changedInput schema / properties / location / description
      Previous value: -"Ignored. Search clones the LinkedIn search box (keywords only), not the location filter."New value: +"Ignored. Roster search does not apply a location AND-filter."
    • changedInput schema / properties / locationId / description
      Previous value: -"Ignored. Search clones the LinkedIn search box (keywords only), not the location filter."New value: +"Ignored. Roster search does not apply a location AND-filter."
    • changedInput schema / properties / network / description
      Previous value: -"Ignored. Search clones the LinkedIn search box (keywords only), not the network filter."New value: +"Ignored. Roster search does not apply a network AND-filter."
    • changedInput schema / properties / title / description
      Previous value: -"Single job title to search for (e.g. 'CEO'). Use `titles` instead when you have a priority order."New value: +"Optional. Boosts rank if the headline matches this title; not sent to Unipile as a filter."
    • changedInput schema / properties / titles / description
      Previous value: -"Ordered job titles for the LinkedIn search box. Title 1 is used as keywords \"<Company> <Title>\"; title 2 is tried only if title 1 returns 0 people (max 2 Unipile searches). Extra titles are not searched and come back in remaining_titles. Plain titles, e.g. ['CFO','Finanční ředitel']. Always pass `company`."New value: +"Optional titles used only as an in-memory rank boost (e.g. ['CFO','Finanční ředitel']). Not required. Always pass `company`."
  11. Changed6 schema fields changed
    • changedInput schema / properties / company / description
      Previous value: -"Current company NAME to filter by (e.g. 'Škoda Auto'). Resolved to LinkedIn's CURRENT COMPANY filter automatically, so results are people who work there NOW — use this to find a specific person at a specific company. Optional."New value: +"Company NAME for the search box (e.g. 'Škoda Auto', 'EXCALIBUR ARMY'). Resolved to a canonical LinkedIn company title for the keywords string and for company_candidates — NOT applied as Unipile CURRENT COMPANY filter. Optional but strongly recommended."
    • changedInput schema / properties / companyId / description
      Previous value: -"Raw LinkedIn company ID. Use only if you already know it; otherwise pass `company` by name. Optional."New value: +"Raw LinkedIn company ID. Optional; used to skip name lookup if you already cached it. The ID is NOT sent as a Unipile company[] filter. The keyword query still uses the company NAME."
    • changedInput schema / properties / location / description
      Previous value: -"Human-readable location name (e.g. 'Praha', 'Brno', 'Berlin'). Resolved to LinkedIn geo ID automatically. Use this OR locationId."New value: +"Ignored. Search clones the LinkedIn search box (keywords only), not the location filter."
    • changedInput schema / properties / locationId / description
      Previous value: -"Raw LinkedIn location ID (e.g. '102221843' for Praha). Use this only if you already know the ID."New value: +"Ignored. Search clones the LinkedIn search box (keywords only), not the location filter."
    • changedInput schema / properties / network / description
      Previous value: -"Network filter: 'S' = 2nd degree, 'O' = out of network. Optional."New value: +"Ignored. Search clones the LinkedIn search box (keywords only), not the network filter."
    • changedInput schema / properties / titles / description
      Previous value: -"Ordered priority list of job titles searched ONE AT A TIME (plain LinkedIn Title filter), stopping at the first that returns anyone. Each entry is one title as it appears on LinkedIn — no quotes, no boolean. INCLUDE CZ AND EN VARIANTS AS SEPARATE ENTRIES since the filter is literal, e.g. ['CFO','Finanční ředitel','Chief Financial Officer','Ekonomický ředitel'] or ['Sales Director','Obchodní ředitel','Head of Sales']. Only ~3 are tried per call on the current runtime (rest come back in remaining_titles). Always pass `company`. Response: `matched_title`, `tried_titles`, `remaining_titles`, `company_candidates`."New value: +"Ordered job titles for the LinkedIn search box. Title 1 is used as keywords \"<Company> <Title>\"; title 2 is tried only if title 1 returns 0 people (max 2 Unipile searches). Extra titles are not searched and come back in remaining_titles. Plain titles, e.g. ['CFO','Finanční ředitel']. Always pass `company`."
  12. Changed1 schema field changed
    • changedInput schema / properties / titles / description
      Previous value: -"Ordered priority list of LOGICAL roles, simple names (e.g. ['CFO','Facility manager','Fleet manager','Provozní ředitel']). The server expands each role to its CZ/EN synonyms (CFO → 'CFO OR Finanční ředitel OR Financial Director OR Ekonomický ředitel') and searches it as ONE boolean query scoped to the resolved company; it moves to the next role only when the current one returns nobody, and STOPS at the first hit. Do NOT pre-expand synonyms into separate list entries — one entry = one role. Always pass `company` too. Response: `matched_title`, `tried_titles`, `remaining_titles`, `company_candidates`."New value: +"Ordered priority list of job titles searched ONE AT A TIME (plain LinkedIn Title filter), stopping at the first that returns anyone. Each entry is one title as it appears on LinkedIn — no quotes, no boolean. INCLUDE CZ AND EN VARIANTS AS SEPARATE ENTRIES since the filter is literal, e.g. ['CFO','Finanční ředitel','Chief Financial Officer','Ekonomický ředitel'] or ['Sales Director','Obchodní ředitel','Head of Sales']. Only ~3 are tried per call on the current runtime (rest come back in remaining_titles). Always pass `company`. Response: `matched_title`, `tried_titles`, `remaining_titles`, `company_candidates`."
  13. Changed1 schema field changed
    • changedInput schema / properties / titles / description
      Previous value: -"Ordered priority list of job titles (e.g. ['CFO','Facility manager','Fleet manager','Provozní ředitel','Manager logistiky','COO','Financial Director']). The server searches them ONE AT A TIME in this order and STOPS at the first title that returns anyone — so it never wastes LinkedIn calls on lower-priority roles. The whole cascade counts as a single search against the rate limit. Prefer this over `title` for decision-maker discovery. Response includes `matched_title` (which one hit) and `tried_titles`."New value: +"Ordered priority list of LOGICAL roles, simple names (e.g. ['CFO','Facility manager','Fleet manager','Provozní ředitel']). The server expands each role to its CZ/EN synonyms (CFO → 'CFO OR Finanční ředitel OR Financial Director OR Ekonomický ředitel') and searches it as ONE boolean query scoped to the resolved company; it moves to the next role only when the current one returns nobody, and STOPS at the first hit. Do NOT pre-expand synonyms into separate list entries — one entry = one role. Always pass `company` too. Response: `matched_title`, `tried_titles`, `remaining_titles`, `company_candidates`."
  14. Changed3 schema fields changed
    • changedInput schema / properties / title / description
      Previous value: -"Job title to search for (e.g. 'CEO', 'Marketing Manager')"New value: +"Single job title to search for (e.g. 'CEO'). Use `titles` instead when you have a priority order."
    • addedInput schema / properties / titles
      Added value: +{
      +  "description": "Ordered priority list of job titles (e.g. ['CFO','Facility manager','Fleet manager','Provozní ředitel','Manager logistiky','COO','Financial Director']). The server searches them ONE AT A TIME in this order and STOPS at the first title that returns anyone — so it never wastes LinkedIn calls on lower-priority roles. The whole cascade counts as a single search against the rate limit. Prefer this over `title` for decision-maker discovery. Response includes `matched_title` (which one hit) and `tried_titles`.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "title"
      -]New value: +[]
  15. Changed2 schema fields changed
    • addedInput schema / properties / company
      Added value: +{
      +  "description": "Current company NAME to filter by (e.g. 'Škoda Auto'). Resolved to LinkedIn's CURRENT COMPANY filter automatically, so results are people who work there NOW — use this to find a specific person at a specific company. Optional.",
      +  "type": "string"
      +}
    • addedInput schema / properties / companyId
      Added value: +{
      +  "description": "Raw LinkedIn company ID. Use only if you already know it; otherwise pass `company` by name. Optional.",
      +  "type": "string"
      +}
  16. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnlyHint=false, openWorldHint=true, idempotentHint=false), and the description adds substantial operational context beyond them: quota consumption (existing-connections mode consumes zero search quota), single company-scoped provider search with local ranking, workspace-driven mode selection, retry_after handling, and the LINKEDIN_PROVIDER_TIMEOUT fallback sequence.

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

Conciseness4/5

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

Front-loaded with the primary purpose and routing, and nearly every sentence earns its place with actionable rules. Minor waste in the mid-sentence fragment 'Search LinkedIn people.' that restates the name, and the dense error/retry prose could be tightened.

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

Completeness5/5

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

For a 13-parameter, no-output-schema tool, the description covers the decision-relevant behavior: mode selection, quota implications, retry/timeout handling, and prospecting workflow. An agent has enough to invoke it correctly across its modes.

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

Parameters4/5

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

Schema description coverage is 100%, so per-parameter meaning is already documented; the description still adds cross-parameter workflow semantics (decisionMakers requires company and must not combine with title/titles, limit of 20-30 for prospecting) that the schema alone does not convey.

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

Purpose5/5

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

States a specific verb+resource+scope ('Default tool for finding people on LinkedIn from criteria (company, role, department)') and explicitly names the two sibling tools it is not, so an agent can route correctly without opening either schema.

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

Usage Guidelines5/5

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

Gives explicit routing rules ('With a ready search URL use search_linkedin_navigator; for one known profile URL use upsert_linkedin_contact'), a recommended prospecting path (decisionMakers:true, company, departments, limit 20-30), a when-not ('use title/titles only when an exact role is required'), and a timeout fallback path.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.