linkedin-mcp-server
MCP server for LinkedIn API integration. Enables authentication, profile access, connections, search, messaging, and feed management via OAuth2.
README
LinkedIn MCP Server
A Model Context Protocol (MCP) server implementation that provides seamless integration with LinkedIn's API. This server enables applications to authenticate, access LinkedIn data, and perform various operations through the MCP interface.
๐ Features
- OAuth2 Authentication: Secure LinkedIn OAuth2 flow with PKCE support
- User Profile Access: Retrieve authenticated user profile information
- Connections Management: List and manage user connections
- Search Functionality: Search for people on LinkedIn
- Feed Management: Access and interact with user feed
- Messaging: Send direct messages to connections
- Skills & Recommendations: Access skills and recommendations data
- Token Management: Automatic token refresh and validation
- Rate Limiting: Built-in rate limiting to respect API quotas
- Error Handling: Comprehensive error handling with detailed messages
- Logging: Winston-based logging for debugging and monitoring
- Security: CSRF protection, HTTPS support, secure credential storage
๐ Prerequisites
- Node.js 16.0.0 or higher
- npm 8.0.0 or higher
- LinkedIn Developer Account
- LinkedIn App credentials (Client ID, Client Secret)
๐ Installation
1. Clone the Repository
git clone https://github.com/yourusername/linkedin_mcp_server.git
cd linkedin_mcp_server
2. Install Dependencies
npm install
3. Configure Environment Variables
Create a .env file in the root directory with your LinkedIn credentials:
# LinkedIn OAuth Configuration
LINKEDIN_CLIENT_ID=your_client_id_here
LINKEDIN_CLIENT_SECRET=your_client_secret_here
LINKEDIN_REDIRECT_URI=http://localhost:3000/callback
# Server Configuration
PORT=3000
HOST=localhost
NODE_ENV=development
# Optional: Anthropic/OpenAI API Keys
CLAUDE_API_KEY=your_claude_api_key
OPENAI_API_KEY=your_openai_api_key
4. Get LinkedIn Credentials
- Visit LinkedIn Developers
- Create a new app
- Copy your Client ID and Client Secret
- Add your redirect URI (default:
http://localhost:3000/callback) - Request access to required API endpoints
๐ง Configuration
Environment Variables
See .env file for all available configuration options:
| Variable | Description | Default |
|---|---|---|
LINKEDIN_CLIENT_ID |
LinkedIn OAuth Client ID | Required |
LINKEDIN_CLIENT_SECRET |
LinkedIn OAuth Client Secret | Required |
LINKEDIN_REDIRECT_URI |
OAuth callback URI | http://localhost:3000/callback |
PORT |
Server port | 3000 |
NODE_ENV |
Environment (dev/prod) | development |
RATE_LIMIT_PER_MINUTE |
API rate limit | 60 |
LOG_LEVEL |
Logging level | info |
๐ Usage
Starting the Server
Development Mode (with auto-reload):
npm run dev
Production Mode:
npm start
OAuth Authentication Flow
1. Get Authorization URL
import LinkedInOAuth from './src/oauth.js';
const oauth = new LinkedInOAuth(
process.env.LINKEDIN_CLIENT_ID,
process.env.LINKEDIN_CLIENT_SECRET,
process.env.LINKEDIN_REDIRECT_URI
);
const authUrl = oauth.getAuthorizationUrl();
console.log('Visit:', authUrl);
2. Handle Callback
// After user authorizes, LinkedIn redirects with 'code' and 'state'
const token = await oauth.exchangeCodeForToken(code, state);
console.log('Access Token:', token.accessToken);
3. Use Access Token
import LinkedInClient from './src/linkedin.js';
const client = new LinkedInClient(token.accessToken);
const profile = await client.getProfile();
console.log('User Profile:', profile);
๐ API Documentation
LinkedInClient Methods
Profile Operations
// Get authenticated user's profile
const profile = await client.getProfile();
// Get specific user's profile
const userProfile = await client.getUserProfile(userId);
// Get user's email
const email = await client.getEmail();
Connections
// Get user's connections (paginated)
const connections = await client.getConnections(start = 0, count = 10);
Search
// Search for people
const results = await client.searchPeople('software engineer', count = 10);
Social Features
// Get user's skills
const skills = await client.getSkills();
// Get received recommendations
const recommendations = await client.getRecommendations();
// Get job experience
const experience = await client.getExperience();
// Get user's feed
const feed = await client.getFeed(count = 10);
Messaging
// Send a message to a connection
const result = await client.sendMessage(recipientId, 'Hello!');
Posting
// Create a share (post)
const share = await client.createShare('This is my new post!', 'TEXT_ONLY');
LinkedInOAuth Methods
// Get authorization URL
const authUrl = oauth.getAuthorizationUrl();
// Exchange authorization code for token
const token = await oauth.exchangeCodeForToken(code, state);
// Refresh an access token
const newToken = await oauth.refreshAccessToken(refreshToken);
// Revoke a token
await oauth.revokeToken(accessToken);
// Validate token
const validation = await oauth.validateToken(accessToken);
// Get user info
const userInfo = await oauth.getUserInfo(accessToken);
๐งช Testing
Run all tests:
npm test
Run tests in watch mode:
npm run test:watch
Generate coverage report:
npm run test:coverage
๐ Code Quality
Linting
# Check code style
npm run lint
# Fix linting issues
npm run lint:fix
Formatting
# Format code with Prettier
npm run format
# Check formatting
npm run format:check
๐ Project Structure
linkedin_mcp_server/
โโโ src/
โ โโโ index.js # Server entry point
โ โโโ linkedin.js # LinkedIn API client
โ โโโ oauth.js # OAuth2 implementation
โ โโโ ...
โโโ tests/
โ โโโ linkedin.test.js
โ โโโ oauth.test.js
โโโ .env # Environment configuration
โโโ .gitignore # Git ignore rules
โโโ package.json # Project dependencies
โโโ README.md # This file
๐ Security Considerations
- Never commit
.envfile - Contains sensitive credentials - Use HTTPS in production - Set
USE_HTTPS=trueand provide SSL certificates - Validate state parameter - CSRF protection in OAuth flow
- Store tokens securely - Use environment variables or secure storage
- Implement rate limiting - Configured via
RATE_LIMIT_PER_MINUTE - Refresh tokens regularly - Call
refreshAccessToken()before expiration - Use PKCE flow - Enable with
usePKCE: truein OAuth methods
๐ Troubleshooting
Common Issues
Issue: "Invalid client credentials"
- Verify
LINKEDIN_CLIENT_IDandLINKEDIN_CLIENT_SECRETare correct - Check credentials in LinkedIn Developer Portal
Issue: "Redirect URI mismatch"
- Ensure
LINKEDIN_REDIRECT_URImatches app configuration in LinkedIn Developer Portal - URIs are case-sensitive
Issue: "Token expired"
- Call
refreshAccessToken()with refresh token - Implement automatic token refresh before expiration
Issue: "Rate limit exceeded"
- Reduce request frequency
- Increase
RATE_LIMIT_PER_MINUTEin.env - Implement exponential backoff
๐ฆ Dependencies
Core Dependencies
- express: Web framework
- node-fetch: HTTP requests
- jsonwebtoken: JWT handling
- dotenv: Environment variables
- axios: HTTP client
- winston: Logging
- helmet: Security headers
- cors: CORS handling
Dev Dependencies
- jest: Testing framework
- eslint: Code linting
- prettier: Code formatting
- nodemon: Development auto-reload
๐ Examples
Basic Usage Example
import LinkedInOAuth from './src/oauth.js';
import LinkedInClient from './src/linkedin.js';
import 'dotenv/config';
async function main() {
// Initialize OAuth
const oauth = new LinkedInOAuth(
process.env.LINKEDIN_CLIENT_ID,
process.env.LINKEDIN_CLIENT_SECRET,
process.env.LINKEDIN_REDIRECT_URI
);
// Get authorization URL
const authUrl = oauth.getAuthorizationUrl();
console.log('Please visit:', authUrl);
// After user authorizes, exchange code for token
const token = await oauth.exchangeCodeForToken(code, state);
// Initialize client with access token
const client = new LinkedInClient(token.accessToken);
// Fetch profile
const profile = await client.getProfile();
console.log('Profile:', profile);
// Get connections
const connections = await client.getConnections(0, 10);
console.log('Connections:', connections);
// Search for people
const searchResults = await client.searchPeople('AI Engineer', 5);
console.log('Search Results:', searchResults);
}
main().catch(console.error);
Express Integration
import express from 'express';
import LinkedInOAuth from './src/oauth.js';
import LinkedInClient from './src/linkedin.js';
const app = express();
const oauth = new LinkedInOAuth(
process.env.LINKEDIN_CLIENT_ID,
process.env.LINKEDIN_CLIENT_SECRET,
process.env.LINKEDIN_REDIRECT_URI
);
// Redirect to LinkedIn login
app.get('/login', (req, res) => {
const authUrl = oauth.getAuthorizationUrl();
res.redirect(authUrl);
});
// Handle OAuth callback
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
try {
const token = await oauth.exchangeCodeForToken(code, state);
req.session.token = token;
res.redirect('/dashboard');
} catch (error) {
res.status(400).send('Authentication failed');
}
});
// Protected route
app.get('/dashboard', async (req, res) => {
const client = new LinkedInClient(req.session.token.accessToken);
const profile = await client.getProfile();
res.json(profile);
});
app.listen(3000, () => console.log('Server running on :3000'));
๐ค Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit changes (
git commit -m 'Add AmazingFeature') - Push to branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Development Guidelines
- Write tests for new features
- Follow ESLint and Prettier rules
- Update documentation
- Add comments for complex logic
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Links
๐ง Support
For issues, questions, or suggestions:
- Open an GitHub Issue
- Contact: your.email@example.com
๐ Acknowledgments
- LinkedIn API Documentation
- MCP Community
- Contributors and testers
Last Updated: 2024 Version: 1.0.0 Status: Active Development
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.