linkedctl

linkedctl

MCP for what few things LinkedIn allows via API

Category
访问服务器

README

LinkedCtl: The Complete CLI & MCP for LinkedIn

CI CodeQL License

OAuth2 CLI and MCP server for the LinkedIn API.

What It Does

  • Post content — text, images, video, documents, articles, multi-image carousels, and polls
  • Comments & reactions — create, list, and delete comments and reactions on posts
  • Organization support — post, comment, react, and view analytics as an organization
  • Analytics — per-post, per-member, and per-organization statistics
  • Media uploads — upload images, video, and documents to LinkedIn
  • Draft posts — save posts as drafts before publishing
  • OAuth 2.0 authentication with your own LinkedIn app
  • Direct token passing for tokens obtained from other applications
  • MCP server for AI assistant integration (Claude, Cursor, etc.)
  • CLI for scriptable LinkedIn operations

Prerequisites

Installation

npm install -g linkedctl

Or run directly:

npx linkedctl --help

Quick Start

  1. Create a LinkedIn app at linkedin.com/developers
  2. Configure OAuth 2.0 credentials
  3. Authenticate:
    linkedctl auth login --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET
    
  4. Start using:
    linkedctl post "Hello from LinkedCtl!"
    

See the OAuth Setup Guide for detailed step-by-step instructions.

MCP Integration

MCP Client Configuration

<details> <summary><b>Claude Desktop</b></summary>

Add to your Claude Desktop configuration (claude_desktop_config.json):

{
    "mcpServers": {
        "linkedctl": {
            "command": "npx",
            "args": ["linkedctl", "mcp"]
        }
    }
}

</details>

<details> <summary><b>Claude Code</b></summary>

claude mcp add linkedctl -- npx linkedctl mcp

</details>

<details> <summary><b>Cursor</b></summary>

Add to .cursor/mcp.json in your project root:

{
    "mcpServers": {
        "linkedctl": {
            "command": "npx",
            "args": ["linkedctl", "mcp"]
        }
    }
}

</details>

<details> <summary><b>Windsurf</b></summary>

Add to ~/.codeium/windsurf/mcp_config.json:

{
    "mcpServers": {
        "linkedctl": {
            "command": "npx",
            "args": ["linkedctl", "mcp"]
        }
    }
}

</details>

Available Tools

All tools accept an optional profile parameter to select a configuration profile.

Authentication

Tool Description
whoami Show the current user's name, email, and profile picture URL
auth_status Show authentication status for a profile
auth_revoke Revoke the access token server-side and clear local credentials

Posts

Tool Description
post_create Create a post on LinkedIn with optional media, poll, or article attachment
post_get Fetch a single post by URN
post_list List posts with pagination (supports as_org for organization posts)
post_update Update the commentary text of an existing post
post_delete Delete a post by URN

post_create supports rich content types:

Parameter Description
text Post text content (required)
visibility PUBLIC or CONNECTIONS (default PUBLIC)
draft Save as draft instead of publishing
image / image_file Attach a single image (URN or local file path)
video / video_file Attach a video (URN or local file path)
document / document_file Attach a document (URN or local file path)
images / image_files Attach multiple images (minimum 2)
article_url Attach an article link
poll Poll question text
poll_options Poll answer options (2–4 required when poll is set)
poll_duration ONE_DAY, THREE_DAYS, ONE_WEEK, or TWO_WEEKS
as_org Post as an organization (numeric ID)

Comments

Tool Description
comment_create Create a comment on a post (supports as_org)
comment_list List comments on a post
comment_get Get a specific comment by URN
comment_delete Delete a comment by URN

Reactions

Tool Description
reaction_create Add a reaction to a post (supports as_org). Types: LIKE, PRAISE, EMPATHY, INTEREST, APPRECIATION, ENTERTAINMENT
reaction_list List reactions on a post
reaction_delete Remove a reaction from a post (supports as_org)

Organizations

Tool Description
org_list List organizations the authenticated user administers
org_get Fetch a single organization by ID
org_followers Get the follower count for an organization

Analytics

Tool Description
stats_post Get analytics for a single post (impressions, reach, reactions, comments, reshares)
stats_me Get aggregated analytics across all your posts
stats_org Get share statistics for an organization (lifetime or time-bucketed)

Media

Tool Description
document_upload Upload a document to LinkedIn (PDF, DOCX, PPTX, DOC, PPT; max 100 MB)

Configuration

Config File Format

LinkedCtl stores configuration in YAML files. Each file represents a single profile:

api-version: "202601"
oauth:
    client-id: "YOUR_CLIENT_ID"
    client-secret: "YOUR_CLIENT_SECRET"
    access-token: "YOUR_ACCESS_TOKEN"
    refresh-token: "YOUR_REFRESH_TOKEN"
    token-expires-at: "2026-05-03T12:00:00.000Z"

Available keys:

Key Description
api-version LinkedIn API version (e.g. 202601)
oauth.client-id OAuth 2.0 client ID
oauth.client-secret OAuth 2.0 client secret
oauth.access-token OAuth 2.0 access token
oauth.refresh-token OAuth 2.0 refresh token
oauth.token-expires-at Token expiration timestamp (ISO 8601)

Config files are written with 0600 permissions (owner read/write only).

File Location and Precedence

Without a profile, LinkedCtl searches for config files in this order:

  1. .linkedctl.yaml in the current working directory
  2. ~/.linkedctl.yaml in the home directory

The first file found is used. When writing (e.g. after auth login), LinkedCtl writes to the CWD file if it exists, otherwise to the home directory file.

Profiles

Profiles let you manage multiple LinkedIn accounts or configurations. Each profile is stored as a separate YAML file under ~/.linkedctl/:

Profile Config file path
(default) ~/.linkedctl.yaml
work ~/.linkedctl/work.yaml
personal ~/.linkedctl/personal.yaml

Use the --profile flag with any command:

linkedctl --profile work auth login --client-id ID --client-secret SECRET
linkedctl --profile work post "Hello from my work account!"

Manage profiles with the profile command:

linkedctl profile create work --access-token YOUR_TOKEN --api-version 202601
linkedctl profile list
linkedctl profile show work
linkedctl profile delete work

Authentication Methods

OAuth 2.0 (Recommended)

LinkedCtl supports OAuth 2.0 with your own LinkedIn Developer App:

linkedctl auth login --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET

Direct Token

If you already have an access token from another application:

linkedctl auth token --access-token YOUR_TOKEN

Environment Variables

Variable Description
LINKEDCTL_CLIENT_ID LinkedIn OAuth 2.0 client ID
LINKEDCTL_CLIENT_SECRET LinkedIn OAuth 2.0 client secret
LINKEDCTL_ACCESS_TOKEN Direct access token (bypasses OAuth flow)
LINKEDCTL_API_VERSION LinkedIn API version string (e.g. 202601) required

Environment variables take precedence over config file values.

Profile-Prefixed Environment Variables

When using a named profile, LinkedCtl also reads profile-prefixed environment variables. The profile name is uppercased with hyphens converted to underscores:

Profile Variable
(default) LINKEDCTL_ACCESS_TOKEN
work LINKEDCTL_WORK_ACCESS_TOKEN
my-brand LINKEDCTL_MY_BRAND_ACCESS_TOKEN

The same pattern applies to CLIENT_ID, CLIENT_SECRET, and API_VERSION.

Precedence Order

Configuration values are resolved in this order (highest priority first):

  1. Environment variables (profile-prefixed if a profile is active)
  2. Config file (profile-specific file, or CWD/home fallback)

CLI Reference

Global Options

Option Description
--profile <name> Use a specific configuration profile
--json Force JSON output
-q, --quiet Suppress informational output
--no-color Disable color output

auth — Manage Authentication

Command Description
auth setup Configure OAuth client credentials interactively
auth login Authenticate via OAuth 2.0 (opens browser)
auth token Store a direct access token
auth status Show authentication status and token expiry
auth logout Clear stored credentials from the active profile
auth refresh Refresh the access token using a stored refresh token
auth revoke Revoke the access token server-side and clear local tokens

auth login options:

Option Description Default
--client-id <id> OAuth 2.0 client ID from config
--client-secret <secret> OAuth 2.0 client secret from config
--scope <scopes> OAuth 2.0 scopes (space-separated) openid profile w_member_social

auth token options:

Option Description
--access-token <token> Access token to store (required)

post — Manage LinkedIn Posts

# Shorthand: pass text as an argument
linkedctl post "Hello from LinkedCtl!"

# Explicit subcommand
linkedctl post create --text "Hello from LinkedCtl!"

# Pipe content from stdin
echo "Hello from LinkedCtl!" | linkedctl post create
Command Description
post create Create a post on LinkedIn
post get <urn> Fetch a post by URN
post list List posts with pagination
post update <urn> Update a post's commentary text
post delete <urn> Delete a post (with confirmation)

post create options:

Option Description Default
--text <text> Text content (also accepts --text-file, positional, or stdin)
--visibility <visibility> PUBLIC or CONNECTIONS PUBLIC
--draft Save as draft instead of publishing
--image <urn> Image URN to attach
--image-file <path> Local image file to upload and attach
--video <urn> Video URN to attach
--video-file <path> Local video file to upload and attach
--document <urn> Document URN to attach
--document-file <path> Local document file to upload and attach
--images <urns> Multiple image URNs (comma-separated, minimum 2)
--image-files <paths> Multiple local image files (comma-separated, minimum 2)
--article-url <url> Article URL to attach
--poll <question> Poll question text
--option <text> Poll option (repeat 2–4 times)
--poll-duration <duration> ONE_DAY, THREE_DAYS, ONE_WEEK, or TWO_WEEKS THREE_DAYS
--as-org <id> Post as an organization (numeric ID)
--format <format> Output format (json, table) auto

post list options:

Option Description Default
--count <n> Number of posts to return (max 100) 10
--start <n> Starting index for pagination 0
--as-org <id> List posts of an organization (numeric ID)

comment — Manage Comments

Command Description
comment create <post-urn> Create a comment on a post
comment list <post-urn> List comments on a post
comment get <comment-urn> Get a specific comment by URN
comment delete <comment-urn> Delete a comment (with confirmation)

comment create options:

Option Description
--text <text> Comment text (required)
--as-org <id> Comment as an organization (numeric ID)

reaction — Manage Reactions

Command Description
reaction create <urn> Add a reaction to a post
reaction list <urn> List reactions on a post
reaction delete <urn> Remove a reaction from a post

reaction create options:

Option Description
--type <type> LIKE, PRAISE, EMPATHY, INTEREST, APPRECIATION, or ENTERTAINMENT (default LIKE)
--as-org <id> React as an organization (numeric ID)

org — Manage Organizations

Command Description
org list List organizations the authenticated user administers
org get <id> Get organization details
org followers <id> Get organization follower count

media — Upload Media

Command Description
media upload-image <file> Upload an image (JPG, PNG, GIF)
media upload-video <file> Upload a video
media upload-document <file> Upload a document (PDF, DOCX, PPTX, DOC, PPT; max 100 MB)

All media commands accept --as-org <id> and --format json|table.

stats — View Analytics

Command Description
stats post <urn> Get post analytics (impressions, reach, engagement)
stats me Get aggregated analytics across all your posts
stats org <id> Get organization share statistics

Common options:

Option Description
--from <date> / --start <date> Start of date range (YYYY-MM-DD)
--to <date> / --end <date> End of date range (YYYY-MM-DD)
--time-granularity <granularity> DAY or MONTH (org stats only)

profile — Manage Configuration Profiles

Command Description
profile create <name> Create a new profile
profile list List all profiles
profile show [<name>] Show profile details (redacted)
profile delete <name> Delete a profile (with confirmation)

profile create options:

Option Description
--access-token <token> OAuth 2.0 access token (required)
--api-version <version> LinkedIn API version, e.g. 202601 (required)

whoami — Show Current User

linkedctl whoami
linkedctl whoami --format json
Option Description Default
--format <format> Output format (json, table) auto

completion — Shell Completions

linkedctl completion bash
linkedctl completion zsh

Security

  • Dependabot keeps dependencies up to date with automated pull requests
  • CodeQL analysis runs on every push and pull request for automated vulnerability detection
  • Path traversal validation on profile names prevents directory escape attacks
  • Unified auth error handling across all MCP tools provides consistent authentication failure messages
  • Destructive operations (delete post, delete comment, delete profile) require interactive confirmation unless --force is passed

Disclaimer

This is an independent project and is not affiliated with, endorsed by, or associated with LinkedIn Corporation. LinkedIn is a trademark of LinkedIn Corporation.

License

AGPL-3.0-only

Using LinkedCtl as a CLI tool or MCP server: No license obligations — use freely.

Using @linkedctl/core as a library in your project: Your combined work must be licensed under AGPL-3.0 (or a compatible license).

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选