
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
Node.js >= 24
A LinkedIn Developer App with appropriate permissions
Installation
npm install -g linkedctlOr run directly:
npx linkedctl --helpQuick Start
Create a LinkedIn app at linkedin.com/developers
Configure OAuth 2.0 credentials
Authenticate:
linkedctl auth login --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRETStart using:
linkedctl post "Hello from LinkedCtl!"
See the OAuth Setup Guide for detailed step-by-step instructions.
MCP Integration
MCP Client Configuration
Add to your Claude Desktop configuration (claude_desktop_config.json):
{
"mcpServers": {
"linkedctl": {
"command": "npx",
"args": ["linkedctl", "mcp"]
}
}
}claude mcp add linkedctl -- npx linkedctl mcpAdd to .cursor/mcp.json in your project root:
{
"mcpServers": {
"linkedctl": {
"command": "npx",
"args": ["linkedctl", "mcp"]
}
}
}Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"linkedctl": {
"command": "npx",
"args": ["linkedctl", "mcp"]
}
}
}Available Tools
All tools accept an optional profile parameter to select a configuration profile.
Authentication
Tool | Description |
| Show the current user's name, email, and profile picture URL |
| Show authentication status for a profile |
| Revoke the access token server-side and clear local credentials |
Posts
Tool | Description |
| Create a post on LinkedIn with optional media, poll, or article attachment |
| Fetch a single post by URN |
| List posts with pagination (supports |
| Update the commentary text of an existing post |
| Delete a post by URN |
post_create supports rich content types:
Parameter | Description |
| Post text content (required) |
|
|
| Save as draft instead of publishing |
| Attach a single image (URN or local file path) |
| Attach a video (URN or local file path) |
| Attach a document (URN or local file path) |
| Attach multiple images (minimum 2) |
| Attach an article link |
| Poll question text |
| Poll answer options (2–4 required when |
|
|
| Post as an organization (numeric ID) |
Comments
Tool | Description |
| Create a comment on a post (supports |
| List comments on a post |
| Get a specific comment by URN |
| Delete a comment by URN |
Reactions
Tool | Description |
| Add a reaction to a post (supports |
| List reactions on a post |
| Remove a reaction from a post (supports |
Organizations
Tool | Description |
| List organizations the authenticated user administers |
| Fetch a single organization by ID |
| Get the follower count for an organization |
Analytics
Tool | Description |
| Get analytics for a single post (impressions, reach, reactions, comments, reshares) |
| Get aggregated analytics across all your posts |
| Get share statistics for an organization (lifetime or time-bucketed) |
Media
Tool | Description |
| 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 |
| LinkedIn API version (e.g. |
| OAuth 2.0 client ID |
| OAuth 2.0 client secret |
| OAuth 2.0 access token |
| OAuth 2.0 refresh token |
| 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:
.linkedctl.yamlin the current working directory~/.linkedctl.yamlin 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) |
|
|
|
|
|
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 workAuthentication 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_SECRETDirect Token
If you already have an access token from another application:
linkedctl auth token --access-token YOUR_TOKENEnvironment Variables
Variable | Description |
| LinkedIn OAuth 2.0 client ID |
| LinkedIn OAuth 2.0 client secret |
| Direct access token (bypasses OAuth flow) |
| LinkedIn API version string (e.g. |
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) |
|
|
|
|
|
The same pattern applies to CLIENT_ID, CLIENT_SECRET, and API_VERSION.
Precedence Order
Configuration values are resolved in this order (highest priority first):
Environment variables (profile-prefixed if a profile is active)
Config file (profile-specific file, or CWD/home fallback)
CLI Reference
Global Options
Option | Description |
| Use a specific configuration profile |
| Force JSON output |
| Suppress informational output |
| Disable color output |
auth — Manage Authentication
Command | Description |
| Configure OAuth client credentials interactively |
| Authenticate via OAuth 2.0 (opens browser) |
| Store a direct access token |
| Show authentication status and token expiry |
| Clear stored credentials from the active profile |
| Refresh the access token using a stored refresh token |
| Revoke the access token server-side and clear local tokens |
auth login options:
Option | Description | Default |
| OAuth 2.0 client ID | from config |
| OAuth 2.0 client secret | from config |
| OAuth 2.0 scopes (space-separated) |
|
auth token options:
Option | Description |
| 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 createCommand | Description |
| Create a post on LinkedIn |
| Fetch a post by URN |
| List posts with pagination |
| Update a post's commentary text |
| Delete a post (with confirmation) |
post create options:
Option | Description | Default |
| Text content (also accepts | |
|
|
|
| Save as draft instead of publishing | |
| Image URN to attach | |
| Local image file to upload and attach | |
| Video URN to attach | |
| Local video file to upload and attach | |
| Document URN to attach | |
| Local document file to upload and attach | |
| Multiple image URNs (comma-separated, minimum 2) | |
| Multiple local image files (comma-separated, minimum 2) | |
| Article URL to attach | |
| Poll question text | |
| Poll option (repeat 2–4 times) | |
|
|
|
| Post as an organization (numeric ID) | |
| Output format ( | auto |
post list options:
Option | Description | Default |
| Number of posts to return (max 100) |
|
| Starting index for pagination |
|
| List posts of an organization (numeric ID) |
comment — Manage Comments
Command | Description |
| Create a comment on a post |
| List comments on a post |
| Get a specific comment by URN |
| Delete a comment (with confirmation) |
comment create options:
Option | Description |
| Comment text (required) |
| Comment as an organization (numeric ID) |
reaction — Manage Reactions
Command | Description |
| Add a reaction to a post |
| List reactions on a post |
| Remove a reaction from a post |
reaction create options:
Option | Description |
|
|
| React as an organization (numeric ID) |
org — Manage Organizations
Command | Description |
| List organizations the authenticated user administers |
| Get organization details |
| Get organization follower count |
media — Upload Media
Command | Description |
| Upload an image (JPG, PNG, GIF) |
| Upload a video |
| 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 |
| Get post analytics (impressions, reach, engagement) |
| Get aggregated analytics across all your posts |
| Get organization share statistics |
Common options:
Option | Description |
| Start of date range (YYYY-MM-DD) |
| End of date range (YYYY-MM-DD) |
|
|
profile — Manage Configuration Profiles
Command | Description |
| Create a new profile |
| List all profiles |
| Show profile details (redacted) |
| Delete a profile (with confirmation) |
profile create options:
Option | Description |
| OAuth 2.0 access token (required) |
| LinkedIn API version, e.g. |
whoami — Show Current User
linkedctl whoami
linkedctl whoami --format jsonOption | Description | Default |
| Output format ( | auto |
completion — Shell Completions
linkedctl completion bash
linkedctl completion zshSecurity
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
--forceis 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
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).
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.