Skip to main content
Glama
iamvaibhav31

linkedin-mcp

by iamvaibhav31

LinkedIn MCP Server — Remote Edition (Claude + ChatGPT)

An MCP server exposing LinkedIn actions, reachable from both Claude and ChatGPT as a custom connector. Runs over HTTP (not stdio) because ChatGPT only supports remote, HTTPS-reachable MCP servers — it cannot launch a local script the way Claude Desktop can.

What this can and can't do

LinkedIn's public API does not expose any endpoint for a third-party app to write directly to a profile's About, Experience, or Projects sections — for any account type:

  • The Profile API is GET-only, and partner-gated even for reads beyond name/photo/headline. There is no POST/PATCH for profile fields.

  • Member Data Portability (the DMA product) is read-only and EU/EEA/Switzerland-only.

  • Nothing else in LinkedIn's product catalog writes member profile data.

That's a platform restriction, not something this code can work around without violating LinkedIn's User Agreement §8.2 — which prohibits "software, devices, scripts, robots or any other means or processes (such as crawlers, browser plugins and add-ons or any other technology)". A browser extension is named in the same clause as a headless bot, so it isn't a safer middle ground; the penalty is account restriction or permanent ban. This project doesn't go there.

Tool

What it does

get_my_profile

Reads your name, email, photo via OpenID Connect

create_post

Publishes a text or link post to your feed

generate_resume_pdf

Builds a PDF from structured About/Experience/Projects data, formatted for LinkedIn's own Import Resume feature

generate_profile_sections

Length-checks finished profile copy against LinkedIn's real limits (headline 220, About 2600, role description 2000) and says where each piece goes

add_certification_link

Builds an Add to Profile link for a certification — see the caveat below

generate_resume_pdf is the practical route to "updating" Experience/Education: LinkedIn auto-parses a resume PDF and pre-fills those sections for review. About and Projects aren't reliably auto-parsed — generate_profile_sections exists to make that manual paste mechanical rather than a guessing game about lengths.

⚠️ add_certification_link no longer prefills. LinkedIn's help centre now states these links "will no longer be customized for a specific certificate or degree" and "will no longer autofill and members must enter the relevant information directly on their profile". Many third-party guides and URL builders still advertise the old prefilling behaviour — they're out of date. The tool still emits the detail parameters (they cost nothing and would start working again if LinkedIn reverts), but treat it as a shortcut to the right form, not as a profile write.

Related MCP server: linkedin-mcp-pro

Two connection modes, and which credentials each one wants

This server supports two different ways of authenticating, auto-detected per request:

  1. Fixed shared secret (Postman, curl, ChatGPT's connector) — you generate MCP_BEARER_TOKEN yourself (e.g. openssl rand -hex 32) and put it in .env alongside LINKEDIN_ACCESS_TOKEN (obtained once via auth_setup.py). Clients send Authorization: Bearer <your MCP_BEARER_TOKEN>, and the server calls LinkedIn using the stored LINKEDIN_ACCESS_TOKEN underneath.

  2. Direct LinkedIn OAuth passthrough (Claude's connector) — Claude logs into LinkedIn itself using your LinkedIn app's Client ID/Secret (not anything you generate) and sends LinkedIn's own resulting access token as the Bearer header. The server detects this token doesn't match your MCP_BEARER_TOKEN and uses it directly as the LinkedIn access token instead.

Don't mix these up: MCP_BEARER_TOKEN is something you invent for mode 1; your LinkedIn app's Client ID/Secret (from LinkedIn's own Auth tab) are what mode 2 needs, and they're never typed into .env at all — Claude holds them.

1. LinkedIn app setup

  1. Create an app: https://www.linkedin.com/developers/apps

  2. Auth tab → add two redirect URLs:

    • http://localhost:8765/callback (for auth_setup.py, mode 1)

    • https://claude.ai/api/mcp/auth_callback (for Claude's connector, mode 2)

  3. Products tab → request:

    • Sign In with LinkedIn using OpenID Connect (auto-approved)

    • Share on LinkedIn (auto-approved)

  4. Copy the Client ID / Secret from the Auth tab — you'll use these directly in Claude's connector settings for mode 2, and/or in your own .env for auth_setup.py (mode 1).

2. Local setup & one-time LinkedIn auth

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# fill in LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET, and set a random MCP_BEARER_TOKEN
python auth_setup.py   # opens browser, completes LinkedIn OAuth, saves LINKEDIN_ACCESS_TOKEN to .env

3. Deploy it somewhere public

Both Claude and ChatGPT need to reach this server over HTTPS — localhost won't work for either unless you tunnel it. Pick one:

Quick test (ngrok tunnel, temporary URL):

python server.py                    # starts on http://0.0.0.0:8000
ngrok http 8000                     # gives you a temporary https:// URL

Permanent (Docker, deploy to Render/Fly.io/Railway/any host that runs containers):

docker build -t linkedin-mcp .
docker run -p 8000:8000 --env-file .env linkedin-mcp

Point that platform's generated HTTPS domain at container port 8000, path /mcp.

A Procfile is also included for platforms that build directly from source (Railway, Heroku-style) without a Dockerfile.

Your MCP endpoint URL will be: https://<your-domain>/mcp

4. Connect it to Claude

Claude.ai → Settings → Connectors → Add custom connector. The dialog only has three fields that matter here — no separate Authorization URL / Token URL inputs, despite what you might expect from a typical OAuth setup:

  • Name: whatever you want it labeled as (e.g. linkedIn-mcp)

  • Remote MCP server URL: https://<your-domain>/mcp

  • Advanced settings → OAuth Client ID / OAuth Client Secret: your LinkedIn app's Client ID and Client Secret (from LinkedIn's Auth tab) — not anything you generate yourself, and not your server's MCP_BEARER_TOKEN

Click Add, then Connect. This sends you to LinkedIn's real login/consent screen — log in and approve. LinkedIn redirects back to Claude with a genuine access token, which Claude then sends as the Bearer header on every tool call.

Before this works, add a second authorized redirect URL in your LinkedIn app's Auth tab (alongside http://localhost:8765/callback, which auth_setup.py still uses separately):

https://claude.ai/api/mcp/auth_callback

The server handles the rest automatically: since the token Claude sends won't match your own MCP_BEARER_TOKEN, it's treated as a real LinkedIn access token and used directly against LinkedIn's API — no code changes needed per person who connects. This also means multiple people could each connect with their own LinkedIn account against the same deployed server.

If Connect fails at the LinkedIn-login step itself (not after — see below), double check the redirect URL above was saved exactly, and that both "Sign In with LinkedIn using OpenID Connect" and "Share on LinkedIn" show as fully added under your LinkedIn app's Products tab.

If it reaches LinkedIn's login/consent screen fine, but fails silently right after you approve: that's LinkedIn's token endpoint requiring the client secret in the POST body rather than an Authorization: Basic header, which some OAuth clients don't handle by default. If that happens and persists, fall back to the Claude Desktop + mcp-remote approach below — it sidesteps this entirely.

Connecting via Claude Desktop + mcp-remote (guaranteed fallback)

If the direct-OAuth route above doesn't work, or you're not on claude.ai web:

~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "linkedin": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote",
        "https://<your-domain>/mcp",
        "--header", "Authorization: Bearer YOUR_MCP_BEARER_TOKEN"
      ]
    }
  }
}

This runs locally as a subprocess and attaches your fixed bearer token directly — no OAuth negotiation involved. Restart Claude Desktop after saving.

Connecting it to ChatGPT

ChatGPT → Settings → Apps & Connectors → Advanced settings → enable Developer mode (requires Plus/Pro/Business/Enterprise) → Add custom connector:

  • URL: https://<your-domain>/mcp

  • Authentication: choose token/API key auth → paste your MCP_BEARER_TOKEN

  • In a new chat, open the + menu → Developer mode → toggle this connector on for that conversation (ChatGPT enables connectors per-conversation).

Using generate_resume_pdf

generate_resume_pdf(
    full_name="Vaibhav Sharma",
    headline="Frontend / Full-Stack Developer",
    email="you@example.com",
    phone="+91-XXXXXXXXXX",
    location="Bengaluru, India",
    about="Frontend/full-stack developer specializing in AI-powered conversational...",
    experience=[{
        "title": "Frontend Developer",
        "company": "Kapture CRM",
        "location": "Bengaluru, India",
        "start_date": "Jan 2024",
        "end_date": "Present",
        "bullets": [
            "Built and shipped the Vitos AI voice/chat agent builder UI end-to-end",
            "Normalized Redux state using createEntityAdapter across the Vitos state tree",
        ],
    }],
    projects=[{
        "name": "Shifra",
        "description": "Voice-controlled AI assistant built with xAI's Grok API.",
        "tech": ["React", "TypeScript", "Grok API", "Vercel"],
    }],
    skills=["React", "TypeScript", "Redux", "Node.js"],
)

The tool returns the PDF as pdf_base64, so you get the file back regardless of where the server runs — ask Claude/ChatGPT to save it for you. output_path is optional and only writes to the server's disk, which is useful when running locally and useless once deployed.

Then: LinkedIn → Me → View Profile → More → Build a resume → Import from resume, review the auto-filled Experience/Education, and paste the About/Projects text manually. Run generate_profile_sections first to confirm that text fits before you paste it.

Files

  • server.py — remote MCP server (streamable-http + bearer auth) + tool definitions

  • linkedin_client.py — LinkedIn REST API wrapper (userinfo, posts)

  • resume_builder.py — reportlab-based resume PDF generator

  • profile_links.py — character limits + Add to Profile URL builder (pure, no network)

  • auth_setup.py — one-time OAuth2 flow to obtain a LinkedIn access token

  • Dockerfile / Procfile — deployment

  • .env.example — credential template

Maintenance

ActivityMaintained
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

  • A
    license
    Not graded
    quality
    D
    maintenance
    An intelligent bridge between Claude and LinkedIn. This MCP server empowers Claude to act as your high-level career consultant, capable of auditing your profile, optimizing your identity, and managing your professional content with real-time API access.
    1
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Self-hosted, ban-safe MCP server for LinkedIn that provides 22 tools for profiles, search, jobs, posts, connections, and messages. Integrates with any MCP-compatible client like Claude Desktop.
    58
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    LinkedIn MCP server for Claude to create posts, read profile, and get analytics.
    29
    MIT

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/iamvaibhav31/linkedIn-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server