Skip to main content
Glama
selvin-paul-raj

LinkedIn MCP Server

LinkedIn MCP Server

License: MIT Python 3.12+ LinkedIn API

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-http

Authentication

Related MCP server: LinkedIn MCP Pro Max

Get your li_at cookie:

  1. Log in to LinkedIn in Chrome

  2. Press F12

  3. Application โ†’ Cookies โ†’ https://www.linkedin.com

  4. Copy the li_at cookie value

  5. Add to .env:

LINKEDIN_COOKIE=li_at=YOUR_COOKIE_VALUE

2. 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=202510
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_emailaddress

Exchange 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_profile

  • get_company_profile

  • get_job_details

  • search_jobs

  • search_recommended_jobs

  • close_session

๐Ÿ“ Post Management

  • create_linkedin_post

  • update_linkedin_post

  • delete_linkedin_post

๐Ÿ–ผ๏ธ Media

  • upload_linkedin_image

  • get_linkedin_image

๐Ÿ’™ Reactions

  • add_linkedin_reaction

  • remove_linkedin_reaction

  • get_linkedin_reactions

๐Ÿ‘ค Profile & Auth

  • get_linkedin_profile

  • validate_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.md

Testing

# unit tests
uv run pytest tests/unit -v

# integration tests
uv run pytest tests/integration -v

# all tests
uv run pytest tests/ -v

Quick API test:

uv run python scripts/test_api.py

Troubleshooting

โŒ "426 Client Error: Upgrade Required"

Fix:

LINKEDIN_API_VERSION=202510

Get fresh cookie from Chrome.

โŒ "401 Unauthorized"

Generate a new access token.

ChromeDriver issues

pip install --upgrade selenium webdriver-manager

API Versioning

Current default:

202510

Check latest: https://learn.microsoft.com/en-us/linkedin/marketing/versioning

Update:

LINKEDIN_API_VERSION=202511

Restart 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-files

Pull 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 tools
close_sessionA

Close the current browser session and clean up resources.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault
company_nameYes
get_employeesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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)

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault
linkedin_usernameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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.

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

ParametersJSON Schema
NameRequiredDescriptionDefault
search_termYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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.

  1. 6 tool updatesv1.4.0
    • First observedclose_session
    • First observedget_company_profile
    • First observedget_job_details
    • First observedget_person_profile
    • First observedget_recommended_jobs
    • First observedsearch_jobs

TDQS

A3.8/5.0
Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

With 6 tools, the set is well-scoped for a LinkedIn-focused server covering profiles and jobs without being overwhelming or sparse.

Completeness3/5

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

ActivityInactive
ResponsivenessSyncing

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

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A 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
    -
  • A
    license
    A
    quality
    D
    maintenance
    High-performance autonomous MCP server that turns LinkedIn into an API for AI workflows, enabling profile management, job search, content posting, and document generation.
    14
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for programmable LinkedIn automation via Playwright, offering 20 tools for profile management, messaging, feed interaction, and job searching through real browser automation.
    29
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    Playwright-powered MCP server for LinkedIn that automates jobs, profile edits, messaging, network actions, and feed posts using a real logged-in browser session.
    36
    Apache 2.0

Latest Blog Posts

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