loading…
Search for a command to run...
loading…
AmplifyrMCP is an MCP server that enables Claude Desktop to manage LinkedIn, Medium, and Telegram accounts through natural language, allowing users to post, sch
AmplifyrMCP is an MCP server that enables Claude Desktop to manage LinkedIn, Medium, and Telegram accounts through natural language, allowing users to post, schedule, engage, and analyze content without leaving the AI assistant.
License: MIT TypeScript Node.js MCP Tests
Amplify your content reach. An MCP server that connects Claude Desktop to LinkedIn, Medium, and Telegram. Manage your entire professional presence through natural language -- post, schedule, engage, analyze, and publish articles, all without leaving your AI assistant.
Author: Gurpreet Singh (linkedin.com/in/gurpreettsengh)
AmplifyrMCP is a bridge between Claude (the AI assistant) and your social media accounts. Instead of opening LinkedIn, typing a post, clicking buttons -- you just tell Claude what you want in plain English and it handles the rest.
How it works in practice:
You: "Post on LinkedIn: Just shipped v2.0 of our API. Feedback welcome!"
Claude: Uses linkedin_create_post tool → post appears on your LinkedIn feed
You: "Show me the stats on my last post"
Claude: Uses linkedin_get_post_stats → Impressions: 1250, Likes: 42, Comments: 8
You: "Reply to the first comment with 'Thanks for the feedback!'"
Claude: Uses linkedin_reply_to_comment → reply posted
Behind the scenes, AmplifyrMCP uses the Model Context Protocol (MCP) -- a standard that lets AI assistants like Claude call external tools. Think of it as giving Claude "hands" to interact with LinkedIn on your behalf.
linkedin_authenticate)What it does: Connects your LinkedIn account to Claude using OAuth 2.0 (the same secure login flow used by "Sign in with Google/LinkedIn" buttons).
How it works:
Why it's secure: Your tokens are encrypted on disk at data/tokens.enc. Even if someone copies the file, they can't read it without your encryption key. Tokens are never logged, even in debug mode.
linkedin_create_post)What it does: Publishes a text post to your LinkedIn personal feed.
Features:
#)PUBLIC (everyone) or CONNECTIONS (your network only)Example prompts:
"Post on LinkedIn: Excited to announce our open-source project!"
"Create a LinkedIn post about AI in DevOps, add hashtags ai, devops, sre"
"Post to connections only: We're hiring engineers. DM me."
What happens behind the scenes:
#ai #devops #srePOST /rest/posts)linkedin_create_post_with_image)What it does: Uploads an image and creates a post with it attached -- all in one step. No need to upload the image separately first.
Features:
Example prompts:
"Post on LinkedIn with image ~/Desktop/infographic.png: Check out our Q1 results!"
"Create a post with image ~/Photos/team.jpg about our hackathon, add hashtags hackathon, teamwork"
linkedin_publish_article)What it does: Shares an article URL as a rich LinkedIn post with title, description, and optional cover image.
Important: LinkedIn's API requires a source URL for articles. This creates an article-style post that links to your content (blog, Medium article, etc.), not a native LinkedIn article.
Example prompts:
"Share my article 'Building MCP Servers' from https://myblog.com/mcp on LinkedIn"
"Publish an article with title 'AI in 2026' from https://example.com/ai with cover image ~/Desktop/cover.png"
linkedin_edit_post)What it does: Updates the text of an existing LinkedIn post. Useful for fixing typos, adding context, or updating information after publishing.
Input: The post URN (returned when you create a post) and the new text.
Example:
"Edit my post urn:li:share:12345 to say: Updated: We're now hiring for 3 roles, not 2."
linkedin_delete_post)What it does: Permanently removes a LinkedIn post from your feed. This cannot be undone.
Example:
"Delete my LinkedIn post urn:li:share:12345"
linkedin_upload_media)What it does: Uploads an image to LinkedIn and returns a URN (a unique identifier) that you can reference when creating posts. This is the manual two-step approach -- most users should use create_post_with_image instead.
Supported formats: JPEG, PNG, GIF (max 8MB)
Example:
"Upload ~/Desktop/diagram.png to LinkedIn"
→ Returns: urn:li:image:D4E10... (use this in your next post)
linkedin_like_post)What it does: Likes a LinkedIn post. You can like your own posts or other people's posts.
Example:
"Like the post urn:li:share:12345"
linkedin_get_comments)What it does: Fetches all comments on a specific post. Returns each comment's author, text, timestamp, and comment URN (needed for replying).
Features:
reply_to_commentExample:
"Show me comments on my post urn:li:share:12345"
→ 1. [2026-04-10T08:15:00Z] urn:li:person:abc
"Great post! Really insightful."
URN: urn:li:comment:(urn:li:share:12345,456)
linkedin_reply_to_comment)What it does: Replies to a specific comment on your post. Useful for engaging with your audience without leaving Claude.
Workflow: First use get_comments to see comments and their URNs, then reply to specific ones.
Example:
"Show comments on urn:li:share:12345"
→ (see comment URNs)
"Reply to comment urn:li:comment:(urn:li:share:12345,456) with 'Thanks for reading! Glad you found it useful.'"
→ Reply posted successfully!
linkedin_get_profile)What it does: Fetches your authenticated LinkedIn profile information.
Returns: Your name, LinkedIn member URN (your unique ID), and profile picture URL.
Example:
"Show my LinkedIn profile"
→ Name: Gurpreet Singh
→ URN: urn:li:person:abc123
→ Picture: https://media.licdn.com/...
linkedin_get_profile_stats)What it does: Fetches your profile-level statistics -- follower count, and where available, profile views and search appearances.
Example:
"How many LinkedIn followers do I have?"
→ Followers: 4,832
Note: Profile views and search appearances require additional API permissions that may not be available with all LinkedIn app configurations.
linkedin_get_post_stats)What it does: Fetches detailed analytics for a specific post -- how many people saw it, engaged with it, and clicked through.
Returns:
Example:
"Show me stats for my post urn:li:share:12345"
→ 📊 Post Stats
👁️ Impressions: 1,250
👍 Likes: 42
💬 Comments: 8
🔄 Shares: 5
🖱️ Clicks: 73
linkedin_search_posts)What it does: Searches your own LinkedIn posts by keyword or hashtag. Useful for finding old posts to reference, reshare, or check stats on.
Features:
Example:
"Search my LinkedIn posts for 'kubernetes'"
→ 🔍 Search results for "kubernetes" (2)
1. [2026-04-01] Kubernetes is becoming invisible...
URN: urn:li:share:111
2. [2026-03-15] Our K8s migration taught me...
URN: urn:li:share:222
linkedin_schedule_post)What it does: Queues a post for future publication. The post is stored in a local SQLite database and automatically published when the scheduled time arrives.
How scheduling works:
create_post)data/scheduler.db)Example:
"Schedule a LinkedIn post for tomorrow at 9am: Big announcement coming soon!"
Important: The schedule uses your server's clock. Make sure your machine's timezone is correct.
linkedin_list_scheduled)What it does: Shows all posts in the scheduling queue with their current status.
Status values:
PENDING — Waiting to be published at the scheduled timePUBLISHING — Currently being sent to LinkedInPUBLISHED — Successfully posted, includes the LinkedIn URLFAILED — Failed after 3 retry attempts, includes error messageCANCELLED — Manually cancelled before publicationExample:
"Show my scheduled LinkedIn posts"
"List failed scheduled posts"
linkedin_cancel_scheduled)What it does: Cancels a pending scheduled post before it's published.
Example:
"List my pending scheduled posts"
→ [PENDING] 2026-04-15T09:00:00Z — "Big announcement..." (ID: fc557a0f-...)
"Cancel scheduled post fc557a0f-2833-40a5-9805-a75a017a92c1"
→ Scheduled post cancelled.
medium_publish_article)What it does: Publishes an article to your Medium account.
Features:
public (visible to everyone), draft (only you can see), unlisted (accessible by link only)Example:
"Publish an article on Medium about observability in banking, tag it with sre, devops, observability"
Setup required: You need a Medium integration token. See Medium Setup.
medium_get_profile)What it does: Fetches your Medium account information -- username, display name, profile URL.
Example:
"Show my Medium profile"
→ Username: @gurpreetsingh
→ URL: https://medium.com/@gurpreetsingh
Not a tool -- notifications fire automatically in the background when configured.
Events that trigger notifications:
Why it's useful: If you schedule posts for the future, you'll get a Telegram ping when they go live (or if they fail). No need to keep checking.
git clone https://github.com/supersaiyane/AmplifyrMCP.git
cd AmplifyrMCP
npm install
npm run build
http://localhost:3456/callbackPosts go to your personal profile, not the company page. The Page association is a LinkedIn requirement for app creation only.
See the full LinkedIn App Setup guide for detailed steps.
cp .env.example .env
Set the two required values in .env:
LINKEDIN_CLIENT_ID=your_client_id
LINKEDIN_CLIENT_SECRET=your_client_secret
Edit your Claude Desktop config:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json{
"mcpServers": {
"linkedin": {
"command": "node",
"args": ["/absolute/path/to/AmplifyrMCP/dist/index.js"],
"env": {
"LINKEDIN_CLIENT_ID": "your_client_id",
"LINKEDIN_CLIENT_SECRET": "your_client_secret",
"TOKEN_ENCRYPTION_KEY": "pick_any_string_at_least_32_characters"
}
}
}
}
Restart Claude Desktop, then in a chat:
"Authenticate with LinkedIn"
Your browser opens, you authorize, done. One-time only -- tokens auto-refresh for ~1 year.
Get push notifications when posts publish, scheduled posts fire, or something fails.
/newbot, get your bot tokenhttps://api.telegram.org/bot<TOKEN>/getUpdates to get your chat ID.env:TELEGRAM_BOT_TOKEN=your_bot_token
TELEGRAM_CHAT_ID=your_chat_id
See Telegram Setup for the full guide.
Publish articles to Medium with markdown/HTML, tags, and draft/public/unlisted modes.
.env:MEDIUM_INTEGRATION_TOKEN=your_token
See Medium Setup for the full guide.
MCP (Model Context Protocol) is a standard created by Anthropic that lets AI assistants call external tools. When you say "post to LinkedIn," Claude doesn't actually know how to talk to LinkedIn. Instead:
{text: "...", visibility: "PUBLIC"})You say "authenticate" → Claude calls linkedin_authenticate tool
→ AmplifyrMCP generates a login URL with a random state token
→ AmplifyrMCP starts a temporary HTTP server on port 3456
→ Your browser opens LinkedIn's login page
→ You approve → LinkedIn redirects to localhost:3456/callback?code=xxx
→ AmplifyrMCP exchanges the code for access + refresh tokens
→ Tokens are encrypted (AES-256-GCM) and saved to data/tokens.enc
→ Temporary server shuts down
→ Claude shows "Authenticated as Gurpreet Singh"
You say "schedule post for tomorrow 9am"
→ Post content + scheduled time saved to SQLite (data/scheduler.db)
→ Background cron job runs every 60 seconds
→ When current time >= scheduled time:
→ Post status: PENDING → PUBLISHING
→ LinkedIn API called
→ Success: status → PUBLISHED, Telegram notification sent
→ Failure: retry up to 3 times, then status → FAILED
LinkedIn has API rate limits. AmplifyrMCP enforces them locally before hitting the API:
If you hit a limit, you'll get a clear error with a "retry after X seconds" message.
When LinkedIn's API returns a temporary error:
Retry-After header value, then retriesClaude Desktop ──► MCP Protocol (stdio) ──► AmplifyrMCP Server (up to 20 tools)
│
├──► LinkedIn App 1 (primary, port 3456)
│ Products: "Share on LinkedIn" + "Sign In"
│ ├── /rest/posts (create, edit, delete, search)
│ ├── /rest/images (upload)
│ └── /rest/networkSizes (followers)
│
├──► LinkedIn App 2 (community, port 3457, optional)
│ Product: "Community Management API" only
│ ├── /rest/socialActions (post stats)
│ ├── /rest/socialActions/{urn}/comments (read/reply)
│ └── /rest/socialActions/{urn}/likes (like)
│
├──► Medium API
├──► Telegram Bot API
│
├──► data/tokens.enc (primary app tokens)
├──► data/community-tokens.enc (community app tokens)
└──► data/scheduler.db (SQLite scheduling queue)
Why two LinkedIn apps? LinkedIn requires the "Community Management API" product to be the only product on an app (for legal/security reasons). Since posting requires "Share on LinkedIn", you need a separate app for engagement features. If you only care about posting/scheduling, one app is enough.
Tech stack: TypeScript, MCP SDK, axios, better-sqlite3, Zod, pino, croner
See Architecture for component details and design decisions.
# Full engagement workflow
"Show stats on my last post. Then show me the comments and reply to anyone who asked a question."
# Content calendar
"Draft 3 LinkedIn posts about AI engineering and schedule them for Tue/Wed/Thu at 10am."
# Blog-to-LinkedIn pipeline
"Read my blog post at [URL], summarize the key points, and post to LinkedIn with hashtags."
# Cross-platform publishing
"Write an article about MCP. Publish on Medium as a draft, then create a LinkedIn post linking to it."
# Post with image
"Create a LinkedIn post with image ~/Desktop/infographic.png about our Q1 results."
# Find and reshare
"Search my posts for 'kubernetes'. Show me stats on the best performing one."
# Batch scheduling
"Here are 5 post ideas. Schedule one per day starting tomorrow at 9am."
See Automation Recipes for 15+ ready-to-paste prompt templates.
All tools are tested with MSW (Mock Service Worker) -- HTTP requests are intercepted at the network level so zero real LinkedIn API calls are made during testing.
npm test # Run all 41 tests
npm run test:watch # Watch mode
Test coverage:
| Area | Tests | What's covered |
|---|---|---|
| Rate limiter | 5 | Window sliding, limit enforcement, retry-after |
| Token store | 5 | Encrypt/decrypt, wrong key, missing file |
| Content formatter | 15 | Formatting, validation, hashtags, edge cases |
| Post scheduler | 6 | Schedule, poll, retry, cancel, past-date |
| New tools | 10 | Stats, comments, reply, delete, edit, like, profile stats, search, post with image |
make dev # Run with hot reload (tsx)
make dev-sse # Run with SSE transport
make test # Run tests
make typecheck # Type check only
make check # Type check + lint + tests
make docker-build # Build Docker image
make docker-run # Run in container
src/
index.ts # Entry point, dependency injection
server.ts # MCP server, 19 tool registrations
config/ # Env validation (Zod), LinkedIn API constants
auth/ # OAuth 2.0, encrypted token storage
api/ # LinkedIn client (14 methods), Medium client, rate limiter, retry
tools/ # 19 tool handlers (one file each)
services/ # Content formatting, media handling, scheduling, notifications
models/ # Zod schemas, error hierarchy, TypeScript types
utils/ # Logger (pino/stderr), AES-256-GCM crypto, UUID
tests/
setup.ts # MSW handlers for all LinkedIn API endpoints
api/ # Rate limiter tests
auth/ # Token store tests
services/ # Content formatter + scheduler tests
tools/ # Tool handler tests (10 tests)
See Contributing for code guidelines and how to add new tools.
| Problem | Solution |
|---|---|
| Server crashes on start | Check LINKEDIN_CLIENT_ID and LINKEDIN_CLIENT_SECRET are set |
| "Directory does not exist" | Create manually: mkdir -p data |
| Posts fail with 403 | Enable "Share on LinkedIn" product in your developer app |
| Posts fail with 426 | LinkedIn API version may need updating -- check src/config/linkedin-api.ts |
| Comments/stats fail with 403 | Enable Community Management API product in LinkedIn Developer Portal (Products tab). This is separate from OAuth scopes. May take 24-48h for approval. Re-authenticate after. |
| "Not authenticated" | Say "Authenticate with LinkedIn" in Claude Desktop |
| Token expired | Auto-refreshes. If refresh fails, re-authenticate |
| Claude Desktop no tools | Verify absolute path in config, run npm run build, restart Claude Desktop |
| JSON parse errors | Rebuild: npm run build |
| Telegram not arriving | Message your bot first, verify token and chat ID |
| Medium tools missing | Set MEDIUM_INTEGRATION_TOKEN and restart |
| Medium 401 error | Generate new token at medium.com/me/settings/security |
See Troubleshooting for detailed symptom-cause-fix entries.
Full wiki with 18 pages covering setup, usage, architecture, and troubleshooting:
| Section | Pages |
|---|---|
| Getting Started | Concepts, Installation, Quick Start, Configuration |
| Architecture | System Overview, Authentication |
| Integrations | LinkedIn App Setup, Telegram Setup, Medium Setup |
| Tools & Automation | Tools Reference, Automation Recipes |
| Operations | Docker Deployment, Troubleshooting |
| Reference | Glossary, FAQ, Contributing |
MIT
Run in your terminal:
claude mcp add amplifyrmcp -- npx Security
Low riskAutomated heuristic from public metadata — not a security guarantee.