A Model Context Protocol (MCP) server for creating and managing LinkedIn posts. This server enables AI assistants to interact with LinkedIn's API to create text posts, image posts, and retrieve profile information.
- ✅ Create text-only LinkedIn posts
- ✅ Create LinkedIn posts with images
- ✅ Get authenticated user's profile information
- ✅ Validate LinkedIn API credentials
- ✅ Support for post visibility settings (PUBLIC, CONNECTIONS)
- ✅ Compatible with Claude Desktop and Windsurf IDE
- Node.js 18 or higher
- npm or yarn
- LinkedIn Developer App with OAuth 2.0 credentials
- Required LinkedIn API permissions:
w_member_social- Create and manage postsr_liteprofile(optional) - Access basic profile informationr_emailaddress(optional) - Access email address
- Clone the repository:
git clone https://github.com/yourusername/linkedin-mcp.git
cd linkedin-mcp- Install dependencies:
npm install- Build the TypeScript code:
npm run build- Go to LinkedIn Developers
- Click "Create app"
- Fill in the required information:
- App name: Choose a descriptive name (e.g., "My LinkedIn MCP Server")
- LinkedIn Page: Select or create a company page to associate with your app
- App logo: Upload an app logo (120x120px minimum)
- Check the legal agreement checkbox
- Click "Create app"
- In your app dashboard, go to the "Auth" tab
- Add Redirect URLs (for OAuth flow):
http://localhost:8080/callbackhttps://oauth.pstmn.io/v1/callback(for Postman testing)
- Note your credentials:
- Client ID: Found at the top of the Auth page
- Client Secret: Found below the Client ID (keep this secure!)
- Go to the "Products" tab in your app dashboard
- Request access to the following products:
- Share on LinkedIn - Required for posting capabilities
- Sign In with LinkedIn - Required for authentication
- These products will be automatically approved for development
- In your app dashboard, look for "OAuth Token Tools" or similar in the Auth section
- Select the scopes:
w_member_social - Click "Generate token"
- Copy the access token (valid for 60 days)
- Open Postman and create a new request
- Go to the Authorization tab
- Select Type: OAuth 2.0
- Configure:
- Token Name: LinkedIn Token
- Grant Type: Authorization Code
- Callback URL:
https://oauth.pstmn.io/v1/callback - Auth URL:
https://www.linkedin.com/oauth/v2/authorization - Access Token URL:
https://www.linkedin.com/oauth/v2/accessToken - Client ID: Your LinkedIn app's Client ID
- Client Secret: Your LinkedIn app's Client Secret
- Scope:
w_member_social r_liteprofile r_emailaddress
- Click "Get New Access Token"
- Authorize the app in the browser window that opens
- Copy the access token from Postman
- Direct users to:
https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:8080/callback&scope=w_member_social%20r_liteprofile%20r_emailaddress
-
After authorization, extract the
codeparameter from the callback URL -
Exchange the code for an access token:
curl -X POST https://www.linkedin.com/oauth/v2/accessToken \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code' \
-d 'code=YOUR_AUTH_CODE' \
-d 'redirect_uri=http://localhost:8080/callback' \
-d 'client_id=YOUR_CLIENT_ID' \
-d 'client_secret=YOUR_CLIENT_SECRET'Create a .env file in the project root:
# Required LinkedIn API credentials
LINKEDIN_CLIENT_ID=your_client_id_here
LINKEDIN_CLIENT_SECRET=your_client_secret_here
LINKEDIN_ACCESS_TOKEN=your_access_token_here
# Optional: API version (default: 202406)
LINKEDIN_API_VERSION=202406-
Find your Claude Desktop configuration file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%/Claude/claude_desktop_config.json
- macOS:
-
Add the LinkedIn MCP server configuration:
{
"mcpServers": {
"linkedin-mcp": {
"command": "/usr/bin/env",
"args": ["node", "/path/to/linkedin-mcp/build/index.js"],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin",
"LINKEDIN_CLIENT_ID": "your_client_id",
"LINKEDIN_CLIENT_SECRET": "your_client_secret",
"LINKEDIN_ACCESS_TOKEN": "your_access_token",
"LINKEDIN_API_VERSION": "202406"
}
}
}
}- For macOS users with Homebrew Node.js:
{
"mcpServers": {
"linkedin-mcp": {
"command": "/usr/bin/env",
"args": ["node", "/path/to/linkedin-mcp/build/index.js"],
"env": {
"PATH": "/opt/homebrew/opt/node@20/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin",
"LINKEDIN_CLIENT_ID": "your_client_id",
"LINKEDIN_CLIENT_SECRET": "your_client_secret",
"LINKEDIN_ACCESS_TOKEN": "your_access_token",
"LINKEDIN_API_VERSION": "202406"
}
}
}
}-
Restart Claude Desktop
-
Verify the server is running:
- Look for the tools icon (🔨) in Claude Desktop
- You should see the LinkedIn MCP server listed
-
Create or edit the Windsurf MCP configuration file:
- Location:
~/.codeium/windsurf/mcp_config.json
- Location:
-
Add the LinkedIn MCP server configuration:
{
"mcpServers": {
"linkedin-mcp": {
"command": "/usr/bin/env",
"args": ["node", "/path/to/linkedin-mcp/build/index.js"],
"env": {
"PATH": "/opt/homebrew/opt/node@20/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin",
"LINKEDIN_CLIENT_ID": "your_client_id",
"LINKEDIN_CLIENT_SECRET": "your_client_secret",
"LINKEDIN_ACCESS_TOKEN": "your_access_token",
"LINKEDIN_API_VERSION": "202406"
}
}
}
}- Enable MCP in Windsurf:
- Open Windsurf Settings (Cmd+Shift+P → "Open Windsurf Settings")
- Navigate to the "Cascade" section
- Enable Model Context Protocol
- Restart or refresh the MCP servers
Create a text-only LinkedIn post.
Parameters:
text(required): The text content of the post (max 3000 characters)visibility(optional): Post visibility - "PUBLIC" or "CONNECTIONS" (default: "PUBLIC")
Example:
Create a LinkedIn post saying "Excited to share my latest project!"
Create a LinkedIn post with an image.
Parameters:
text(required): The text content of the postimageUrl(required): URL of the image to includevisibility(optional): Post visibility - "PUBLIC" or "CONNECTIONS" (default: "PUBLIC")
Example:
Post to LinkedIn with the text "Check out this amazing view!" and image https://example.com/image.jpg
Get the authenticated user's LinkedIn profile information.
Note: Requires additional profile permissions that may not be available with basic app access.
Validate that the LinkedIn credentials are working correctly.
npm run devnpm run buildnpm test- Ensure your app has the required products enabled (Share on LinkedIn)
- Verify your access token has the
w_member_socialscope - Check that your access token hasn't expired (tokens last 60 days)
- This might indicate an issue with LinkedIn's servers
- Try generating a fresh access token
- Ensure you're using the correct API version
- Make sure you've run
npm install - Rebuild the project with
npm run build - Check that the build directory exists
- Verify the path to Node.js is correct in your configuration
- Ensure all environment variables are properly set
- Check logs in:
- Claude:
~/Library/Logs/Claude/mcp-server-linkedin-mcp.log - Windsurf:
~/.codeium/windsurf/logs/
- Claude:
- Never commit credentials: Always use environment variables
- Keep tokens secure: Treat access tokens like passwords
- Rotate tokens regularly: Generate new tokens before they expire
- Use HTTPS: Always use HTTPS URLs in production
- Validate input: The server validates all inputs before sending to LinkedIn
- Token expiration: Access tokens expire after 60 days
- Rate limits: LinkedIn has rate limits on API calls
- Post length: Maximum 3000 characters for post text
- Image posts: Currently supports single image posts only
- Profile access: Full profile access requires additional permissions
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with the Model Context Protocol SDK
- LinkedIn API documentation and developer resources
- Claude Desktop and Windsurf IDE for MCP support