LinkedIn MCP Server

LinkedIn MCP Server

Enables natural language interaction with LinkedIn, including profile retrieval, job searching, messaging, and post engagement.

Category
访问服务器

README

LinkedIn MCP Server (Fork)

Personal fork of stickerdaniel/linkedin-mcp-server with additional tools for messaging and post engagement.

Added Tools

Tool Description
send_message Send a LinkedIn message to a 1st-degree connection
send_connection_request Send a connection request, with or without a note
follow_company Follow a LinkedIn company page
get_inbox Read recent inbox conversations (supports unread_only)
get_conversation Read the full message thread with a specific person
get_post_likers Get the list of people who reacted to a LinkedIn post
get_last_post Get the most recent organic post from a person's profile

Detail Mode

All page-scraping tools (get_person_profile, search_people, get_company_profile, get_company_posts, get_job_details, search_jobs) accept a detail parameter:

  • "basic" (default) — truncates each section's raw text to BASIC_SECTION_MAX_CHARS (2000 chars). LinkedIn front-loads the most important content (name, headline, location, about), so this captures essentials while staying well within LLM context limits. References, job IDs, and post URNs are always kept.
  • "full" — returns the complete raw page text, current behaviour.

If basic mode doesn't return enough information, call the tool again with detail="full".

The truncation limit is a single constant in linkedin_mcp_server/tools/utils.py:

BASIC_SECTION_MAX_CHARS = 2000

All Tools

People

Tool Description
get_person_profile Get profile info with optional sections: experience, education, interests, honors, languages, contact_info, posts. Supports detail param.
search_people Search for people by keywords and optional location. Supports detail param.
get_last_post Get the most recent organic post from a person (visits profile first, then Posts activity tab; returns text, timestamp, URL, and URN)
send_connection_request Send a connection request, with or without a note (~300 char limit); handles profiles where Connect is in the More dropdown
send_message Send a message to a 1st-degree connection (also used to reply to existing threads)
follow_person Follow a person's profile
check_follow Check whether you are following a person
check_connection Check whether you are connected to a person

Companies

Tool Description
get_company_profile Get company info with optional sections: posts, jobs. Supports detail param.
get_company_posts Get recent posts from a company's feed; returns post URNs plus lightweight posts[] metadata including posted_at. Supports detail param.
follow_company Follow a company page
check_follow_company Check whether you are following a company

Jobs

Tool Description
search_jobs Search for jobs by keywords and optional location. Supports detail param.
get_job_details Get full details of a specific job posting. Supports detail param.

Messaging

Tool Description
get_inbox List recent inbox conversations with name, preview, timestamp, and unread flag; pass unread_only=true to filter
get_conversation Read the full message thread with a person by their LinkedIn username

Posts

Tool Description
get_post_likers Get the list of people who reacted to a post (by feed URL or post URN)
get_last_post Get the most recent organic post from a person (no likes, no reshares)

Session

Tool Description
close_session Close the browser session and clean up resources

Setup

Prerequisites: Python 3.12+ and uv installed

# 1. Clone the repo
git clone https://github.com/pauling-ai/linkedin-mcp-server
cd linkedin-mcp-server

# 2. Install dependencies
uv sync

# 3. Log in (first time only)
uv run -m linkedin_mcp_server --login

This opens a browser for you to log in manually (5 minute timeout for 2FA, captcha, etc.). The browser profile is saved to ~/.linkedin-mcp/profile/ and persists across sessions.

Installing into another project

To use this server from another Python project or Claude Code workspace, install it in editable mode pointing at your local clone:

# With uv (recommended)
uv pip install -e /path/to/linkedin-mcp-server

# Or with pip
pip install -e /path/to/linkedin-mcp-server

Editable mode means changes to the repo are immediately reflected — no reinstall needed.

Then point your MCP config at the installed binary:

# Find the installed binary path
which linkedin-scraper-mcp

Claude Code / MCP Configuration

After installing (either in a project venv or globally), add to your .mcp.json:

{
  "mcpServers": {
    "linkedin": {
      "command": "/path/to/venv/bin/linkedin-scraper-mcp",
      "args": ["--project-auth", "--delay-between-linkedin-calls", "1.5", "--delay-jitter", "0.5"],
      "env": {
        "LOG_LEVEL": "INFO"
      }
    }
  }
}

Or run directly from the repo with uv (no install needed):

{
  "mcpServers": {
    "linkedin": {
      "command": "uv",
      "args": ["--directory", "/path/to/linkedin-mcp-server", "run", "-m", "linkedin_mcp_server", "--project-auth", "--delay-between-linkedin-calls", "1.5", "--delay-jitter", "0.5"],
      "env": {
        "LOG_LEVEL": "INFO"
      }
    }
  }
}

The uv approach is the simplest — just update the --directory path and you're done.

Use --slow-mo only when debugging or when you want to watch browser actions happen more slowly. For LinkedIn-facing pacing between tool calls, prefer --delay-between-linkedin-calls / --delay-jitter. The smaller --human-delay-min-ms / --human-delay-max-ms settings still control waits inside individual browser workflows.

If you want a separate LinkedIn account per repo on the same machine, start the server with --project-auth. That stores the auth state under the current project in .linkedin-mcp-server/ instead of the shared ~/.linkedin-mcp/ location.

CLI Options

  • --login - Open browser to log in and save persistent profile
  • --logout - Clear stored LinkedIn browser profile
  • --status - Check if current session is valid and exit
  • --no-headless - Show browser window (useful for debugging)
  • --project-auth - Store auth under the current project at .linkedin-mcp-server/
  • --slow-mo MS - Debugging aid: slows all browser actions uniformly in ms (default: 0)
  • --human-delay-min-ms MS - Minimum randomized delay between LinkedIn actions (default: 500)
  • --human-delay-max-ms MS - Maximum randomized delay between LinkedIn actions (default: 2000)
  • --delay-between-linkedin-calls SECONDS - Baseline delay before each LinkedIn MCP tool call (default: 1.5)
  • --delay-jitter SECONDS - Random jitter added/subtracted from tool-call delay (default: 0.5)
  • --delay-distribution {uniform,beta,lognormal} - Shape of randomized delays (default: beta)
  • --linkedin-cache-dir PATH - Override cache root (default: beside auth profile)
  • --disable-linkedin-cache - Disable LinkedIn tool result caching
  • --profile-cache-ttl-hours HOURS - TTL for cached person profiles (default: 720 / 30 days)
  • --no-reading-time - Disable reading-time pauses after page extraction
  • --reading-time-wpm WPM - Simulated reading speed in words-per-minute (default: 800)
  • --reading-time-jitter PERCENT - Jitter percentage for reading-time pauses (default: 30)
  • --reading-time-max SECONDS - Maximum reading-time pause in seconds (default: 45)
  • --log-level {DEBUG,INFO,WARNING,ERROR} - Logging level (default: WARNING)
  • --timeout MS - Browser timeout for page operations in ms (default: 5000)
  • --transport {stdio,streamable-http} - Transport mode (default: stdio)

Troubleshooting

Patchright browser cache: The server owns Patchright setup by default. On startup it sets PLAYWRIGHT_BROWSERS_PATH=~/.linkedin-mcp/patchright-browsers, sets PLAYWRIGHT_SKIP_BROWSER_GC=1, and idempotently runs python -m patchright install chromium. This makes separate terminals, cron jobs, uvx runs, and long-running automations independent of shell state and prevents unrelated Playwright/Patchright installs from garbage-collecting the browser revision. Override PLAYWRIGHT_BROWSERS_PATH if you need a custom cache, or set LINKEDIN_PATCHRIGHT_AUTO_INSTALL=0 to disable startup install.

Derived runtime profiles: Foreign runtimes reuse committed derived profiles by default, so server restarts do not re-bridge/rebuild the browser profile every time. Set LINKEDIN_PERSIST_DERIVED_SESSION=0 for legacy fresh-bridge behavior, or LINKEDIN_DEBUG_BRIDGE_EVERY_STARTUP=1 when intentionally debugging bridging.

Session expired: Run uv run -m linkedin_mcp_server --login again.

Login issues: LinkedIn may require confirmation in the mobile app, or show a captcha — the --login browser window lets you handle these manually.

Scraping issues: Use --no-headless to watch the browser and --log-level DEBUG for detailed logs.

Timeout issues: Increase with --timeout 10000 or env var TIMEOUT=10000.

Tool-call pacing: Tune with --delay-between-linkedin-calls / --delay-jitter or env vars LINKEDIN_CALL_DELAY_MS / LINKEDIN_CALL_DELAY_JITTER_MS. Defaults are 1.5 ± 0.5 seconds, so each LinkedIn MCP tool call starts after roughly 1-2 seconds.

In-tool pacing: Tune with --human-delay-min-ms / --human-delay-max-ms or env vars HUMAN_DELAY_MIN_MS / HUMAN_DELAY_MAX_MS. These are smaller pauses inside a tool workflow, e.g. after navigation or clicks.

Delay distribution: By default, randomized delays use a beta distribution (right-skewed) instead of a flat uniform distribution. This means most delays cluster toward the shorter end of the configured range, with occasional longer pauses — a pattern that's mathematically much harder for bot detectors to fingerprint. Use --delay-distribution uniform or DELAY_DISTRIBUTION=uniform to restore the old flat distribution. lognormal is also available for a classic human reaction-time model.

Reading-time simulation: After extracting page content, the scraper pauses proportionally to text length to simulate skimming. This makes the scraper's time-on-page correlate with content length, which looks more human to LinkedIn's behavioral analysis. Defaults are 800 WPM with ±30% jitter and a 45-second hard cap. Tune with --reading-time-wpm, --reading-time-jitter, --reading-time-max, or env vars READING_TIME_WPM, READING_TIME_JITTER_PCT, READING_TIME_MAX_SECONDS. Use --no-reading-time or READING_TIME_ENABLED=false to disable.

Scrolling behavior: The scraper simulates human-like scrolling via mouse wheel events rather than instant window.scrollTo jumps. Scroll distances are variable, occasionally include small upward corrections (overshoot/re-reading), and use non-uniform pauses between scroll steps. This triggers LinkedIn's lazy loaders and intersection observers more naturally than mechanical scrolling.

Mouse movement: The scraper replaces Playwright's default locator.click() (which teleports the mouse to the exact element center with no mousemove events) with curved quadratic Bezier paths that generate 5–10 mousemove events before every click. This includes variable speed, occasional overshoot-and-correction, and random target offsets within the element. Idle mouse micro-movements are also added during page reading time to maintain nonzero mouse event density.

Profile caching: get_person_profile caches raw profile scrape results for 720 hours by default. The cache is shared across sessions beside the auth profile: ~/.linkedin-mcp/cache/profiles/ by default, or .linkedin-mcp-server/cache/profiles/ when using --project-auth. Use force_refresh=true on the tool call to bypass cache for one profile. Requests that include the posts section are not cached, so competitor post discovery stays fresh. Use --profile-cache-ttl-hours, --linkedin-cache-dir, or --disable-linkedin-cache to tune globally. Env vars: LINKEDIN_PROFILE_CACHE_TTL_HOURS, LINKEDIN_CACHE_DIR, LINKEDIN_CACHE_DISABLED.

slow_mo vs pacing delays: --slow-mo / SLOW_MO is mainly for debugging because it slows nearly every browser action. Prefer the tool-call and in-tool pacing settings for normal runs.

Per-project LinkedIn accounts: Use --project-auth or env var PROJECT_AUTH=true. The login flow will then create:

  • .linkedin-mcp-server/profile/ for the persistent browser profile
  • .linkedin-mcp-server/cookies.json
  • .linkedin-mcp-server/source-state.json
  • .linkedin-mcp-server/runtime-profiles/ for derived runtime sessions

send_message / get_conversation not finding the Message button: The target user must be a 1st-degree connection. The tool returns an error with diagnostic info if the button isn't found.

send_connection_request not finding the Connect button: The user may already be a connection, have a pending request, or not allow connection requests. If Connect is hidden behind a More dropdown, the tool handles this automatically.

Notes

  • Browser profile stored at ~/.linkedin-mcp/profile/
  • Tool calls are serialized — concurrent requests queue rather than run in parallel
  • Use in accordance with LinkedIn's Terms of Service

License

Apache 2.0 — see LICENSE

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选