Typed, policy-enforced Python MCP server for authorized LinkedIn visible-UI capabilities
claude mcp add linkedin -- uvx linkedin-mcp{
"mcpServers": {
"linkedin": {
"command": "uvx",
"args": ["linkedin-mcp"]
}
}
}MCP Servers overview
# LinkedIn MCP Server
<!-- mcp-name: io.github.prakharagarwal-dev/linkedin-mcp-server -->
[](https://github.com/prakharagarwal-dev/linkedin-mcp-server/actions/workflows/ci.yml)
[](https://github.com/prakharagarwal-dev/linkedin-mcp-server/actions/workflows/codeql.yml)
[](https://pypi.org/project/linkedin-mcp-local/)
[](https://www.python.org/)
[](LICENSE)
A standalone Python MCP server that exposes narrow, typed LinkedIn capabilities
through the visible LinkedIn web UI.
> [!IMPORTANT]
> This is an unofficial, beta project. It is not affiliated with, endorsed by,
> or sponsored by LinkedIn. LinkedIn is a trademark of LinkedIn Corporation.
> Visible-UI automation can stop working when LinkedIn changes its interface and
> may cause checkpoints, restrictions, or other account consequences. You are
> responsible for complying with applicable terms, laws, consent requirements,
> and organizational policies. Do not use this project for spam, deceptive
> activity, high-volume extraction, or bypassing access controls.
This repository is the LinkedIn harness, not an agent runtime. LangGraph,
schedulers, ranking, memory, and natural-language planning belong in clients
that call this server. Agents never receive cookies, arbitrary browser control,
generic navigation, JavaScript execution, or unrestricted network access.
Version `0.14.1` has no database, migration, Docker-service, keyring, or
application-state dependency. It uses one local Playwright Chromium profile to
preserve the LinkedIn login and keeps capability execution state only for the
lifetime of one server process.
## Runtime model
```text
LangGraph / Codex / another MCP client
|
stdio or loopback HTTP
|
typed MCP capabilities
|
bounded asyncio.Queue (one worker)
|
policy -> executor -> page objects
|
one persistent Playwright context
|
visible linkedin.com surfaces
```
The server owns:
- official MCP Python SDK transport and typed Pydantic contracts;
- one bounded in-process queue and one capability worker;
- one account-scoped persistent Playwright Chromium context;
- internal navigation pacing and per-operation safety bounds;
- exact-host, surface, scope, and effect authorization;
- visible page extraction and field-level evidence;
- expiring, filter-bound continuation cursors for collection reads;
- immutable prepare/confirm/execute envelopes for writes;
- process-local request replay, evidence, action drafts, and idempotency.
It has no dependency on LangGraph, Temporal, `startup-scanner`, PostgreSQL,
RabbitMQ, Redis, or another LinkedIn MCP implementation.
## What survives a restart
| Data | Location | Lifetime |
| --- | --- | --- |
| LinkedIn cookies and browser preferences | local Chromium profile | across restarts |
| Managed Chromium binaries | local Playwright browser cache | across package environments |
| Explicit post/message assets | configured local asset directory | user managed |
| Calls and request replay | memory | current process only |
| Evidence resources | memory | current process only |
| Action drafts and attempts | memory | current process only |
| Execution idempotency keys | memory | current process only |
| Queue and pacing history | memory | current process only |
| Collection cursors, seen identities, and invitation snapshots | memory | current process only |
The browser profile is sensitive authentication material. Its directory is
created with owner-only permissions on supported POSIX systems. Never commit,
copy, log, or share it.
Because operation state is intentionally ephemeral:
- read retries deduplicate only while the same server process is alive;
- `linkedin://sources/{source_id}` must be read before that process exits;
- a prepare and its matching execute call must use the same process;
- after a hard process interruption during a write, inspect LinkedIn's visible
state before preparing any new action. Never blindly retry the old execute
request.
LangGraph should checkpoint workflow history, cross-run deduplication,
notifications, rankings, and conversations outside this server.
## MCP surface
| MCP primitive | Purpose |
| --- | --- |
| `linkedin.server.status` | Non-secret runtime metadata |
| `linkedin.capabilities.list` | Installed capabilities and policy status |
| `linkedin.session.status` | Browser setup, profile, authentication, and pause state |
| `linkedin.jobs.search` | Cursor-paged current Jobs search with optional keywords, Any time by default, and every current account-visible filter |
| `linkedin.jobs.get` | Expanded JD, header metadata, application method, and hiring team for a numeric job ID |
| `linkedin.people.search` | Bounded People search with every current account-visible filter |
| `linkedin.people.get` | Selected or all visible member-profile sections |
| `linkedin.companies.search` | Cursor-paged Company search with keywords and every current native filter: headquarters, industry, all eight size buckets, job listings, and first-degree connection presence |
| `linkedin.companies.get` | Exact Company Overview plus About, including all visible structured About fields and field evidence |
| `linkedin.posts.search` | Post search with every current visible filter, including live videos, followed authors, and Author Keywords |
| `linkedin.posts.get` | Exact post read with fully expanded text, typed current media/link/poll variants, engagement and visibility, field evidence, completeness coverage, and bounded repost-original resolution |
| `linkedin.posts.comments.list` | Top-level comments and nested replies |
| `linkedin.posts.create.prepare` / `.execute` | Nine current personal composer modes: text/link, edited images, video, document, poll, celebration, event, existing-job hiring, and expert request; plus audience/group, comment control, brand partnership, eligible collaborators, and scheduling |
| `linkedin.posts.comment.prepare` / `.execute` | Top-level comment or exact-thread reply with text/emoji/link, exact mentions, one photo, or one exact GIF |
| `linkedin.posts.reaction.prepare` / `.execute` | Set, change, remove, or no-op any current post/comment reaction: Like, Celebrate, Support, Love, Insightful, or Funny |
| `linkedin.invitations.list` | Exact sent view or deduplicated union of every current received invitation view |
| `linkedin.connections.list` | Cursor-page and sort the existing first-degree connection inventory |
| `linkedin.connections.search` | Search established first-degree connections with first-degree enforced by the server |
| `linkedin.invitations.send.prepare` / `.execute` | Connection invitation with optional note |
| `linkedin.invitations.accept.prepare` / `.execute` | Accept an exact received invitation |
| `linkedin.invitations.ignore.prepare` / `.execute` | Ignore an exact received connection request |
| `linkedin.messaging.search` | Cursor-paged recipient/message-keyword search across Focused, Other, Archived, or Spam with exactly one optional Jobs, Unread, Connections, InMail, or Starred filter |
| `linkedin.messaging.conversation.get` | Bounded reverse-virtualized one-to-one history with incoming/outgoing messages, visible attachments, replies, edits, reactions, and explicit completeness |
| `linkedin.messaging.message.prepare` / `.execute` | Exact-recipient text/emoji, current desktop image/file, exact KLIPY GIF, or exact-message reply with hash-locked confirmation and visible postconditions |
| `linkedin://sources/{source_id}` | Evidence captured by the current process |
Every operation accepts a caller-owned `context_id` and `request_id`. Direct
detail reads do not require a prior search. The server constructs bounded,
canonical LinkedIn targets from validated job IDs, profile slugs, company
slugs, post references, comment references, and conversation references.
### Collection pagination
Every LinkedIn search or list tool accepts `page_size` (1–100) and an optional
opaque `cursor`. Omit `cursor` for the first page, then copy
`pagination.next_cursor` into the next call with a new `request_id`. A terminal
page has `pagination.has_more=false`.
Cursors are process-local, single-use, expire after 15 minutes by default, and
are bound to the account, capability, and semantic filters that created them.
Changing `page_size` between pages is allowed; changing the search target,
query, sort, direction, or filters is rejected as `invalid_cursor`. The server
rescans a bounded live prefix and removes stable identities already returned,
so `consistency=live_deduplicated` prevents duplicates but does not claim a
frozen LinkedIn snapshot. `truncated=true` means an internal safety or cursor
state bound ended the scan and no further cursor is issued.
`linkedin.invitations.list` uses a stronger contract. A single-filter call
captures and exactly reconciles that view against LinkedIn's visible count.
Received `all` is server-defined because the latest UI has no reliable All
control: it reconciles Focused, Other, Verified, Mutual Connections, Your
Company, and Your School separately, then deduplicates their stable invitation
identities. Coverage reports the per-view counts, their membership sum, the
overlap removed, and the exact unique snapshot count. Continuations slice that
immutable process-local snapshot without reopening LinkedIn and report
`consistency=captured_snapshot`. A quiet list, physical bottom, loader state,
or end message can never substitutWhat people ask about linkedin-mcp-server
What is prakharagarwal-dev/linkedin-mcp-server?
+
prakharagarwal-dev/linkedin-mcp-server is mcp servers for the Claude AI ecosystem. Typed, policy-enforced Python MCP server for authorized LinkedIn visible-UI capabilities It has 0 GitHub stars and was last updated today.
How do I install linkedin-mcp-server?
+
You can install linkedin-mcp-server by cloning the repository (https://github.com/prakharagarwal-dev/linkedin-mcp-server) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is prakharagarwal-dev/linkedin-mcp-server safe to use?
+
prakharagarwal-dev/linkedin-mcp-server has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.
Who maintains prakharagarwal-dev/linkedin-mcp-server?
+
prakharagarwal-dev/linkedin-mcp-server is maintained by prakharagarwal-dev. The last recorded GitHub activity is from today, with 0 open issues.
Are there alternatives to linkedin-mcp-server?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy linkedin-mcp-server to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/prakharagarwal-dev-linkedin-mcp-server)<a href="https://claudewave.com/repo/prakharagarwal-dev-linkedin-mcp-server"><img src="https://claudewave.com/api/badge/prakharagarwal-dev-linkedin-mcp-server" alt="Featured on ClaudeWave: prakharagarwal-dev/linkedin-mcp-server" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
The fastest path to AI-powered full stack observability, even for lean teams.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!