{"_id":"@egistr/linkedin-mcp","name":"@egistr/linkedin-mcp","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@egistr/linkedin-mcp","version":"1.0.0","description":"Open-source LinkedIn MCP server for AI agents (Claude Code, OpenCode, Cursor). TypeScript, official LinkedIn API, OAuth PKCE, image upload.","type":"module","main":"dist/index.js","bin":{"linkedin-mcp":"dist/index.js"},"author":{"name":"Eggi Satria","email":"egisatriadev@gmail.com","url":"https://github.com/EgiStr"},"license":"MIT","homepage":"https://github.com/EgiStr/linkedin-mcp#readme","repository":{"type":"git","url":"git+https://github.com/EgiStr/linkedin-mcp.git"},"bugs":{"url":"https://github.com/EgiStr/linkedin-mcp/issues"},"keywords":["linkedin","mcp","model-context-protocol","claude","opencode","ai","agent","api","typescript"],"publishConfig":{"access":"public"},"scripts":{"prepublishOnly":"npm run build","start":"node dist/index.js","dev":"tsx watch src/index.ts","build":"tsc","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test":"vitest run","test:watch":"vitest","inspector":"npx @modelcontextprotocol/inspector node dist/index.js"},"engines":{"node":">=18"},"dependencies":{"@modelcontextprotocol/sdk":"^1.6.1","axios":"^1.7.9","zod":"^3.23.8"},"devDependencies":{"@types/node":"^22.20.1","nock":"^14.0.16","tsx":"^4.19.2","typescript":"^5.7.2","vitest":"^4.1.10"},"_id":"@egistr/linkedin-mcp@1.0.0","gitHead":"1cd1dcf2b7e444c4d005e52a654ff6a3c9e894f2","types":"./dist/index.d.ts","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-DP9HcOeJjjL3LjoucaabzKi5/SXr0G4eeVJwBtl20vEWl+ADRbr/Bl3pwpz1aS/wjgzgYPyq+HVFEL42npI61A==","shasum":"7059591623f6df3dc0d91e884bdd80029f81fa3b","tarball":"https://registry.npmjs.org/@egistr/linkedin-mcp/-/linkedin-mcp-1.0.0.tgz","fileCount":47,"unpackedSize":243878,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC/05CDx9jXBQKknKue6BZRWPr5GdtTmwfvmtlWb6butAIhAPA7Z/VkmU1JXmUFybVX/jiyZJWkTS+9Kn6T+WXWhgff"}]},"_npmUser":{"name":"egistr","email":"egisatria2310@gmail.com"},"directories":{},"maintainers":[{"name":"egistr","email":"egisatria2310@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/linkedin-mcp_1.0.0_1783954565766_0.7602037355053501"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-13T14:56:05.591Z","1.0.0":"2026-07-13T14:56:05.901Z","modified":"2026-07-13T14:56:06.127Z"},"maintainers":[{"name":"egistr","email":"egisatria2310@gmail.com"}],"description":"Open-source LinkedIn MCP server for AI agents (Claude Code, OpenCode, Cursor). TypeScript, official LinkedIn API, OAuth PKCE, image upload.","homepage":"https://github.com/EgiStr/linkedin-mcp#readme","keywords":["linkedin","mcp","model-context-protocol","claude","opencode","ai","agent","api","typescript"],"repository":{"type":"git","url":"git+https://github.com/EgiStr/linkedin-mcp.git"},"author":{"name":"Eggi Satria","email":"egisatriadev@gmail.com","url":"https://github.com/EgiStr"},"bugs":{"url":"https://github.com/EgiStr/linkedin-mcp/issues"},"license":"MIT","readme":"# LinkedIn MCP Server\n\n[![npm version](https://img.shields.io/npm/v/@egistr/linkedin-mcp)](https://www.npmjs.com/package/@egistr/linkedin-mcp)\n[![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)\n[![CI](https://github.com/EgiStr/linkedin-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/EgiStr/linkedin-mcp/actions/workflows/ci.yml)\n[![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](package.json)\n\nMCP server for LinkedIn API integration — profiles, posts, feed, and connections.\n\nWorks with Claude Desktop, Cursor, Windsurf, Claude Code, OpenCode, and any MCP-compatible client.\n\n## Features\n\n| Tool | Description | Scope Required |\n|---|---|---|\n| `linkedin_get_user_info` | Get OpenID Connect user info | `openid` |\n| `linkedin_get_my_profile` | Get full LinkedIn profile | `openid` + `r_liteprofile` |\n| `linkedin_create_post` | Publish a LinkedIn post | `w_member_social` |\n| `linkedin_list_posts` | List your/others' posts | `r_member_social` |\n| `linkedin_delete_post` | Delete a LinkedIn post | `w_member_social` |\n| `linkedin_get_feed` | Get your feed activity | `r_member_social` |\n| `linkedin_get_connections` | Get your connections | Partner API |\n| `linkedin_send_message` | Send a direct message | Partner API |\n| `linkedin_search_people` | Search LinkedIn members | Partner API |\n| `linkedin_oauth_login` | OAuth PKCE login flow | — |\n\n## Quick Start\n\n```bash\n# Install from npm (recommended)\nnpx @eggisatriadev/linkedin-mcp\n\n# Or install locally\nnpm install @eggisatriadev/linkedin-mcp\n\n# Set your access token\nexport LINKEDIN_ACCESS_TOKEN=AQX_your_token_here\n\n# Run the server\nnpx @eggisatriadev/linkedin-mcp\n```\n\n### For Claude Desktop\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"linkedin\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@eggisatriadev/linkedin-mcp\"],\n      \"env\": {\n        \"LINKEDIN_ACCESS_TOKEN\": \"AQX_your_token_here\"\n      }\n    }\n  }\n}\n```\n\n### For OpenCode\n\nAdd to your `opencode.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"linkedin\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@eggisatriadev/linkedin-mcp\"],\n      \"env\": {\n        \"LINKEDIN_ACCESS_TOKEN\": \"AQX_your_token_here\"\n      }\n    }\n  }\n}\n```\n\n## Setup\n\n### 1. Create a LinkedIn Developer App\n\n1. Go to https://www.linkedin.com/developers/apps\n2. Create a new app\n3. Add products:\n   - **Sign In with LinkedIn using OpenID Connect** (auto-approved)\n   - **Share on LinkedIn** (for posting capabilities)\n4. Note your **Client ID** and **Client Secret**\n5. Add `http://localhost:8080` as an OAuth redirect URL\n\n### 2. Generate Access Token\n\nThe easiest way is to use the OAuth 2.0 token generator in the LinkedIn Developer Portal:\n\n1. Go to your app → **Auth** tab\n2. In **OAuth 2.0 settings**, find the access token section\n3. Select scopes: `openid`, `profile`, `email`, `w_member_social`\n4. Generate and copy the token\n\n### 3. Run the Server\n\n```bash\n# Install dependencies\nnpm install\n\n# Set your token\nexport LINKEDIN_ACCESS_TOKEN=AQX_your_token_here\n\n# Build and run\nnpm run build\nnpm start\n```\n\n### 4. Connect to Claude Desktop\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"linkedin\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/linkedin-mcp-server/dist/index.js\"],\n      \"env\": {\n        \"LINKEDIN_ACCESS_TOKEN\": \"AQX_your_token_here\"\n      }\n    }\n  }\n}\n```\n\n### 5. Connect to OpenCode\n\nAdd to your `opencode.json` (or use the MCP config):\n\n```json\n{\n  \"mcpServers\": {\n    \"linkedin\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/linkedin-mcp-server/dist/index.js\"],\n      \"env\": {\n        \"LINKEDIN_ACCESS_TOKEN\": \"AQX_your_token_here\"\n      }\n    }\n  }\n}\n```\n\n## OAuth PKCE Login (No Token Required)\n\nSkip step 2 — let the server handle authentication interactively:\n\n```bash\n# Required: set your LinkedIn app credentials\nexport LINKEDIN_CLIENT_ID=your_client_id\nexport LINKEDIN_CLIENT_SECRET=your_client_secret\n\n# Run the server (it will detect no token and guide you)\nnpm run build\nnpm start\n\n# Or from npm package:\nnpx @eggisatriadev/linkedin-mcp\n```\n\nThen call the `linkedin_oauth_login` tool from your MCP client:\n\n1. **port** (optional): Callback server port (default: `8080`)\n2. **open_browser** (optional): Auto-open browser (default: `true`)\n3. **timeout** (optional): Max wait in ms (default: `120000`)\n\nThe flow:\n1. Server starts a local HTTP server on port 8080\n2. Opens your browser to LinkedIn's authorization page\n3. You approve the request\n4. LinkedIn redirects to localhost — server captures the code\n5. Server exchanges the code for an access token via PKCE S256\n6. Token is saved to `~/.config/linkedin-mcp/config.json`\n7. All tools immediately work without further setup\n\n## Media Upload\n\nLinkedIn supports image upload via a 3-step `/rest/images` flow:\n\n1. **Initialize**: `POST /rest/images?action=initializeUpload` → returns `uploadUrl` + `image` URN\n2. **Upload binary**: `PUT {uploadUrl}` with image data\n3. **Attach to post**: Use the image URN as `media.id` in `createPost()`\n\n**Supported formats:** JPEG, PNG, GIF (static)\n**Max file size:** 10 MB\n**Recommended dimensions:** 2048×2048px\n\nImage upload happens automatically when you pass a `media_url` parameter\nto `linkedin_create_post`. The MediaUploader handles retries on expired\nupload URLs and validates format/size before uploading.\n\n## Development\n\n```bash\n# Watch mode (auto-reload)\nnpm run dev\n\n# Build\nnpm run build\n\n# Test with MCP Inspector\nnpm run inspector\n```\n\n## Architecture\n\nThe server follows a layered architecture with four bounded contexts:\n\n```\nlinkedin-mcp-server/\n├── src/\n│   ├── index.ts                 # Entry point: server init, tool registration, health check\n│   ├── types.ts                 # Shared types and enums\n│   ├── services/\n│   │   └── linkedin-client.ts   # LinkedIn API client (14+ methods, error classification)\n│   ├── tools/\n│   │   ├── profile.ts           # Profile tools: getMyProfile, getUserInfo\n│   │   ├── posts.ts             # Posts tools: createPost, listPosts, deletePost\n│   │   ├── network.ts           # Network tools: getFeed, getConnections, sendMessage, searchPeople\n│   │   └── auth.ts              # Auth tool: oauthLogin\n│   ├── auth/\n│   │   ├── oauth.ts             # PKCE OAuth 2.0 flow (RFC 7636)\n│   │   ├── config.ts            # Config file management\n│   │   └── token-store.ts       # Token persistence (env var → config file fallback)\n│   └── media/\n│       └── uploader.ts          # 3-step image upload: init → binary → URN\n├── tests/\n│   ├── linkedin-client.test.ts\n│   ├── tools/\n│   ├── auth/\n│   └── media/\n├── docs/\n│   └── pocket/arch/*/tech-design.md   # Full technical design document\n├── package.json\n├── tsconfig.json\n└── README.md\n```\n\n### Token Resolution Chain\n\n1. `LINKEDIN_ACCESS_TOKEN` env var (highest priority)\n2. `~/.config/linkedin-mcp/config.json` (persistent local token)\n3. OAuth PKCE flow (if `LINKEDIN_CLIENT_ID` + `LINKEDIN_CLIENT_SECRET` are set)\n\nSee [tech-design.md](docs/pocket/arch/2026-07-13-linkedin-mcp-server/tech-design.md) for the full architecture, API contracts, data flow diagrams, and ADRs.\n\n## Contributing\n\nWe welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for:\n\n- Bug reports & feature requests (GitHub Issues)\n- Development setup guide\n- Coding standards & test requirements\n- Pull request guidelines\n\nThis project adheres to a [Code of Conduct](CODE_OF_CONDUCT.md).\n\n## Limitations\n\n- **Connections API**: Requires LinkedIn Partner Program (not available on free tier)\n- **People Search**: Not available via public API (needs Sales Navigator)\n- **Messaging API**: Requires LinkedIn Messaging API (partner program)\n- **Feed**: Limited by API restrictions\n- **Rate Limits**: 100-500 requests/day per app on free tier\n\n## License\n\nMIT — see [LICENSE](LICENSE) for details.\n","readmeFilename":"README.md","_rev":"1-e78d31d30b7a9aaf46d261b36e43d478"}