linkedin-mcp
# @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
Scored across 6 tools
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.
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.
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.
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.