Skip to main content
Glama
supersaiyane

AmplifyrMCP

by supersaiyane

AmplifyrMCP

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)


What is This?

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.


All 19 Tools

LinkedIn — Content Creation (4 tools)

1. Authenticate (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:

  1. You say "Authenticate with LinkedIn"

  2. Your browser opens LinkedIn's login page

  3. You approve the connection

  4. AmplifyrMCP stores your credentials locally, encrypted with AES-256-GCM (military-grade encryption)

  5. Tokens auto-refresh for ~1 year, so you only do this once

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.


2. Create Post (linkedin_create_post)

What it does: Publishes a text post to your LinkedIn personal feed.

Features:

  • Up to 3,000 characters per post

  • Optional hashtags (added automatically, no need to type #)

  • Visibility control: 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:

  1. Your text is validated (length, content)

  2. Hashtags are formatted and appended: #ai #devops #sre

  3. An API call is made to LinkedIn's REST API (POST /rest/posts)

  4. The post URL is returned so you can see it live


3. Create Post with Image (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:

  • Supports JPEG, PNG, GIF (max 8MB)

  • Text + image + hashtags in one command

  • Two-step upload handled automatically (initialize → upload binary → create post)

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"

4. Publish Article (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 — Post Management (3 tools)

5. Edit Post (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."

6. Delete Post (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"

7. Upload Media (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 — Engagement (3 tools)

8. Like 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"

9. Get Comments (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:

  • Configurable count (1-100 comments, default 20)

  • Returns comment URNs for use with reply_to_comment

Example:

"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)

10. Reply to Comment (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 — Analytics (4 tools)

11. Get Profile (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/...

12. Get Profile Stats (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.


13. Get Post Stats (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:

  • Impressions (how many times the post appeared in feeds)

  • Likes

  • Comments

  • Shares (how many people reposted it)

  • Clicks (link clicks, "see more" clicks, profile clicks)

Example:

"Show me stats for my post urn:li:share:12345"
→ 📊 Post Stats
  👁️ Impressions: 1,250
  👍 Likes: 42
  💬 Comments: 8
  🔄 Shares: 5
  🖱️ Clicks: 73

14. Search Posts (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:

  • Searches post text (commentary) for matching keywords

  • Configurable result count (1-50, default 10)

  • Returns post URNs for use with other tools (stats, edit, delete)

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 — Scheduling (3 tools)

15. Schedule Post (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:

  1. Your post content is validated (same rules as create_post)

  2. The scheduled time must be at least 5 minutes in the future

  3. Post is saved to a local SQLite database (data/scheduler.db)

  4. A background cron job checks every minute for posts that are due

  5. When the time arrives, the post is published to LinkedIn

  6. If publishing fails, it retries up to 3 times before marking as FAILED

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.


16. List Scheduled Posts (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 time

  • PUBLISHING — Currently being sent to LinkedIn

  • PUBLISHED — Successfully posted, includes the LinkedIn URL

  • FAILED — Failed after 3 retry attempts, includes error message

  • CANCELLED — Manually cancelled before publication

Example:

"Show my scheduled LinkedIn posts"
"List failed scheduled posts"

17. Cancel Scheduled Post (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 (2 tools)

18. Publish to Medium (medium_publish_article)

What it does: Publishes an article to your Medium account.

Features:

  • Supports Markdown and HTML content

  • Up to 5 tags per article

  • Three publish modes: public (visible to everyone), draft (only you can see), unlisted (accessible by link only)

  • Optional canonical URL (tells search engines the original source, useful for cross-posting from your blog)

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.


19. Get Medium Profile (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

Telegram Notifications (Automatic)

Not a tool -- notifications fire automatically in the background when configured.

Events that trigger notifications:

  • LinkedIn post published successfully

  • LinkedIn article shared

  • Scheduled post auto-published at its scheduled time

  • Scheduled post failed (after 3 retries)

  • Medium article published

  • Authentication completed

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.


Quick Start

Prerequisites

  • Node.js 20+ (download)

  • Claude Desktop (download)

  • A personal LinkedIn account

  • (Optional) Telegram account for notifications

  • (Optional) Medium account for article publishing

1. Clone and Build

git clone https://github.com/supersaiyane/AmplifyrMCP.git
cd AmplifyrMCP
npm install
npm run build

2. Create a LinkedIn Developer App

  1. Go to linkedin.com/developers/apps and create an app

  2. Auth tab: Add redirect URL http://localhost:3456/callback

  3. Products tab: Request access to Share on LinkedIn and Sign In with LinkedIn using OpenID Connect

  4. Auth tab: Copy your Client ID and Client Secret

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

3. Configure

cp .env.example .env

Set the two required values in .env:

LINKEDIN_CLIENT_ID=your_client_id
LINKEDIN_CLIENT_SECRET=your_client_secret

4. Connect to Claude Desktop

Edit your Claude Desktop config:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %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"
      }
    }
  }
}

5. Authenticate

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.


Optional Integrations

Telegram Notifications

Get push notifications when posts publish, scheduled posts fire, or something fails.

  1. Message @BotFather on Telegram, send /newbot, get your bot token

  2. Message your bot, visit https://api.telegram.org/bot<TOKEN>/getUpdates to get your chat ID

  3. Add to .env:

    TELEGRAM_BOT_TOKEN=your_bot_token
    TELEGRAM_CHAT_ID=your_chat_id

See Telegram Setup for the full guide.

Medium Publishing

Publish articles to Medium with markdown/HTML, tags, and draft/public/unlisted modes.

  1. Go to medium.com/me/settings/security

  2. Create an integration token

  3. Add to .env:

    MEDIUM_INTEGRATION_TOKEN=your_token

See Medium Setup for the full guide.


How Things Work Under the Hood

The MCP Protocol

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:

  1. Claude sees the available tools (registered by AmplifyrMCP)

  2. Claude decides which tool to call based on your request

  3. Claude sends a structured request to the tool (e.g., {text: "...", visibility: "PUBLIC"})

  4. AmplifyrMCP executes the tool (calls LinkedIn API)

  5. AmplifyrMCP returns the result to Claude

  6. Claude shows you the result in human-readable format

Authentication Flow

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"

Post Scheduling Architecture

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

Rate Limiting

LinkedIn has API rate limits. AmplifyrMCP enforces them locally before hitting the API:

  • Posts: Max 100 per day (sliding 24-hour window)

  • API calls: Max 150 per minute (sliding 60-second window)

If you hit a limit, you'll get a clear error with a "retry after X seconds" message.

Retry Logic

When LinkedIn's API returns a temporary error:

  • HTTP 429 (rate limited): Waits for the Retry-After header value, then retries

  • HTTP 500/502/503/504 (server error): Retries with exponential backoff (1s, 2s, 4s)

  • Network errors (timeout, connection reset): Same exponential backoff

  • Max 3 retries per request, with random jitter to avoid thundering herd


Architecture

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


Automation Examples

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


Testing

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


Development

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

Project Structure

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.


Troubleshooting

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.


Documentation

Full wiki with 18 pages covering setup, usage, architecture, and troubleshooting:


License

MIT

F
license - not found
-
quality - not tested
C
maintenance

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/supersaiyane/AmplifyrMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server