A Custom MCP Server for LinkedIn integration built with FastMCP.
LinkedIn MCP Server
A powerful Model Context Protocol (MCP) server that enables AI agents like Claude to interact seamlessly with LinkedIn's professional network. Built with FastMCP for high performance and reliability.
What is This?
This MCP server bridges the gap between AI assistants and LinkedIn, allowing them to:
- Create and manage LinkedIn posts with text and images
- Comment on posts and engage with content
- Access profile information
- Search for companies, jobs, and people
- Automate LinkedIn interactions through natural language
Perfect for professionals who want to leverage AI to manage their LinkedIn presence efficiently.
Features
Core Capabilities
- Secure Authentication - OAuth 2.0 flow with access token management
- Content Creation - Publish text posts and image posts
- Content Management - Update and delete posts
- Engagement - Comment on posts and manage comments
- Profile Access - Retrieve authenticated user profile information
- Company Intelligence - Search and view company profiles
- Job Discovery - Search job postings and view details
- People Search - Find professionals on LinkedIn
Built With
- FastMCP - Modern Python MCP framework
- httpx - Async HTTP client for API calls
- Pydantic - Data validation and settings management
- OAuth 2.0 - Industry-standard authentication
Installation
Option 1: Using uvx (Recommended)
The fastest way to get started:
uvx linkedin-mcp-server
Option 2: Using pip
Install from PyPI:
pip install linkedin-mcp-server
Option 3: From Source
For development or customization:
git clone https://github.com/SARAMALI15792/LinkedIn_mcp_custom_server.git
cd LinkedIn_mcp_custom_server
pip install -e .
Quick Start Guide
Step 1: Create LinkedIn App
- Go to LinkedIn Developer Portal
- Click "Create app"
- Fill in required information:
- App name: Choose a descriptive name
- LinkedIn Page: Associate with your page or create one
- App logo: Upload a logo (optional but recommended)
- Request access to these products:
- Sign In with LinkedIn using OpenID Connect (instant approval)
- Share on LinkedIn (instant approval)
- In the "Auth" tab:
- Add Redirect URL:
http://localhost:8000 - Copy your Client ID
- Copy your Client Secret
- Add Redirect URL:
Step 2: Configure Environment
Create a .env file in your working directory:
LINKEDIN_CLIENT_ID=your_client_id_here
LINKEDIN_CLIENT_SECRET=your_client_secret_here
LINKEDIN_REDIRECT_URI=http://localhost:8000
Security Note: Never commit the .env file to version control. It's already in .gitignore.
Step 3: Configure Claude Desktop
Edit your Claude Desktop configuration file:
Windows: %APPDATA%\Claude\claude_desktop_config.json
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
Add the LinkedIn MCP server:
{
"mcpServers": {
"linkedin": {
"command": "uvx",
"args": ["linkedin-mcp-server"]
}
}
}
If installed via pip:
{
"mcpServers": {
"linkedin": {
"command": "linkedin-mcp-server"
}
}
}
For local development:
{
"mcpServers": {
"linkedin": {
"command": "python",
"args": ["-m", "linkedin_mcp_server"],
"env": {
"LINKEDIN_CLIENT_ID": "your_client_id",
"LINKEDIN_CLIENT_SECRET": "your_client_secret",
"LINKEDIN_REDIRECT_URI": "http://localhost:8000"
}
}
}
}
Step 4: Authenticate with LinkedIn
- Restart Claude Desktop
- In Claude, type: "Generate LinkedIn login URL"
- Copy and open the URL in your browser
- Sign in to LinkedIn and authorize the application
- You'll be redirected to
http://localhost:8000/?code=... - Copy the
codeparameter value from the URL - In Claude, type: "Exchange this code: [paste the code]"
- Done! You're now authenticated.
Your access token is automatically saved to .env and will be used for all future requests.
Usage Examples
Authentication
User: "Generate LinkedIn login URL"
Claude: [Provides OAuth URL with instructions]
User: "Exchange this code: AQTvqXXXXXXXXXXX"
Claude: "Success! Access Token saved. Expires in 5183999 seconds."
Creating Posts
Text Post:
User: "Post to LinkedIn: Excited to announce the launch of our new AI-powered LinkedIn MCP server! Check it out on GitHub."
Claude: [Creates post and returns post URN]
Post with Image:
User: "Post this image to LinkedIn with caption 'Team celebration': C:/Users/photos/team.jpg"
Claude: [Uploads image and creates post with caption]
Managing Content
Update a Post:
User: "Update post urn:li:share:7289123456789 to say: Updated announcement..."
Claude: [Deletes old post and creates new one with updated text]
Delete a Post:
User: "Delete my post urn:li:share:7289123456789"
Claude: [Deletes the post permanently]
Engagement
Comment on Posts:
User: "Comment on post urn:li:share:7289123456789: Great insights, thanks for sharing!"
Claude: [Posts comment and returns comment URN]
View Comments:
User: "Show comments on post urn:li:share:7289123456789"
Claude: [Retrieves and displays all comments]
Profile Information
User: "What's my LinkedIn email address?"
Claude: [Retrieves profile and shows email]
User: "Show me my LinkedIn profile"
Claude: [Displays profile information: name, email, picture URL, etc.]
Company Research
User: "Search for companies: Microsoft"
Claude: [Returns list of matching companies]
User: "Get details for company urn:li:organization:1035"
Claude: [Shows company profile information]
Job Search
User: "Find remote Python developer jobs"
Claude: [Searches and displays matching job postings]
User: "Search for Machine Learning Engineer positions in San Francisco"
Claude: [Returns relevant job listings]
User: "Get details for job urn:li:job:123456789"
Claude: [Shows detailed job information]
People Search
User: "Search for AI researchers at Stanford"
Claude: [Returns matching professionals]
Available Tools
| Tool Name | Description | Read-Only | Destructive |
|-----------|-------------|-----------|-------------|
| linkedin_get_oauth_url | Generate OAuth 2.0 authorization URL | Yes | No |
| linkedin_exchange_code | Exchange auth code for access token | No | No |
| linkedin_get_my_profile | Get authenticated user's profile | Yes | No |
| linkedin_get_member_profile | Get member profile by URN | Yes | No |
| linkedin_create_post | Create text post | No | No |
| linkedin_create_image_post | Create post with image | No | No |
| linkedin_update_post | Update existing post (via delete + create) | No | Yes |
| linkedin_delete_post | Delete post permanently | No | Yes |
| linkedin_get_recent_posts | List recent posts | Yes | No |
| linkedin_create_comment | Comment on content | No | No |
| linkedin_get_post_comments | Get comments on post | Yes | No |
| linkedin_delete_comment | Delete comment permanently | No | Yes |
| linkedin_get_company_profile | Get company details by URN | Yes | No |
| linkedin_search_companies | Search for companies | Yes | No |
| linkedin_search_jobs | Search job postings | Yes | No |
| linkedin_get_job_details | Get job details by URN | Yes | No |
| linkedin_search_people | Search for people | Yes | No |
Understanding LinkedIn URNs
LinkedIn uses URNs (Uniform Resource Names) to identify resources:
- Person:
urn:li:person:AbC123XyZ - Post/Share:
urn:li:share:7289123456789 - Comment:
urn:li:comment:(ugcPost:7289123456789,7289987654321) - Organization:
urn:li:organization:1035 - Job:
urn:li:job:123456789
When Claude returns a URN, you can use it to reference that resource in other commands.
API Permissions and Limitations
Available Permissions
This server requests these OAuth scopes:
openid- OpenID Connect authenticationprofile- Access to profile informationemail- Access to email addressw_member_social- Create posts and comments
Known Limitations
Some LinkedIn API features require additional permissions that are restricted to approved partners:
Restricted Read Operations:
r_member_social- Read user's posts (rarely granted to third-party apps)- Marketing Developer Platform - Advanced company/people search
- Talent Solutions - Advanced job search features
What This Means:
- Creating posts: Works perfectly
- Deleting posts: Works perfectly
- Reading your own posts: May not work (requires restricted permission)
- Advanced search: May require approval for Marketing/Talent APIs
Why? LinkedIn restricts these APIs to protect user privacy and control third-party access to their platform.
Project Structure
linkedin-mcp-server/
├── linkedin_mcp_server/ # Main package
│ ├── __init__.py # Package initialization
│ ├── __main__.py # CLI entry point
│ ├── server.py # MCP server with 18 tool definitions
│ ├── config.py # Configuration with pydantic-settings
│ ├── utils.py # Shared HTTP client utilities
│ └── tools/ # Tool implementations
│ ├── auth.py # OAuth 2.0 authentication flow
│ ├── profile.py # Profile retrieval operations
│ ├── post.py # Post and comment operations
│ ├── company.py # Company search and profiles
│ ├── job.py # Job search operations
│ └── search.py # People search functionality
├── pyproject.toml # Package metadata and dependencies
├── requirements.txt # Pinned dependencies
├── README.md # This file
├── claude.md # Claude integration guide
├── LICENSE # MIT License
└── get_profile.py # Example standalone script
Development
Setting Up Development Environment
# Clone repository
git clone https://github.com/SARAMALI15792/LinkedIn_mcp_custom_server.git
cd LinkedIn_mcp_custom_server
# Install with dev dependencies
pip install -e ".[dev]"
Running Tests
pytest tests/
Code Quality
# Format code
black linkedin_mcp_server/
# Lint
ruff check linkedin_mcp_server/
# Type checking
mypy linkedin_mcp_server/
Running Locally
# Using module syntax
python -m linkedin_mcp_server
# Using installed command
linkedin-mcp-server
Troubleshooting
Authentication Issues
Problem: "Error: LINKEDIN_CLIENT_ID not configured"
Solution: Create .env file with your LinkedIn app credentials
Problem: "Unauthorized (401)" errors Solution: Your access token expired. Re-authenticate using the OAuth flow
Problem: "Error exchanging code: invalid code" Solution: Authorization codes expire quickly. Generate a new OAuth URL and try again
API Errors
Problem: "Forbidden (403)" errors Solution: Your LinkedIn app may lack required permissions. Check your app's products in the Developer Portal
Problem: "r_member_social permission required" Solution: This permission is restricted. LinkedIn rarely grants it to third-party apps. Focus on write operations instead
Problem: Can't search companies/jobs/people Solution: These APIs may require Marketing/Talent Solutions products which need LinkedIn approval
Connection Issues
Problem: MCP server not connecting in Claude Desktop Solution:
- Verify
claude_desktop_config.jsonsyntax is valid JSON - Check that the command path is correct
- Restart Claude Desktop
- Check Claude Desktop logs for error messages
Problem: ".env file not found"
Solution: Create .env file in the same directory where Claude Desktop runs the server, or specify environment variables in the config
Security Best Practices
- Never commit credentials -
.envis in.gitignorefor a reason - Rotate tokens regularly - Re-authenticate periodically for security
- Use HTTPS in production - Update redirect URI to HTTPS for production apps
- Minimum permissions - Only request scopes you actually need
- Review app access - Regularly check LinkedIn's "Apps" section in settings
Contributing
Contributions are welcome! Here's how:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Run tests:
pytest tests/ - Format code:
black linkedin_mcp_server/ - Commit:
git commit -m 'Add amazing feature' - Push:
git push origin feature/amazing-feature - Open a Pull Request
Contribution Guidelines
- Follow existing code style (Black formatter, 100 char line length)
- Add tests for new features
- Update documentation as needed
- Keep commits focused and atomic
- Write clear commit messages
Roadmap
Future enhancements being considered:
- Token refresh flow implementation
- Webhook support for real-time notifications
- Enhanced error handling and retry logic
- Pagination support for search results
- Bulk operations for efficiency
- Analytics and insights (if API access granted)
- Connection management features
- Message sending (if Messaging API access granted)
FAQ
Q: Why can't I read my own posts?
A: The r_member_social permission required to read posts is restricted by LinkedIn. Most third-party apps cannot access this feature.
Q: How long do to access tokens last? A: LinkedIn controls token expiration. Typically tokens last for 60 days, but this can vary. You'll need to re-authenticate when tokens expire.
Q: Can I use this for multiple LinkedIn accounts?
A: Currently, the server is designed for single-user authentication. Each .env file holds one access token.
Q: Is this officially supported by LinkedIn? A: No, this is a community project. It uses LinkedIn's public APIs but is not officially endorsed by LinkedIn.
Q: Can I use this commercially? A: Yes, the MIT license allows commercial use. However, check LinkedIn's terms of service and API usage policies.
Q: Why do some searches return empty results? A: Search APIs may require additional LinkedIn products (Marketing/Talent) that need approval. Also, API access varies by account type.
Support
- Report bugs: GitHub Issues
- Documentation: GitHub README
- Integration Guide: claude.md
- Discussions: GitHub Discussions
Resources
- FastMCP Documentation
- Model Context Protocol Spec
- LinkedIn API Documentation
- OAuth 2.0 Specification
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
Built with:
- FastMCP - For the excellent MCP framework
- Model Context Protocol - For enabling AI-agent integrations
- LinkedIn API - For providing professional networking capabilities
- Claude - For inspiring and testing this integration
Author
SARAM ALI
- Email: saramali15792@gmail.com
- GitHub: @SARAMALI15792
- Project: LinkedIn MCP Custom Server
Built with care for the AI and LinkedIn communities | Report Issues | Contribute | Star on GitHub