Skip to main content
Glama
ml-lubich

linkedin-mcp

by ml-lubich

linkedin-mcp

linkedin-mcp is an unofficial LinkedIn CLI and MCP server in one Python package. Every command and every MCP tool call the same shared core (linkedin_mcp/core.py), so the two surfaces never drift apart.

It consolidates two prior tools into one:

  • linkedin-cli (by frizynn, MIT) — the Voyager-API read/write surface: feed, search, profile, profile-posts, activity, post, react, unreact, save, unsave, comment. This repo forked that project and built on top of it.

  • linkedin-agent — the CDP surface that drives your own already-logged-in Chrome for messaging, referrals, and posting: doctor, classify, post-cdp, messages, referral. That project is now absorbed into this one.

It is built around a real LinkedIn web session (Voyager) or your own logged-in Chrome (CDP) — not OAuth. That makes it practical for personal automation, but session handling, browser behavior, and endpoint stability all matter.

What it does

Voyager API surface (a real session, requests/Playwright fallback):

  • Read the authenticated home feed, search people/posts, fetch a profile or its posts, inspect an activity, emit JSON for scripting.

  • Write: publish a post, react/unreact, save/unsave, comment — all through a Playwright browser-automation fallback.

CDP agent surface (your own already-open, already-logged-in Chrome, via own-chrome):

  • doctor — environment/session health check.

  • classify — is an inbound message hiring-shaped, excluded, already-referred?

  • post-cdp draft / post-cdp publish — lint-then-publish a feed post.

  • messages read / messages send — read/reply in the open thread, with an optional file attachment.

  • referral draft / referral send — draft/send a referral message with a resume attached, paced and deduped through a rate governor.

MCP server (linkedin-mcp serve): every command above as an MCP tool, for Claude/Cursor/any MCP client.

Related MCP server: linkedin-mcp

Confirm gate — nothing sends without it

Every write/send/publish command requires an explicit --confirm (CLI) or confirm: true (MCP tool). Two families, two mechanisms:

  • Voyager writes (post, react, unreact, save, unsave, comment) refuse instantly — ConfirmRequiredError, nothing touched — without it.

  • CDP agent writes (post-cdp publish, messages send, referral send) still fill the browser compose box/composer as a preview, then refuse to click Send/Post — SendNotConfirmedError — without it.

Installation

git clone https://github.com/ml-lubich/linkedin-mcp.git
cd linkedin-mcp
uv tool install --force --from . linkedin-mcp

Installs two identical console scripts, linkedin and linkedin-mcp. If you previously had the standalone tools installed, remove them so their command names don't shadow this one:

uv tool uninstall linkedin-cli
uv tool uninstall linkedin-agent

Install Playwright's browser if you use the Voyager write fallback:

uv run playwright install chromium

Quick start (Voyager side)

export LINKEDIN_COOKIE_HEADER='li_at=...; JSESSIONID="ajax:..."; ...'
linkedin auth-status
linkedin feed --max 10
linkedin profile satyanadella
linkedin search "AI engineer" --max 10

Quick start (CDP agent side)

Chrome must be listening on its debugging port (default 9222); quit Chrome fully first, then (macOS, since Chrome 136+ ignores the flag on the default profile):

open -a "Google Chrome" --args --remote-debugging-port=9222 --user-data-dir="$HOME/chrome-debug"
linkedin doctor                                    # environment/session check
linkedin messages read --limit 20                  # read the open thread
linkedin messages send "thanks, that works" --confirm
linkedin post-cdp draft "shipped a small thing this week"   # anti-cringe lint, no browser
linkedin post-cdp publish "shipped a small thing this week" --confirm

Config for the CDP side lives at ~/.config/linkedin-agent/config.toml (unchanged from linkedin-agent — copy config.example.toml from that repo). It holds the CDP port, your display name, the referral identity, and exclusion lists. Nothing personal is hardcoded here.

MCP server

linkedin-mcp serve   # stdio transport

Claude Code / Cursor config:

{
  "mcpServers": {
    "linkedin": { "command": "linkedin-mcp", "args": ["serve"] }
  }
}

21 tools are exposed, one per CLI command (dashes/spaces -> underscores), except serve (starts the server itself) and auth env (the one command that reads a raw cookie value back out — never exposed as a tool; capture the session with the auth_capture tool or linkedin auth capture instead). tests/test_mcp_parity.py fails the build if a command and its tool ever drift apart.

Authentication (Voyager side)

Resolved in this order:

  1. LINKEDIN_COOKIE_HEADER (most reliable)

  2. LINKEDIN_LI_AT + LINKEDIN_JSESSIONID

  3. Browser cookie extraction (Chrome, Chromium, Brave, Edge, Firefox)

  4. linkedin auth capture — CDP-based, for Chrome 127+, where its app-bound cookie encryption blocks #3. Polls a CDP-attached Chrome until logged in, then saves the cookie to ~/.config/linkedin-mcp/cookies (mode 0600). Never prints a cookie value. linkedin auth env is the one command that does, deliberately, to export LINKEDIN_COOKIE_HEADER.

export LINKEDIN_LI_AT='AQ...'
export LINKEDIN_JSESSIONID='"ajax:123456789"'
export LINKEDIN_BROWSER='chrome'
export LINKEDIN_HEADLESS='1'
export LINKEDIN_PROXY='http://127.0.0.1:7890'
export LINKEDIN_CONFIG="$PWD/config.yaml"

Commands

linkedin auth-status
linkedin auth capture
linkedin auth env
linkedin feed --max 20 --json
linkedin search "product manager" --max 10
linkedin profile satyanadella --json
linkedin profile-posts satyanadella --max 20
linkedin activity urn:li:activity:123
linkedin post "hello from linkedin-mcp" --confirm
linkedin react urn:li:activity:123 --type like --confirm
linkedin unreact urn:li:activity:123 --confirm
linkedin save urn:li:activity:123 --confirm
linkedin unsave urn:li:activity:123 --confirm
linkedin comment urn:li:activity:123 "nice post" --confirm
linkedin doctor
linkedin classify "InMail: Senior AI Engineer role" --name "Jordan Lee"
linkedin post-cdp draft "..."
linkedin post-cdp publish "..." --confirm
linkedin messages read --limit 40
linkedin messages send "..." --confirm
linkedin referral draft "Jordan Lee" "..." --headline "Talent @ Acme"
linkedin referral send "Jordan Lee" "<thread url>" --confirm
linkedin-mcp serve

Skill

This repo ships one Codex/Claude skill in skills/linkedin-mcp/ covering command selection, the confirm gate, auth troubleshooting, and write workflows for both surfaces.

Configuration (Voyager side)

The repository includes a sample config.yaml:

fetch:
  count: 20

filter:
  enabled: false
  mode: "recent"

browser:
  preferred: "chrome"
  fallback_enabled: true
  headless: true

rate_limit:
  request_delay: 1.25
  max_retries: 3
  retry_base_delay: 3.0
  write_delay_min: 1.5
  write_delay_max: 4.0
  timeout: 20.0

Development

uv sync --extra dev
uv run playwright install chromium

Run checks (see docs/TESTING.md for the full gate):

uv run ruff check .
uv run pytest -q --cov=linkedin_mcp

Important notes

  • Unofficial, not affiliated with LinkedIn.

  • LinkedIn can change internal web endpoints without notice.

  • Session cookies are credentials. Treat them like passwords — never commit them, print them, or paste them into an issue/PR.

  • Never invent a referral target, resume, or pitch — they come only from config/env vars.

  • Do not use this for spam, scraping at abusive rates, or automating repeated posting/engagement loops.

Security and Privacy

See SECURITY.md for reporting guidance.

Contributing

Before opening a pull request, read CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SECURITY.md.

License

MIT. See LICENSE. Portions of this project originate from frizynn/linkedin-cli (MIT).

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables LinkedIn API integration for managing profiles, posts, feed, connections, and sending messages through MCP-compatible clients.
    10
    10 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for AI-native LinkedIn prospecting. It enables lead research, audience building, conversation management, and controlled outreach actions such as messaging and publishing through an OAuth-protected remote endpoint.
    2
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables MCP-compatible clients to read LinkedIn profiles, companies, and jobs, and to send connection requests after explicit confirmation, using interactive browser-based authentication instead of stored credentials.
    8
    MIT