LinkedIn MCP Server
Enables AI-powered LinkedIn post creation, content generation, and screenshot capture through a unified Model Context Protocol interface.
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
- Go to LinkedIn Developers
- Click Create app
- 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
- Click Create app
2. Get API Credentials
- Navigate to Auth tab
- Copy Client ID and Client Secret
- Add redirect URL:
http://localhost:3000/callback - Request necessary permissions:
w_member_social- Create postsr_liteprofile- Read profiler_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
- Go to LinkedIn Token Tools
- Select your app
- Select required scopes
- Click Request access token
- 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_msparameter - 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
.envfile 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:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- 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
- Built with Model Context Protocol
- Uses Puppeteer for screenshots
- Powered by Bun runtime
- AI providers: OpenAI, Google Gemini, OpenRouter
Happy posting! 🚀
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。