{
  "markdown": "<div align=\"center\">\n\n# 🔗 LinkedIn MCP\n\n### LinkedIn for AI assistants — structured data via a real, stealth browser session\n\n[![CI](https://github.com/devag7/linkedin-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/devag7/linkedin-mcp/actions/workflows/ci.yml)\n[![npm version](https://img.shields.io/npm/v/linkedin-mcp-tools?color=cb0000&logo=npm)](https://www.npmjs.com/package/linkedin-mcp-tools)\n[![MIT License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.8-blue?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)\n[![MCP](https://img.shields.io/badge/MCP-Compatible-purple?logo=anthropic&logoColor=white)](https://modelcontextprotocol.io/)\n[![Glama score](https://glama.ai/mcp/servers/devag7/linkedin-mcp/badges/score.svg)](https://glama.ai/mcp/servers/devag7/linkedin-mcp)\n\n**Give Claude, Cursor, and any MCP client access to LinkedIn — profiles, people/job/company search, feed, messaging, and your network — as clean structured JSON.**\n\n**22 tools** · reads + **gated writes** (connect, message, post, react, comment) · a real **safety layer** (daily caps, human pacing, circuit breaker) · **166 tests**.\n\n> ⚠️ Automating LinkedIn violates its User Agreement and can get an account restricted. **No tool is ban-proof — and this one says so up front.** Use a secondary account; read [Account safety](#-account-safety) and [DISCLAIMER.md](DISCLAIMER.md) first.\n\n</div>\n\n---\n\n## Why this exists\n\nLinkedIn's internal **Voyager API** (the one its own web app uses) returns rich, structured JSON — but it sits behind **Cloudflare bot-management**, which rejects plain HTTP requests (a stateless `fetch` or `curl` gets stuck in an endless redirect, even with a valid cookie). The only reliable way to read LinkedIn data programmatically in 2026 is from inside a **real browser** that clears the challenge.\n\n**This project's approach:**\n\n1. Drive a real Chrome via [**patchright**](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright) (an undetected Playwright fork) so Cloudflare's challenge is solved with a genuine browser fingerprint.\n2. Query Voyager **from inside the authenticated page** — same-origin, the exact network path LinkedIn's own SPA uses → **structured JSON, not scraped DOM text**.\n\nThat last point is the edge over DOM-scraping tools: in-page API calls are **locale-independent and resilient to UI redesigns**, so they don't break on a moved CSS selector or a translated label.\n\n---\n\n## ✨ What's good here\n\n| | |\n|---|---|\n| 🧩 **Structured JSON** | In-page Voyager API calls return normalized data, shaped into compact objects — not brittle innerText scraping. |\n| ✍️ **Writes are API calls, not button-clicking** | `connect` / `message` / `post` / `react` / `comment` POST straight to Voyager — the **exact requests the web app sends, captured and verified live**. No hunting for a \"Connect\" button under a sticky navbar, no composer-dialog race. Every write returns a **structured status** (`ok` / `duplicate` / `already_connected` / `restricted` / `quota_exhausted` / …) — never a blind \"sent: true\". |\n| 🛡️ **Safety layer built in** | Serial queue, human-paced jittered delays, per-action **daily budgets**, account **warmup ramp**, and a **circuit breaker** that hard-stops on any checkpoint/captcha. (Risk reduction — *not* a safety guarantee.) |\n| 🔥 **One warm session** | A single persistent browser per process (cookies + Cloudflare clearance survive restarts). Explicit `close_session`, signal-handled teardown — no zombie Chrome. |\n| 🌍 **Locale-independent** | API + embedded-JSON parsing, not English-only DOM selectors — survives UI redesigns and translations. |\n| 🔒 **Local & private** | Session stored under `~/.linkedin-mcp/` with `0700/0600` perms; no cookies/tokens to paste, none ever logged. |\n\n---\n\n## How it compares\n\n| | DOM-scraping LinkedIn MCPs | **This** |\n|---|---|---|\n| Reads | scraped page text (brittle, locale-bound) | **structured API JSON** |\n| Writes (connect/message/post) | click rendered buttons (break on sticky navbars, dialog races, localized labels) | **direct Voyager `POST`, captured + verified live** |\n| Write feedback | \"clicked it\" → hope | **structured status** (ok / duplicate / restricted / quota_exhausted / …) |\n| Resilience | breaks on UI tweaks / translations | **API + embedded-JSON, locale-proof** |\n| Safety (caps, pacing, circuit breaker) | none | **✅ built-in, 166 tests** |\n| Zombie browser processes | common | **✅ reaped on close** |\n| Language | Python | TypeScript + official MCP SDK |\n\nWe hit LinkedIn's own API from inside the challenge-passed browser — reads *and*\nwrites — so you get the structured response and a real status, not parsed HTML\nand a hopeful click.\n\n## 📦 Status\n\n**Stable — v2, all 22 tools shipping.** Full transparency on exactly where every piece stands:\n\n| Area | State |\n|---|---|\n| Stealth browser engine (patchright) | ✅ built, **live-proven** |\n| In-page Voyager fetch (the core mechanism) | ✅ **live-verified** (returns structured JSON) |\n| Safety layer (queue / pacer / budgets / circuit-breaker) | ✅ built, 166 unit tests |\n| **Profile** — `get_profile`, `get_my_profile` (name, headline, summary, experience, education, skills, certifications, languages) | ✅ live-verified |\n| **Feed / notifications** — `get_feed`, `get_notifications` | ✅ live-verified |\n| **Jobs / messaging** — `search_jobs`, `get_job_details`, `get_inbox`, `get_conversation` | ✅ live-verified |\n| **People / companies** — `search_people`, `search_companies`, `get_company`, `get_company_posts`, `get_company_employees` (DOM fallback) | ✅ live-verified |\n| **Network** — `get_pending_invitations` (received + sent) | ✅ |\n| **Session** — `whoami`, `health_check` (live Voyager probe + budget headroom), `close_session` | ✅ |\n| **Write tools** — `connect_with_person`, `send_message`, `create_post`, `react_to_post`, `comment_on_post` | ✅ all 5 endpoints captured + live-verified on a burner; gated (`confirm:true` + daily caps), structured statuses. ⚠️ These take real, often irreversible actions — keep the gate on and use a throwaway account. |\n\n**22 tools.** typecheck + 166 tests green.\n\n**Login is headful, the server is headless.** The one-time `--login` opens a real\nChrome window (to clear Cloudflare and let you solve any captcha/2FA). After that\nthe persistent profile carries the clearance, so the server runs **headless** —\nverified returning live data. Use a **residential IP**; datacenter/VPN IPs are\noften pre-flagged by Cloudflare regardless of headless vs headful.\n\n---\n\n## 🚀 Quick start\n\n**1. Log in once** (opens a real Chrome window — sign in, solve any captcha/2FA):\n\n```bash\nnpx -y linkedin-mcp-tools@latest --login\n```\n\nNeeds Google Chrome installed (or run `npx patchright install chrome` once). Your\nsession — Cloudflare clearance and all — persists to `~/.linkedin-mcp/profile/`.\n\n**2. Point your MCP client at it.** Claude Desktop / Cursor / Claude Code config:\n\n```json\n{\n  \"mcpServers\": {\n    \"linkedin\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"linkedin-mcp-tools@latest\"]\n    }\n  }\n}\n```\n\nThen just ask: *\"Get my LinkedIn profile and summarize my experience\"* or *\"Find 5\nrecruiters at Google.\"*\n\n<details>\n<summary><b>From source / contributing</b></summary>\n\n```bash\ngit clone https://github.com/devag7/linkedin-mcp.git\ncd linkedin-mcp\nnpm install\nnpm run setup:browser     # installs the Chrome patchright drives\nnpm run login             # log in once\nnpm run spike             # verify: fetches your profile as JSON\nnpm run build             # produces dist/\n```\n\nMCP config: `\"command\": \"node\", \"args\": [\"/absolute/path/to/dist/index.js\"]`.\n</details>\n\n### Headless / server deployment\n\nThe one-time `--login` needs a window; the server then runs **headless** (verified\nreturning live data). Run `--login` on a machine with a display (or via VNC),\ncopy `~/.linkedin-mcp/profile/` to your server, and run there:\n\n```bash\nLINKEDIN_HEADLESS=true npx -y linkedin-mcp-tools@latest   # no display needed\n```\n\nUse a **residential IP** — datacenter/VPN IPs are frequently pre-flagged by\nCloudflare regardless of headless vs headful.\n\n---\n\n## 🛡️ Account safety\n\n**Read this.** Automating LinkedIn violates its User Agreement and **can get your account restricted or banned** — no tool can prevent that, including this one. The built-in safety features (daily caps, human pacing, warmup, circuit breaker) **reduce risk; they do not eliminate it.**\n\nDefaults err conservative:\n\n- Connections **20/day**, messages **50/day**, likes+comments **50/day** combined, follows **30/day** — combined write cap **150/24h**.\n- Profile views **80/day**, searches **30/day**.\n- New-account **warmup ramp** over the first weeks; **pending-invite ceiling** and **acceptance-rate** pauses.\n- Reads paced 4–12s apart, writes 45–150s, with long breaks and a working-hours gate.\n- A **circuit breaker** stops automatically on any checkpoint, captcha, or \"unusual activity\" page — and never tries to solve one.\n\n**Recommendations:** use a **secondary/throwaway account**, run from a **residential IP**, warm it up slowly. See [DISCLAIMER.md](DISCLAIMER.md) for the full legal/ToS notice.\n\n---\n\n## ⚙️ Configuration\n\n| Variable | Default | Description |\n|---|---|---|\n| `LINKEDIN_HEADLESS` | `true` | Server runs headless. `--login` always opens a real window regardless. Set `false` to watch the browser. |\n| `LINKEDIN_CHROME_PATH` | — | Explicit Chrome binary path (else patchright's). |\n| `LINKEDIN_PROFILE_DIR` | `~/.linkedin-mcp/profile` | Persistent browser profile. |\n| `LINKEDIN_IDLE_TIMEOUT_MS` | `300000` | Close the browser after this idle time (0 disables). |\n| `LINKEDIN_CONCURRENCY` | `1` | Serial by default; >1 is ban-risky. |\n| `TRANSPORT` | `stdio` | `stdio` (primary) or `http`. |\n\n---\n\n## 🛠 Development\n\n```bash\nnpm run dev          # run from source (stdio)\nnpm run typecheck\nnpm test             # vitest (safety layer + smoke)\nnpm run build\n```\n\n---\n\n## 📄 License\n\nMIT — see [LICENSE](LICENSE). Not affiliated with LinkedIn. Use at your own risk; see [DISCLAIMER.md](DISCLAIMER.md).\n\n<div align=\"center\">\n\n[![linkedin-mcp MCP server](https://glama.ai/mcp/servers/devag7/linkedin-mcp/badges/card.svg)](https://glama.ai/mcp/servers/devag7/linkedin-mcp)\n\nMade by [Dev Agarwalla](https://github.com/devag7)\n\n</div>\n",
  "bytes": 10344,
  "sha": "a4252494fa28876392299a7271eb9a34fe3592777e0b0c873dfd913a3fe3a87a",
  "repo_slug": "devag7/linkedin-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_devag7_linkedin_mcp_b8bb8f54/readme"
}