Skip to main content
Glama
nick-choudhary

linkedin-sales-nav-mcp

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
HOSTNoHost for HTTP transport127.0.0.1
PORTNoPort for HTTP transport9000
HEADLESSNofalse = visible window (safest); true = headless (more detectable)false
HTTP_PATHNoPath for HTTP transport/mcp
LOG_LEVELNoLog level: DEBUG, INFO, WARNING, ERRORWARNING
TRANSPORTNoTransport type (stdio or HTTP)stdio
CHROME_PATHNoUse your own Chrome instead of bundled Chromium
NAV_TIMEOUTNoTimeout for navigation (seconds)60
CAPTURE_WAITNoWait time for capturing responses (seconds)25
PROXY_SERVERNoLeave empty on your own machine; only for a residential exit node if remote
TOOL_TIMEOUTNoPer-tool MCP timeout (seconds) — must exceed the pacing budget below600.0
LOGIN_TIMEOUTNoTimeout for login (seconds)300
USER_DATA_DIRNoPersistent browser profile directory~/.linkedin-sales-nav/profile
LONG_PAUSE_MAXNoLength of longer break (seconds)45.0
LONG_PAUSE_MINNoLength of longer break (seconds)20.0
PACING_ENABLEDNoHuman-like delays between pagestrue
PAGE_DELAY_MAXNoRandom dwell before advancing a page (seconds)8.0
PAGE_DELAY_MINNoRandom dwell before advancing a page (seconds)3.0
LONG_PAUSE_EVERYNoTake a longer break every N pages (0 disables)5

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}
logging
{}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
extensions
{
  "io.modelcontextprotocol/ui": {}
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
search_contactsA

Search people/leads by driving Sales Navigator in the logged-in browser and capturing its search API responses. Results are saved to the local database automatically; this tool returns a small summary, not the records (call export_results or get_results for the data).

Build the search in Sales Navigator (title / geography / industry / seniority / keyword filters), copy the URL from the address bar, and pass it here. Saved lead lists work too.

Resumable: the search URL is hashed to a query id. If a previous run stopped partway, calling again with the same URL resumes from the next page instead of restarting — safe to call repeatedly to page deeper.

search_accountsA

Search companies/accounts by driving Sales Navigator in the logged-in browser and capturing its search API responses. Results are saved to the local database automatically; this tool returns a small summary, not the records (call export_results or get_results for the data).

Build the search in Sales Navigator (industry / headcount / geography / growth filters), copy the URL from the address bar, and pass it here. Saved account lists work too.

Resumable: the search URL is hashed to a query id. If a previous run stopped partway, calling again with the same URL resumes from the next page instead of restarting.

list_queriesA

List every saved search and its progress.

Returns: Dict with queries: for each, url_hash, url, scraper_type, status (new|in_progress|paused|complete), last_page, total_available, records_count. Use a url_hash with export_results or get_results.

export_resultsB

Export a saved query's records to files under the output folder.

get_resultsA

Pull a bounded slice of a saved query's records into the conversation for analysis. Bounded on purpose — for large sets, prefer export_results and analyze the file with code rather than loading everything into context.

enrich_leadsA

Add Open Profile / InMail status to a saved contact search.

Search results cannot carry this. Sales Navigator's search payload has an openLink field, but it is false for everyone — the real flag is memberBadges.openLink, which only the profile endpoint returns, one request per lead. There is no bulk endpoint.

Costs one LinkedIn request per lead (~1s each with pacing), so it is a separate opt-in tool rather than part of search_contacts. Start with a limit to sample before committing to a whole query.

Results go to the lead_enrichment table, keyed on the stable member_id, and are joined in by get_results / export_results as an enrichment block. Search records are never modified, and a lead enriched once is reused by every search that finds them again.

Resumable and idempotent: with only_missing=true (the default), leads that already have a successful fetch are skipped, so calling repeatedly walks through the query. Failed fetches stay pending and are retried.

check_session_statusA

Check whether the browser profile has a live Sales Navigator session.

Launches (or reuses) the browser and verifies it lands on a signed-in /sales page. Use this first when searches fail — it tells you if you need to run --login again.

Returns: Dict with logged_in (bool), plus the profile directory and headless setting for this server.

next_outreach_batchA

Leads eligible for a first message, best channel first.

Read-only. Excludes anyone already sent to in ANY campaign — dedupe is on the stable member_id, so a person found by three searches is messaged once — and anyone already handled in this campaign.

With open_profile_only (the default) only leads confirmed Open Profile by enrich_leads come back: those are free to message. Run enrich_leads first or this returns nothing.

send_messageA

Send ONE Sales Navigator message. Writes to LinkedIn.

This is the only tool here that is not read-only, and it is guarded accordingly:

  • dry_run defaults to true — you get back exactly what would be sent and nothing leaves the browser. Set it false deliberately.

  • Sending must also be enabled server-side (ENABLE_SENDING=true), so a default install cannot message anyone.

  • A lead already messaged in ANY campaign is refused.

  • A rolling 24h cap applies across all campaigns.

  • If the lead is not Open Profile the message would spend an InMail credit, and that is refused unless ALLOW_CREDIT_SPEND=true.

  • evidence_used must name fields that exist on the stored lead record, or the draft is rejected as ungrounded.

outreach_statusB

Counts by status and channel, plus remaining daily cap.

reconcile_outreachA

Settle sends stuck in sending by checking LinkedIn itself.

A sending row means the Send click happened but the outcome was never recorded — a crash, a killed browser, a disconnect. The message either went out or it did not, and only LinkedIn knows. This opens each lead's conversation, looks for our own message text, and resolves the row to sent or failed.

Sends nothing. Until reconciled, an ambiguous lead is treated as already-contacted, so the uncertainty can never produce a duplicate — it can only delay a legitimate follow-up.

check_repliesA

Read the Sales Navigator inbox and mark leads who replied.

Sends nothing. Reads structured message threads — a reply is a message whose author is the lead rather than you, matched to leads by the stable member_id, so nothing depends on parsing rendered text or guessing who spoke last.

Only leads this server recorded a send for are considered; a conversation with someone you messaged by hand elsewhere is left alone. A lead marked replied still counts as contacted, so a reply can never cause a duplicate first touch.

run_outreach_batchA

Draft and send for several leads in one call, unattended.

Uses MCP sampling: the server asks YOUR client for each draft, so no model runs here and no API key lives here — only the request for a completion. That is what lets a scheduled job run the loop without a person taking a turn.

Nothing is relaxed for automation. Every draft goes through the same send path as a manual one: the evidence gate, global dedupe, the daily cap, the free-channel-only default, and two-phase commit. dry_run still defaults to true, so the first call shows you what it would say and sends nothing.

Stops early when the daily cap is reached. A draft that fails to parse or fails validation is recorded and skipped rather than ending the run.

fetch_lead_profilesA

Fetch full profiles for a query's leads — depth 3, drafting material.

Same endpoint as enrich_leads, much wider projection: headline, summary, full position descriptions, educations, skills, languages, volunteering, connection counts. About 15 KB per lead against ~240 bytes for the enrichment screen.

Deliberately separate from enrich_leads. The screen runs across a whole list to find who is free to message; this runs only for the leads you are about to write to. Merging them would pull heavy payloads for leads you never contact, and would make "recent activity" as stale as the screen.

Requires ENABLE_PROFILE=true — it costs one heavy request per lead, so a default install will not do it.

Resumable: leads with a successful fetch are skipped, so calling repeatedly walks the query.

get_lead_profileA

Read one stored full profile — the payload you draft a message from.

Reads from the local store only; it does not call LinkedIn. Run fetch_lead_profiles first for leads that have not been fetched.

pipeline_statusA

One funnel view of a query: scraped → enriched → open → profiled → sent.

State otherwise lives across four tables; this joins it so "where is everything?" is one call instead of mental arithmetic.

Prompts

Interactive templates invoked by user choice

NameDescription
sales_nav_compose_messageDraft a personalized Sales Navigator message for one lead, using your own offer file. Refuses to render if OFFER_FILE is not set.
sales_nav_search_workflowPlaybook for a prospecting run with this server: verify the session, run a Sales Navigator search URL, then sample or export the saved records.

Resources

Contextual data attached and managed by the client

NameDescription
saved_queriesEvery saved Sales Navigator search and its progress (url_hash, url, scraper_type, status, last_page, total_available, records_count). Attach this to see what is already in the local store before deciding to search again.

Latest Blog Posts

MCP directory API

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

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nick-choudhary/linkedin-sales-nav-mcp'

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