Skip to main content
Glama
Ramankumar6566

linkedin-mcp-server

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

Related MCP server: linkedin-mcp

πŸ“‹ 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

  1. Visit LinkedIn Developers

  2. Create a new app

  3. Copy your Client ID and Client Secret

  4. Add your redirect URI (default: http://localhost:3000/callback)

  5. 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 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

  1. Never commit .env file - Contains sensitive credentials

  2. Use HTTPS in production - Set USE_HTTPS=true and provide SSL certificates

  3. Validate state parameter - CSRF protection in OAuth flow

  4. Store tokens securely - Use environment variables or secure storage

  5. Implement rate limiting - Configured via RATE_LIMIT_PER_MINUTE

  6. Refresh tokens regularly - Call refreshAccessToken() before expiration

  7. Use PKCE flow - Enable with usePKCE: true in OAuth methods

πŸ› Troubleshooting

Common Issues

Issue: "Invalid client credentials"

  • Verify LINKEDIN_CLIENT_ID and LINKEDIN_CLIENT_SECRET are correct

  • Check credentials in LinkedIn Developer Portal

Issue: "Redirect URI mismatch"

  • Ensure LINKEDIN_REDIRECT_URI matches 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_MINUTE in .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:

  1. Fork the repository

  2. Create a feature branch (git checkout -b feature/AmazingFeature)

  3. Commit changes (git commit -m 'Add AmazingFeature')

  4. Push to branch (git push origin feature/AmazingFeature)

  5. 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.

πŸ“§ Support

For issues, questions, or suggestions:

πŸ™ Acknowledgments

  • LinkedIn API Documentation

  • MCP Community

  • Contributors and testers


Last Updated: 2024 Version: 1.0.0 Status: Active Development

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for LinkedIn, enabling posting, liking, commenting, and profile retrieval via official OAuth 2.0. Features CLI, HTTP admin, and optional Telegram bot.
    14 npm
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables LinkedIn API integration for managing profiles, posts, feed, connections, and sending messages through MCP-compatible clients.
    10
    9 npm
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    MCP server providing LinkedIn profile and page access via a stateless OAuth proxy, enabling Claude or MCP clients to interact with LinkedIn data.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for AI-native LinkedIn prospecting. It enables lead research, audience building, conversation management, and controlled outreach actions such as messaging and publishing through an OAuth-protected remote endpoint.
    2
    MIT