Skip to main content
Glama

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

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

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

Add 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

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

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

-
security - not tested
A
license - permissive license
-
quality - not tested

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/alexey-pelykh/linkedctl'

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