Skip to main content
Glama
echohello-dev

linkedin-mcp

README.md
# @echohello/linkedin-mcp

LinkedIn MCP server for Claude, Codex, OpenCode and other MCP clients. TypeScript, stdio transport, member OAuth, and a small tool surface for the signed-in member's profile and text posts.

```bash
npm install
npm run build
LINKEDIN_CLIENT_ID=... LINKEDIN_CLIENT_SECRET=... node dist/index.js
```

## Why

LinkedIn does not ship an MCP server. This one speaks the public member APIs only: three-legged OAuth, OpenID userinfo, and a text post on behalf of the signed-in member. It does not take a browser session cookie, and it does not read other people's data, send messages, or send connection requests.

## What you need

Create an app in the [LinkedIn developer portal](https://www.linkedin.com/developers/) and add:

- Sign In with LinkedIn using OpenID Connect (`openid`, `profile`, `email`)
- Share on LinkedIn (`w_member_social`)

Register this redirect URL exactly:

`http://127.0.0.1:53682/callback`

## Tools

| Tool | Purpose |
|---|---|
| `linkedin_login` | Start member sign-in and return the approval URL |
| `linkedin_finish_login` | Wait for the loopback callback, or exchange a pasted redirect URL |
| `linkedin_status` | Show whether a session is stored, without returning tokens |
| `linkedin_profile` | Read the signed-in member's OpenID profile |
| `linkedin_create_post` | Publish a text post as that member |
| `linkedin_logout` | Delete the stored session |

## Configure

| Variable | Required | Purpose |
|---|---|---|
| `LINKEDIN_CLIENT_ID` | yes | App client id |
| `LINKEDIN_CLIENT_SECRET` | yes | App client secret |
| `LINKEDIN_REDIRECT_URI` | no | Defaults to `http://127.0.0.1:53682/callback` |
| `LINKEDIN_SCOPES` | no | Space-separated override of the default member scopes |
| `LINKEDIN_VERSION` | no | Posts API version header, `YYYYMM`. Defaults to `202609` |
| `LINKEDIN_TOKEN_PATH` | no | Session file. Defaults to `~/.config/echohello/linkedin-mcp/tokens.json` |

The session file is mode `0600`. Tool results never include the access token.

Sign in from a terminal before starting the server, or let the agent call the login tools:

```bash
LINKEDIN_CLIENT_ID=... LINKEDIN_CLIENT_SECRET=... node dist/index.js login
```

MCP client config:

```json
{
  "mcpServers": {
    "linkedin": {
      "command": "node",
      "args": ["/absolute/path/to/linkedin-mcp/dist/index.js"],
      "env": {
        "LINKEDIN_CLIENT_ID": "your-client-id",
        "LINKEDIN_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}
```

## Out of scope

Messaging, invitations, company-page posting, image and video uploads, and reading the member's feed all need products this server does not request. `r_member_social` is a restricted permission and is not part of the default scope set.

## Develop

```bash
npm test
npm run typecheck
```

TDQS

A3.9/5.0

Scored across 6 tools

Disambiguation4/5

Each tool has a distinct function: the login/finish_login pair forms a clear two-step flow, and status, logout, profile, and create_post are all sharply separated. The only mild risk is confusion between linkedin_login and linkedin_finish_login, but descriptions disambiguate the sequence.

Naming Consistency5/5

All six tools use a consistent linkedin_ prefix with snake_case verb/noun naming (linkedin_login, linkedin_finish_login, linkedin_status, etc.). The convention is predictable throughout.

Tool Count5/5

Six tools is well-scoped for an auth-plus-basic-actions server, with each tool earning its place across the session lifecycle and core member operations.

Completeness4/5

The auth lifecycle (login, finish, status, logout) plus profile read and post creation covers the core member flow. Minor gaps exist—no post delete/list, no profile update—but the surface is coherent for its apparent scope.

Maintenance

ActivityMaintained
ResponsivenessNo issues