LinkedIn MCP Server

LinkedIn MCP Server

Enables AI-powered LinkedIn post creation, content generation, and screenshot capture through a unified Model Context Protocol interface.

Category
Visit Server

README

LinkedIn MCP Server

A production-ready Model Context Protocol (MCP) server for LinkedIn integration with AI-powered content generation and advanced screenshot capabilities. Automate LinkedIn posting, generate engaging content, and capture beautiful screenshotsβ€”all through a unified MCP interface.

Features

  • πŸ€– AI-Powered Content Generation - Generate engaging LinkedIn posts using OpenAI, Google Gemini, or OpenRouter
  • πŸ“Έ Advanced Screenshot Capture - Capture websites, code snippets, and project demos
  • πŸ”„ Approval Workflow - Preview and approve posts before publishing
  • πŸ“Š Analytics - Track post performance and engagement
  • 🎨 Image Processing - Create collages, optimize for LinkedIn, and format code beautifully
  • πŸ” OAuth 2.0 Authentication - Secure LinkedIn API integration
  • πŸ“ Project Analysis - Automatically analyze projects and generate contextual posts

Installation

Prerequisites

  • Bun runtime (latest stable version)
  • Linux environment (tested on Ubuntu/Debian)
  • Chromium browser for screenshots
  • LinkedIn API credentials (see LinkedIn API Setup)

System Dependencies

# Install Chromium and required libraries for Puppeteer
sudo apt-get update
sudo apt-get install -y chromium-browser libgbm1 libasound2

# Optional: Native screenshot tools
sudo apt-get install -y imagemagick

Install Project

# Clone the repository
git clone <your-repo-url>
cd linkedin-mcpserver

# Install dependencies
bun install

# Copy environment template
cp .env.example .env

# Edit .env with your credentials
nano .env

LinkedIn API Setup

1. Create a LinkedIn App

  1. Go to LinkedIn Developers
  2. Click Create app
  3. Fill in app details:
    • App name: Your MCP Server
    • LinkedIn Page: Select or create a page
    • App logo: Upload an icon
    • Privacy policy URL: Your privacy policy
  4. Click Create app

2. Get API Credentials

  1. Navigate to Auth tab
  2. Copy Client ID and Client Secret
  3. Add redirect URL: http://localhost:3000/callback
  4. Request necessary permissions:
    • w_member_social - Create posts
    • r_liteprofile - Read profile
    • r_organization_social - Organization analytics

3. Get Access Token

There are two methods:

Method A: OAuth Flow (Recommended)

import { LinkedInAuth } from './src/linkedin/auth.js';

const auth = new LinkedInAuth();
const authUrl = auth.getAuthorizationUrl();
console.log('Visit:', authUrl);

// After authorization, exchange code for token
const tokens = await auth.exchangeCodeForToken(code);
// Save tokens to .env

Method B: LinkedIn Token Inspector

  1. Go to LinkedIn Token Tools
  2. Select your app
  3. Select required scopes
  4. Click Request access token
  5. Copy the access token to .env

4. Configure Environment

Update .env file:

LINKEDIN_CLIENT_ID=your_client_id_here
LINKEDIN_CLIENT_SECRET=your_client_secret_here
LINKEDIN_ACCESS_TOKEN=your_access_token_here
LINKEDIN_REDIRECT_URI=http://localhost:3000/callback

AI_PROVIDER=openai
OPENAI_API_KEY=your_openai_key_here

Configuration

Environment Variables

Variable Description Default
LINKEDIN_CLIENT_ID LinkedIn app client ID Required
LINKEDIN_CLIENT_SECRET LinkedIn app client secret Required
LINKEDIN_ACCESS_TOKEN LinkedIn access token Required
LINKEDIN_REFRESH_TOKEN LinkedIn refresh token Optional
AI_PROVIDER AI provider: openai, gemini, openrouter openai
OPENAI_API_KEY OpenAI API key Required if using OpenAI
GEMINI_API_KEY Google Gemini API key Required if using Gemini
OPENROUTER_API_KEY OpenRouter API key Required if using OpenRouter
AI_MODEL AI model name gpt-4
SCREENSHOT_OUTPUT_DIR Screenshot output directory ./screenshots
SCREENSHOT_DEFAULT_WIDTH Default viewport width 1920
SCREENSHOT_DEFAULT_HEIGHT Default viewport height 1080
SCREENSHOT_QUALITY Image quality (1-100) 90

Usage

Running the Server

# Development mode
bun run dev

# Production mode
bun run start

Using with MCP Clients

VS Code / Cline Configuration

Add to your MCP settings (e.g., ~/.cline/mcp_settings.json):

{
  "mcpServers": {
    "linkedin": {
      "command": "bun",
      "args": ["run", "/path/to/linkedin-mcpserver/src/index.ts"],
      "env": {
        "LINKEDIN_CLIENT_ID": "your_client_id",
        "LINKEDIN_CLIENT_SECRET": "your_client_secret",
        "LINKEDIN_ACCESS_TOKEN": "your_access_token",
        "OPENAI_API_KEY": "your_openai_key"
      }
    }
  }
}

Available Tools

1. analyze_project

Analyze a project and generate LinkedIn post content.

{
  "name": "analyze_project",
  "arguments": {
    "project_path": "./my-project",
    "include_commits": true,
    "commit_count": 5,
    "tone": "professional",
    "length": "medium",
    "capture_screenshots": true,
    "screenshot_config": {
      "include_demo": true,
      "localhost_url": "http://localhost:3000",
      "pages_to_demo": ["/", "/dashboard", "/settings"]
    }
  }
}

2. create_linkedin_post

Create and publish a LinkedIn post.

{
  "name": "create_linkedin_post",
  "arguments": {
    "content": "Excited to share my new project! πŸš€\n\nBuilt with React, TypeScript, and Tailwind CSS...",
    "visibility": "PUBLIC",
    "media_urls": ["/path/to/screenshot.png"],
    "require_approval": true
  }
}

3. confirm_post

Confirm or reject a pending post.

{
  "name": "confirm_post",
  "arguments": {
    "request_id": "preview-1234567890",
    "approved": true
  }
}

4. preview_post

Preview a post before publishing.

{
  "name": "preview_post",
  "arguments": {
    "content": "My post content...",
    "visibility": "PUBLIC"
  }
}

5. capture_screenshot

Capture screenshot from URL.

{
  "name": "capture_screenshot",
  "arguments": {
    "source_type": "url",
    "source": "https://example.com",
    "viewport_width": 1920,
    "viewport_height": 1080,
    "full_page": false
  }
}

6. capture_project_demo

Capture multiple pages for project demo.

{
  "name": "capture_project_demo",
  "arguments": {
    "project_url": "http://localhost:3000",
    "pages_to_capture": ["/", "/features", "/pricing"],
    "include_mobile_view": true,
    "create_collage": true
  }
}

7. capture_code_snippet

Capture beautifully formatted code.

{
  "name": "capture_code_snippet",
  "arguments": {
    "file_path": "./src/components/Hero.tsx",
    "line_start": 10,
    "line_end": 30,
    "theme": "github-dark",
    "show_line_numbers": true
  }
}

8. create_screenshot_collage

Combine multiple screenshots.

{
  "name": "create_screenshot_collage",
  "arguments": {
    "screenshot_paths": ["./img1.png", "./img2.png"],
    "layout": "horizontal",
    "spacing": 20
  }
}

9. get_profile_info

Get LinkedIn profile information.

{
  "name": "get_profile_info",
  "arguments": {}
}

10. get_post_analytics

Get post engagement metrics.

{
  "name": "get_post_analytics",
  "arguments": {
    "post_id": "urn:li:share:1234567890"
  }
}

Example Workflows

Example 1: Full Project Announcement

// 1. Analyze project and generate content
const analysis = await analyzedProject({
  project_path: "./my-app",
  capture_screenshots: true,
  screenshot_config: {
    include_demo: true,
    localhost_url: "http://localhost:3000",
    pages_to_demo: ["/", "/dashboard"]
  },
  tone: "professional",
  length: "medium"
});

// 2. Create post with preview
const post = await createLinkedInPost({
  content: analysis.generated_content,
  media_urls: analysis.screenshots,
  visibility: "PUBLIC",
  require_approval: true
});

// 3. Confirm after review
await confirmPost({
  request_id: post.preview_id,
  approved: true
});

Example 2: Code Snippet Share

// 1. Capture code screenshot
const code = await captureCodeSnippet({
  file_path: "./src/auth/oauth.ts",
  line_start: 45,
  line_end: 75,
  theme: "github-dark"
});

// 2. Post with manual content
await createLinkedInPost({
  content: "Just implemented OAuth 2.0 authentication! πŸ”\n\nHere's the core logic...",
  media_urls: [code.path],
  require_approval: false
});

Example 3: Weekly Progress Update

// Analyze recent commits
const analysis = await analyzeProject({
  include_commits: true,
  commit_count: 20,
  tone: "casual",
  length: "short"
});

// Post update
await createLinkedInPost({
  content: analysis.generated_content,
  visibility: "PUBLIC"
});

Troubleshooting

Authentication Issues

Error: "Invalid access token"

  • Verify token is correct in .env
  • Check if token has expired (LinkedIn tokens expire)
  • Request a new token from LinkedIn Developer Portal

Error: "Insufficient permissions"

  • Verify your app has required scopes: w_member_social, r_liteprofile
  • Re-authorize with correct permissions

Screenshot Issues

Error: "Failed to launch browser"

# Install Chromium
sudo apt-get install chromium-browser

# If on WSL, you may need:
export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
export PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser

Error: "Page load timeout"

  • Increase timeout in code or use delay_ms parameter
  • Check if localhost server is running
  • Verify URL is accessible

API Rate Limits

LinkedIn has rate limits:

  • Posts: 100 per day
  • API calls: Varies by endpoint

The server implements rate limiting and will throw RateLimitError when exceeded.

Memory Issues

If browser instances aren't being cleaned up:

// The server automatically cleans up, but you can force cleanup
import { puppeteerService } from './src/screenshots/puppeteer-service.js';
await puppeteerService.cleanup();

Development

Project Structure

linkedin-mcpserver/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.ts                 # MCP server entry point
β”‚   β”œβ”€β”€ config.ts               # Configuration management
β”‚   β”œβ”€β”€ linkedin/               # LinkedIn API integration
β”‚   β”‚   β”œβ”€β”€ auth.ts
β”‚   β”‚   β”œβ”€β”€ client.ts
β”‚   β”‚   β”œβ”€β”€ posts.ts
β”‚   β”‚   β”œβ”€β”€ media.ts
β”‚   β”‚   └── types.ts
β”‚   β”œβ”€β”€ project-analysis/       # Project analysis & AI
β”‚   β”‚   β”œβ”€β”€ file-reader.ts
β”‚   β”‚   β”œβ”€β”€ git-analyzer.ts
β”‚   β”‚   β”œβ”€β”€ content-generator.ts
β”‚   β”‚   β”œβ”€β”€ context-builder.ts
β”‚   β”‚   └── ai-providers/
β”‚   β”œβ”€β”€ screenshots/            # Screenshot system
β”‚   β”‚   β”œβ”€β”€ capturer.ts
β”‚   β”‚   β”œβ”€β”€ puppeteer-service.ts
β”‚   β”‚   β”œβ”€β”€ code-formatter.ts
β”‚   β”‚   β”œβ”€β”€ image-processor.ts
β”‚   β”‚   └── types.ts
β”‚   β”œβ”€β”€ tools/                  # MCP tools
β”‚   β”‚   β”œβ”€β”€ analyze-project.ts
β”‚   β”‚   β”œβ”€β”€ create-post.ts
β”‚   β”‚   β”œβ”€β”€ capture-screenshot.ts
β”‚   β”‚   └── ...
β”‚   └── utils/                  # Utilities
β”‚       β”œβ”€β”€ logger.ts
β”‚       β”œβ”€β”€ error-handler.ts
β”‚       └── rate-limiter.ts
β”œβ”€β”€ .env.example
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
└── README.md

Running Tests

bun test

Building

bun run build

Security Considerations

  • Never commit .env file with credentials
  • Validate all inputs before posting to LinkedIn
  • Be careful with screenshots - don't capture sensitive data
  • Use approval workflow for important posts
  • Monitor API usage to avoid rate limits
  • Review generated content before posting

Rate Limits

LinkedIn API limits:

  • Posts: 100 per day
  • Profile reads: More lenient
  • Analytics: Limited per hour

The server implements rate limiting to prevent exceeding these limits.

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

License

MIT License - see LICENSE file for details

Support

For issues and questions:

  • GitHub Issues: [Your repo issues page]
  • Documentation: This README
  • LinkedIn API Docs: https://docs.microsoft.com/en-us/linkedin/

Acknowledgments


Happy posting! πŸš€

Recommended Servers

playwright-mcp

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured