LinkedIn MCP Server
A ToS-compliant Model Context Protocol server for LinkedIn that uses the official API for OAuth 2.0 authentication, profile reading, and content posting.
README
LinkedIn MCP Server
A ToS-compliant Model Context Protocol server for LinkedIn, using only the official LinkedIn API.
Unlike other LinkedIn MCP servers that rely on scraping (which violates LinkedIn's User Agreement and risks account bans), this server uses LinkedIn's official Consumer API with proper OAuth 2.0 authentication.
Quick start
git clone https://github.com/anubisalpha/linkedin-mcp.git
cd linkedin-mcp
pip install -e .
Add to your Claude Code .mcp.json:
{
"mcpServers": {
"linkedin": {
"command": "python",
"args": ["-m", "linkedin_mcp.server"],
"env": {
"LINKEDIN_CLIENT_ID": "your_client_id",
"LINKEDIN_CLIENT_SECRET": "your_client_secret"
}
}
}
}
Important: Replace
your_client_idandyour_client_secretwith your actual values. Environment variable references like${LINKEDIN_CLIENT_ID}are not supported — use the literal strings.
Restart Claude Code, then ask: "Run linkedin_setup to check my configuration"
The setup assistant will check your credentials, show any missing steps, and guide you through first-time login.
Features
Tools
| Tool | Description |
|---|---|
linkedin_login |
OAuth 2.0 sign-in — opens your browser for secure authorization |
linkedin_logout |
Clear stored authentication tokens |
linkedin_status |
Check auth status, token expiry, and refresh token availability |
linkedin_health |
Run a health check — token validity, API connectivity, encryption, audit log |
linkedin_profile |
Get your name, email, photo, and locale |
linkedin_audit_log |
View the audit trail of all post previews, publishes, and deletions |
linkedin_create_text_post |
Publish a text post (public or connections-only) |
linkedin_create_article_post |
Share a URL/article with commentary |
linkedin_create_image_post |
Upload an image and publish with text |
linkedin_delete_post |
Delete a post by its URN |
linkedin_undo_last_post |
Quick-delete the most recently published post (undo) |
linkedin_post_history |
View your post history — URNs, timestamps, content, with optional type filter |
linkedin_link_preview |
Fetch Open Graph metadata from a URL to preview how LinkedIn will display it |
linkedin_setup |
First-run setup assistant — checks config and walks through any missing steps |
All write operations require explicit user approval before executing, keeping the integration compliant with LinkedIn's API Terms of Use (no automated posting).
Security and compliance
- Human-in-the-loop — Every write tool uses a two-step confirm pattern: preview first (default), then publish only after explicit approval
- Approval stamp — Published posts include a configurable stamp showing the content was human-approved
- Audit logging — Every preview, publish, and delete is recorded in a local NDJSON audit log
- Token encryption — Access tokens are encrypted at rest using Fernet with a machine-derived key
- Token refresh — Silently refreshes expired tokens when a refresh token is available, avoiding unnecessary re-authentication
- Health check — Diagnose issues with a single tool call: checks token validity, API connectivity, credential configuration, and audit log status
- Character count — Post previews show character count against LinkedIn's 3,000-character limit, preventing over-length submissions
- Undo/recall — Quick-delete the most recently published post with a single tool call, without needing to look up the URN
- MCP Inspector compatible — All tool schemas include
additionalProperties: falseand the server declares its version for strict MCP spec compliance - Scope verification — Checks that the stored token has all required scopes before attempting API actions, failing fast with a clear message
- Configurable encryption key — Optionally provide your own encryption key via environment variable for token portability between machines
- Configurable callback port — Change the OAuth callback port from the default 8585 via environment variable
- Type checked — Full mypy strict mode with no errors across all modules
- CI pipeline — GitHub Actions runs tests and type checking on Python 3.10, 3.11, and 3.12 for every push and PR
- Post history — Local record of all published posts with URNs, timestamps, content, and type filtering
- Link preview — Fetch Open Graph metadata from URLs before sharing to check the link card
- First-run setup — Interactive setup assistant that checks configuration and walks through missing steps
- Minimal scope — Only requests the API scopes needed (
openid,profile,email,w_member_social)
Testing
The project includes a comprehensive test suite with 184 unit tests (95% coverage) covering all modules:
pip install -e ".[dev]"
pytest tests/ -v
| Test file | Tests | Coverage |
|---|---|---|
test_models.py |
24 | Encryption, token save/load, expiry, backward compatibility, configurable key |
test_auth.py |
24 | OAuth flow, token refresh, auto-refresh logic, configurable port, callback handler |
test_api.py |
26 | Post building, approval stamp, API calls, URL encoding, image upload, link preview |
test_audit.py |
7 | NDJSON logging, truncation, directory creation, configurable path |
test_history.py |
14 | Post recording, retrieval, filtering, deletion, corruption handling |
test_server.py |
89 | All tool handlers, call routing, preview enforcement, health check, undo, char count, scope verification, setup, MCP Inspector |
Setting up a LinkedIn Developer App
Before you can use this MCP server, you need a LinkedIn Developer App. Here's how:
1. Create the app
Go to linkedin.com/developers/apps and click Create app.
You'll need:
- App name — e.g. "My LinkedIn MCP"
- LinkedIn Page — link to any LinkedIn company page you admin (or create one)
- App logo — a square PNG image (minimum 100x100px)
- Privacy policy URL — a URL to your privacy policy (you can host one via GitHub Pages — see below)
2. Enable the required products
On your app's Products tab, request access to:
- Sign in with LinkedIn using OpenID Connect — grants
openid,profile,emailscopes - Share on LinkedIn — grants
w_member_socialscope
Both are self-serve and activate immediately.
3. Configure the redirect URL
On the Auth tab:
- Copy your Client ID and Client Secret
- Under Authorized redirect URLs for your app, add:
http://localhost:8585/callback(or your custom port if usingLINKEDIN_MCP_CALLBACK_PORT)
4. Privacy policy (if you need one)
If you don't have a privacy policy URL, you can use GitHub Pages:
- Fork this repository
- Go to your fork's Settings > Pages
- Set source to Deploy from a branch, branch
main, folder/docs - Your privacy policy will be at:
https://yourusername.github.io/linkedin-mcp/privacy-policy
A template privacy policy is included at docs/privacy-policy.md.
Installation
Requirements
- Python 3.10+
- A configured LinkedIn Developer App (see above)
Install
git clone https://github.com/anubisalpha/linkedin-mcp.git
cd linkedin-mcp
pip install -e .
Configuration
Claude Code
Add to your project .mcp.json or ~/.claude/.mcp.json (global):
{
"mcpServers": {
"linkedin": {
"command": "python",
"args": ["-m", "linkedin_mcp.server"],
"env": {
"LINKEDIN_CLIENT_ID": "your_client_id",
"LINKEDIN_CLIENT_SECRET": "your_client_secret"
}
}
}
}
Claude Desktop
Add to your claude_desktop_config.json:
{
"mcpServers": {
"linkedin": {
"command": "python",
"args": ["-m", "linkedin_mcp.server"],
"env": {
"LINKEDIN_CLIENT_ID": "your_client_id",
"LINKEDIN_CLIENT_SECRET": "your_client_secret"
}
}
}
}
Environment variables
| Variable | Required | Description |
|---|---|---|
LINKEDIN_CLIENT_ID |
Yes | Your LinkedIn app's Client ID |
LINKEDIN_CLIENT_SECRET |
Yes | Your LinkedIn app's Client Secret |
LINKEDIN_MCP_TOKEN_PATH |
No | Custom path for token storage (default: ~/.linkedin-mcp/tokens.json) |
LINKEDIN_MCP_APPROVAL_STAMP |
No | Text appended to posts showing human approval. Set to empty string to disable. Default: AI-drafted · Human-approved · Posted via LinkedIn MCP |
LINKEDIN_MCP_AUDIT_PATH |
No | Custom path for the audit log (default: ~/.linkedin-mcp/audit.log) |
LINKEDIN_MCP_ENCRYPTION_KEY |
No | Custom encryption key for token storage. Enables token portability between machines. When unset, uses a machine-derived key. |
LINKEDIN_MCP_HISTORY_PATH |
No | Custom path for the post history file (default: ~/.linkedin-mcp/history.json) |
LINKEDIN_MCP_CALLBACK_PORT |
No | OAuth callback port (default: 8585). Change if another service is using that port. Remember to update the redirect URL in your LinkedIn Developer App to match. |
Usage
First-time login
Ask Claude to log you in:
"Log in to my LinkedIn account"
This opens your browser for LinkedIn's OAuth consent page. After authorizing, the token is stored locally and lasts 60 days.
Posting content
"Write a LinkedIn post about the project I just shipped and publish it"
Claude will draft the post and show you the exact content before publishing. You approve or reject via the standard tool approval prompt.
Sharing an article
"Share this article on LinkedIn with a short commentary: https://example.com/article"
Posting with an image
"Create a LinkedIn post about our team event and attach the photo at /path/to/image.jpg"
How it works
- Authentication: Standard OAuth 2.0 Authorization Code Flow. Your browser handles the LinkedIn login — credentials never pass through the MCP server.
- Token storage: Access tokens are encrypted at rest using Fernet encryption with a machine-derived key, stored at
~/.linkedin-mcp/tokens.json. Tokens expire after 60 days. - Token refresh: If LinkedIn provides a refresh token, the server will silently refresh expired access tokens without opening the browser. If no refresh token is available, you'll be prompted to re-authenticate.
- Human-in-the-loop: Every write action (post, delete) requires explicit user approval in your MCP client before the API call is made.
- API scope: Uses only
openid,profile,email, andw_member_social— the minimum required for profile reading and content posting.
ToS compliance
This server is designed to comply with LinkedIn's User Agreement and API Terms of Use:
- Uses only the official API — no scraping, crawling, or browser automation
- No automated posting — every publish action requires human approval
- Minimal data access — only requests the scopes needed
- No data storage beyond tokens — profile data is fetched on demand, not cached
- No mass messaging — the server publishes individual posts, not bulk content
Rate limits
- 150 posts per day per member
- 100,000 API calls per day per application
Architecture
See docs/architecture.md for implementation details, design decisions, and API reference.
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.