LinkedIn MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@LinkedIn MCP ServerGet my LinkedIn profile"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
LinkedIn MCP Server
Complete LinkedIn automation toolkit. Scrape profiles, manage posts, read any LinkedIn content, and automate interactions via MCP (Model Context Protocol).
๐ Table of Contents
Overview
linkedin-mcp is a fully featured MCP server that provides automation tools for LinkedIn.
It supports browser-based scraping and API-based operations for content management, media uploads, and reactions.
Repository: Linkedin MCP Server
Features
๐ Scraping (Browser-Based)
Extract full LinkedIn profiles
Scrape company pages
Read job listings
Read ANY LinkedIn post
Extract images, videos, engagement metrics
๐ API-Based Post Management
Create, update, delete LinkedIn posts
Add or remove reactions
Upload images and documents
Supports all official LinkedIn REST API features
๐งฉ MCP Integration
Works with Claude Desktop and any MCP-compatible client
17 total tools included
๐งช Testing
50+ tests
Covers scraping, API, and MCP tools
Quickstart
Install
git clone https://github.com/selvin-paul-raj/Linkedin-MCP-Server.git
cd Linkedin-MCP-Server
# create environment config
cp .env.example .env
# install dependencies
pip install -e .Run
# Standard MCP server
uv run linkedin-mcp
# Debug mode (shows browser)
uv run main.py --debug --no-headless --no-lazy-init
# HTTP mode
uv run main.py --transport streamable-httpAuthentication
Related MCP server: LinkedIn MCP Pro Max
1. Scraping (LinkedIn Cookie)
Get your li_at cookie:
Log in to LinkedIn in Chrome
Press F12
Application โ Cookies โ https://www.linkedin.com
Copy the
li_atcookie valueAdd to
.env:
LINKEDIN_COOKIE=li_at=YOUR_COOKIE_VALUE2. API (OAuth Access Token)
Add these fields to .env:
LINKEDIN_CLIENT_ID=your_id
LINKEDIN_CLIENT_SECRET=your_secret
LINKEDIN_ACCESS_TOKEN=your_access_token
LINKEDIN_API_VERSION=202510Quick OAuth Link
https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=w_member_social%20r_liteprofile%20r_emailaddressExchange auth code:
curl -X POST https://www.linkedin.com/oauth/v2/accessToken \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=YOUR_CODE" \
-d "redirect_uri=YOUR_REDIRECT_URI" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"Usage
Read any LinkedIn post
{
"tool": "read_linkedin_post",
"input": "https://www.linkedin.com/posts/...activity-123456..."
}Create a post
{
"tool": "create_linkedin_post",
"input": {
"text": "Excited to announce our new product launch! ๐",
"visibility": "PUBLIC"
}
}Upload image
{
"tool": "upload_linkedin_image",
"input": { "image_url": "https://example.com/image.jpg" }
}Claude Desktop Integration
Add this to claude_desktop_config.json:
{
"mcpServers": {
"linkedin": {
"command": "uv",
"args": [
"--directory",
"D:\\MCP\\linkedin-mcp",
"run",
"linkedin-mcp"
],
"env": {
"LINKEDIN_COOKIE": "li_at=YOUR_COOKIE",
"LINKEDIN_ACCESS_TOKEN": "YOUR_TOKEN"
}
}
}
}Available Tools
๐ Content Reading
read_linkedin_post
๐ Scraping
get_person_profileget_company_profileget_job_detailssearch_jobssearch_recommended_jobsclose_session
๐ Post Management
create_linkedin_postupdate_linkedin_postdelete_linkedin_post
๐ผ๏ธ Media
upload_linkedin_imageget_linkedin_image
๐ Reactions
add_linkedin_reactionremove_linkedin_reactionget_linkedin_reactions
๐ค Profile & Auth
get_linkedin_profilevalidate_linkedin_credentials
More details. See TOOLS_REFERENCE.md.
Project Structure
linkedin-mcp/
โโโ linkedin_mcp_server/
โ โโโ server.py
โ โโโ cli.py
โ โโโ config/
โ โโโ drivers/
โ โโโ tools/
โโโ tests/
โ โโโ unit/
โ โโโ integration/
โโโ scripts/
โโโ .env.example
โโโ pyproject.toml
โโโ README.md
โโโ TOOLS_REFERENCE.mdTesting
# unit tests
uv run pytest tests/unit -v
# integration tests
uv run pytest tests/integration -v
# all tests
uv run pytest tests/ -vQuick API test:
uv run python scripts/test_api.pyTroubleshooting
โ "426 Client Error: Upgrade Required"
Fix:
LINKEDIN_API_VERSION=202510โ "LINKEDIN_COOKIE required"
Get fresh cookie from Chrome.
โ "401 Unauthorized"
Generate a new access token.
ChromeDriver issues
pip install --upgrade selenium webdriver-managerAPI Versioning
Current default:
202510Check latest: https://learn.microsoft.com/en-us/linkedin/marketing/versioning
Update:
LINKEDIN_API_VERSION=202511Restart the server.
Contributing
git clone https://github.com/selvin-paul-raj/Linkedin-MCP-Server.git
cd Linkedin-MCP-Server
uv sync
uv run pytest tests/ -v
uv run ruff format .
uv run pre-commit run --all-filesPull requests welcome.
License
MIT License.
See the LICENSE file.
Disclaimer
This tool is for educational and automation purposes. Follow LinkedIn TOS, API terms, and usage limits. Use responsibly.
Built with โค๏ธ for LinkedIn automation
Available Tools
6 toolsclose_sessionA
Close the current browser session and clean up resources.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must disclose behavioral traits. It mentions resource cleanup but does not specify irreversibility, side effects (e.g., cookies cleared), or error conditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one short sentence that conveys the essential purpose without extraneous words. It is appropriately front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with zero parameters and an output schema, the description adequately explains the action and cleanup. No further context is necessary.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so schema coverage is 100%. The description does not need to add parameter detail; the baseline of 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Close') and the resource ('current browser session') with additional context ('clean up resources'). It is distinct from sibling tools which are all retrieval operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use versus alternatives. The use case is implied (ending a session), but no 'when not to use' or prerequisite information is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_company_profileA
Get a specific company's LinkedIn profile.
Args: company_name (str): LinkedIn company name (e.g., "docker", "anthropic", "microsoft") get_employees (bool): Whether to scrape the company's employees (slower)
Returns: Dict[str, Any]: Structured data from the company's profile
| Name | Required | Description | Default |
|---|---|---|---|
| company_name | Yes | ||
| get_employees | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description mentions that setting get_employees to true is 'slower', disclosing a behavioral trait. No annotations exist, so the description carries full burden. It does not cover error handling, rate limits, or data freshness, but the core behavior is clear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured with a brief summary followed by Args/Returns docstring. It uses only necessary text, though the docstring format adds slight verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (2 params, output schema present), the description covers the key aspects: purpose, parameter meanings, return type, and a performance hint. Missing guidance on error cases or prerequisites, but adequate for the complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no descriptions (0% coverage), but the description adds meaningful semantics: company_name is clarified as a LinkedIn company name with examples, and get_employees is explained as controlling employee scraping with a performance note.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get a specific company's LinkedIn profile' with examples like 'docker', 'anthropic', 'microsoft'. It distinguishes from sibling tools like get_person_profile and search_jobs by specifying company focus.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not provide explicit when-to-use or when-not-to-use guidance relative to siblings, though the purpose is clear. It includes parameter details but lacks contextual triggers or alternative tool references.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_job_detailsA
Get job details for a specific job posting on LinkedIn
Args: job_id (str): LinkedIn job ID (e.g., "4252026496", "3856789012")
Returns: Dict[str, Any]: Structured job data including title, company, location, posting date, application count, and job description (may be empty if content is protected)
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that the job description may be empty if content is protected, which is a valuable behavioral trait. However, it does not mention authentication requirements, rate limits, or potential side effects. Since no annotations are provided, the description carries the full burden; it covers the most important behavioral nuance well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with a clear heading and structured Args/Returns sections. Every sentence adds value: the purpose, parameter explanation, examples, and return structure. There is no fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has one parameter and an output schema (context signals indicate has_output_schema=true). The description explains the return structure (title, company, location, etc.) and notes the edge case of empty job description. For a simple retrieval tool, this covers all necessary context, leaving no obvious gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no description for job_id (0% coverage). The description compensates by providing examples ('e.g., '4252026496', '3856789012''), which adds meaning and clarifies the format beyond the schema's bare type declaration. This helps the agent understand what a valid job ID looks like.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Get job details') and the resource ('a specific job posting on LinkedIn'). It distinguishes itself from sibling tools like search_jobs and get_company_profile by focusing on a single posting via a job ID. The verb-resource pair is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies that this tool is used when you have a specific job ID, but it does not explicitly state when to use it versus alternatives like search_jobs or get_company_profile. There is no guidance on prerequisites or when not to use it, leaving the agent to infer usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_person_profileA
Get a specific person's LinkedIn profile.
Args: linkedin_username (str): LinkedIn username (e.g., "stickerdaniel", "anistji")
Returns: Dict[str, Any]: Structured data from the person's profile
| Name | Required | Description | Default |
|---|---|---|---|
| linkedin_username | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Basic read operation described, but lacks disclosure of rate limits, authentication requirements, or error handling. Without annotations, description carries the burden but provides minimal behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise with front-loaded purpose, clear Args/Returns sections, and no unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with an output schema, the description fully explains the parameter and return type, making it complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Description adds example and clarifies the parameter format (LinkedIn username), which adds meaning beyond the schema's simple 'string' type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it retrieves a specific person's LinkedIn profile. Differentiates from siblings which deal with companies, jobs, sessions, or searches.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. No mention of context or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recommended_jobsB
Get your personalized recommended jobs from LinkedIn
Returns: List[Dict[str, Any]]: List of recommended jobs
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description must disclose behavior. It only mentions the action and return type, omitting any side effects, authentication needs, or rate limits. Minimal compared to the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise (one line plus return type). No wasted words, but could benefit from a brief sentence on usage context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Sufficient for a zero-parameter tool with output schema, but lacks any behavioral or usage context (e.g., what 'recommended' means, if results are sorted). Adequate but could be more helpful.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has zero parameters, so baseline is 4. Description does not need to add parameter info; it correctly notes return type which is partially redundant with output schema but acceptable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it retrieves personalized recommended jobs from LinkedIn, but does not explicitly differentiate from siblings like search_jobs, which could also be personalized. The verb 'get' and resource 'recommended jobs' are specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives (e.g., search_jobs, get_job_details). The description only states what it does without context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_jobsB
Search for jobs on LinkedIn using a search term.
Args: search_term (str): Search term to use for the job search.
Returns: List[Dict[str, Any]]: List of job search results
| Name | Required | Description | Default |
|---|---|---|---|
| search_term | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, and the description does not disclose behavioral traits such as idempotency, rate limits, authorization requirements, or whether it modifies data. The only behavioral hint is that it is a search (likely read-only), but this is implied rather than explicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: a single sentence followed by a structured Args and Returns section. Every part is necessary and there is no redundant information. It efficiently conveys what the tool does and how to use it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter, no nested objects) and the presence of an output schema, the description is adequate but lacks details such as pagination, result limits, or query operators. It covers the basics but leaves some behavioral context unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'search_term' is described as 'Search term to use for the job search', which adds basic meaning beyond the schema's property name. However, with 0% schema description coverage, the description only restates the obvious without adding constraints, formatting, or examples.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Search for jobs on LinkedIn using a search term.' This provides a specific verb (search) and resource (jobs), and distinguishes it from siblings like 'get_job_details' and 'get_recommended_jobs' which have different functions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description offers no guidance on when to use this tool versus alternatives like 'get_recommended_jobs' or 'get_job_details'. There are no conditions, prerequisites, or exclusions mentioned, leaving the agent without contextual decision support.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
6 tool updates
v1.4.0- First observed
close_session - First observed
get_company_profile - First observed
get_job_details - First observed
get_person_profile - First observed
get_recommended_jobs - First observed
search_jobs
TDQS
Each tool has a clear, distinct purpose: session management, company profiles, person profiles, job details, recommended jobs, and job search. No two tools overlap in functionality.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., get_company_profile, search_jobs), making them predictable and easy to understand.
With 6 tools, the set is well-scoped for a LinkedIn-focused server covering profiles and jobs without being overwhelming or sparse.
The tool surface covers basic read operations (profiles, jobs) but lacks common interaction capabilities like sending messages, posting updates, or managing connections, leaving notable gaps.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
- LinkMCPOAuthio.linkmcp
Hosted MCP server for LinkedIn: 31 tools for profiles, search, messaging, posts, enrichment.
Managed LinkedIn MCP server for AI agents: search, connect, message and enrich on accounts you own.
LinkedIn outreach MCP server โ 19 tools for AI agents to prospect, sequence, and manage contacts.
MCP server for LeadDelta โ manage LinkedIn connections and CRM data via AI assistants.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA FastMCP-based server that enables programmatic LinkedIn automation and data extraction through browser automation, offering secure authentication and tools for profile operations and post interactions while respecting LinkedIn's rate limits.53-
- AlicenseAqualityDmaintenanceHigh-performance autonomous MCP server that turns LinkedIn into an API for AI workflows, enabling profile management, job search, content posting, and document generation.141MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for programmable LinkedIn automation via Playwright, offering 20 tools for profile management, messaging, feed interaction, and job searching through real browser automation.29MIT
- AlicenseBqualityCmaintenancePlaywright-powered MCP server for LinkedIn that automates jobs, profile edits, messaging, network actions, and feed posts using a real logged-in browser session.36Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/selvin-paul-raj/Linkedin-MCP-Server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server