Skip to main content
Glama
sindhujaIBM

linkedin-mcp

README.md
# linkedin-mcp

An MCP (Model Context Protocol) server that lets an AI agent post, comment, and read analytics on LinkedIn — for your personal profile, and optionally a company page you administer.

Point Claude (or any MCP-compatible agent) at this server and it can:

- **post_to_profile** — publish a post to your personal LinkedIn profile
- **post_to_company_page** — publish a post to a company page you administer
- **comment_on_post** — comment on a post as your profile or a company page
- **get_recent_posts** — list recent posts with their URNs, so the agent can find something to comment on or check analytics for
- **get_post_analytics** — impressions, reactions, comments, shares, and clicks for a post

Nothing here talks to LinkedIn except LinkedIn's own official REST API. Your access token stays local, in a `.env` file you control.

---

## 1. Create a LinkedIn Developer App

1. Go to [linkedin.com/developers/apps](https://www.linkedin.com/developers/apps) and create a new app.
2. Under **Products**, add:
   - **Sign In with LinkedIn using OpenID Connect** — lets you look up your own person URN
   - **Share on LinkedIn** — gives you `w_member_social`, the scope that lets you post and comment as yourself
3. If you also want company page posting and analytics, add the product that grants `w_organization_social` / `r_organization_social` on your app (LinkedIn calls this the Community Management API in newer developer accounts, Marketing Developer Platform in older ones). This product is gated — you apply for access from the app's Products tab, and LinkedIn reviews the request. Skip this if you only want personal posting; `post_to_profile`, `comment_on_post`, and `get_recent_posts`/`get_post_analytics` for your profile all work without it.

## 2. Run the OAuth 2.0 flow to get an access token

LinkedIn uses the standard OAuth 2.0 authorization code flow.

**Authorize** (open in a browser, replace `CLIENT_ID` and `REDIRECT_URI` with your app's values):

```text
https://www.linkedin.com/oauth/v2/authorization
  ?response_type=code
  &client_id=CLIENT_ID
  &redirect_uri=REDIRECT_URI
  &scope=openid%20profile%20w_member_social
```

Add `%20r_organization_social%20w_organization_social` to the scope if you added company page access in step 1.

LinkedIn redirects you to `REDIRECT_URI?code=AUTH_CODE`. Grab `AUTH_CODE` from that URL.

**Exchange the code for an access token:**

```bash
curl -X POST https://www.linkedin.com/oauth/v2/accessToken \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTH_CODE" \
  -d "redirect_uri=REDIRECT_URI" \
  -d "client_id=CLIENT_ID" \
  -d "client_secret=CLIENT_SECRET"
```

The response includes `access_token`. It's valid for 60 days — after that, repeat this flow to refresh it.

## 3. Get your person URN

```bash
curl https://api.linkedin.com/v2/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

The `sub` field in the response is your person ID. Your person URN is `urn:li:person:SUB_VALUE`.

## 4. (Optional) Get your organization URN

Only needed for company page features:

```bash
curl "https://api.linkedin.com/v2/organizationalEntityAcls?q=roleAssignee" \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

Find your organization's ID in the response; the URN is `urn:li:organization:ORG_ID`.

## 5. Install

**Option A — npm package:**

```bash
npm install -g @sindhujaks/linkedin-mcp
```

**Option B — clone and build:**

```bash
git clone https://github.com/sindhujaIBM/linkedin-mcp.git
cd linkedin-mcp
npm install
npm run build
```

## 6. Configure your credentials

If you installed via npm, create a `.env` file in the directory you'll run the server from (see `.env.example` in this repo for the template). If you cloned the repo:

```bash
cp .env.example .env
```

Fill in `LINKEDIN_ACCESS_TOKEN` and `LINKEDIN_PERSON_URN` from steps 2–3. Add `LINKEDIN_ORGANIZATION_URN` if you did step 4.

## 7. Add it to Claude

**Claude Code** (npm install):

```bash
claude mcp add linkedin -- linkedin-mcp
```

**Claude Code** (cloned repo):

```bash
claude mcp add linkedin -- node /absolute/path/to/linkedin-mcp/dist/index.js
```

**Claude Desktop** — add this to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "linkedin": {
      "command": "linkedin-mcp"
    }
  }
}
```

(Or `"command": "node", "args": ["/absolute/path/to/linkedin-mcp/dist/index.js"]` if you cloned the repo instead of installing via npm.)

Restart Claude, and the five tools above will be available. You can then just ask, in plain language: "post this to my LinkedIn profile," or "comment 'thanks for reading' on my most recent post," or "how did my last post do?"

---

## Notes

- Access tokens expire after 60 days. When yours does, tool calls will fail with an auth error — re-run the OAuth flow in step 2 and update `.env`.
- `post_to_company_page`, and using `as: "company"` on the other tools, all require `LINKEDIN_ORGANIZATION_URN` to be set — otherwise they return a clear error telling you what's missing.
- This uses LinkedIn's `/v2/ugcPosts` and related endpoints. LinkedIn occasionally changes API versioning requirements for newer developer apps; if a call fails with a version-related error, check LinkedIn's [API versioning docs](https://learn.microsoft.com/en-us/linkedin/marketing/versioning) for the current required header.

## License

MIT

TDQS

A4.1/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a clearly different action and resource: posting to a profile, posting to a company page, commenting, listing recent posts, and fetching analytics. There is no meaningful overlap or ambiguity between the tools.

Naming Consistency5/5

All tool names follow the same snake_case verb-first convention, with clear patterns like post_to_* and get_*. The naming is predictable and makes the purpose of each tool immediately obvious.

Tool Count5/5

Five tools is well-scoped for a LinkedIn content publishing and engagement server. Each tool covers a distinct core operation without unnecessary bloat or missing essentials.

Completeness4/5

The set covers the main lifecycle for LinkedIn posting: create posts, comment, retrieve recent posts, and view analytics. Delete and update operations are absent, but they are not core to the apparent purpose of publishing and measuring engagement.

Maintenance

ActivityMaintained
ResponsivenessNo issues