Skip to main content
Glama
Hoyasumii

linkedin-mcp

by Hoyasumii
README.md
<div align="center">

# @hoyasumii/linkedin

**An unofficial MCP server and TypeScript SDK to create, edit and delete your own LinkedIn posts.**

[![npm](https://img.shields.io/npm/v/@hoyasumii/linkedin?color=cb3837&logo=npm)](https://www.npmjs.com/package/@hoyasumii/linkedin)
[![Continuous Delivery](https://github.com/Hoyasumii/linkedin/actions/workflows/cd.yml/badge.svg)](https://github.com/Hoyasumii/linkedin/actions/workflows/cd.yml)
[![Docs](https://img.shields.io/badge/docs-hoyasumii.github.io%2Flinkedin-0a66c2)](https://hoyasumii.github.io/linkedin/)
[![Generated by orval](https://img.shields.io/badge/generated%20by-orval-0a66c2)](https://orval.dev)
[![OpenAPI](https://img.shields.io/badge/OpenAPI-3.1-6ba539?logo=openapiinitiative&logoColor=white)](spec/openapi.yml)
[![Node](https://img.shields.io/badge/Node-%E2%89%A520-5fa04e?logo=nodedotjs&logoColor=white)](https://nodejs.org)
[![Windows](https://img.shields.io/badge/Windows-native%20%2B%20WSL-0078d4)](#windows)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)

</div>

**Documentation: [hoyasumii.github.io/linkedin](https://hoyasumii.github.io/linkedin/)** (English and Português),
also as [`llms.txt`](https://hoyasumii.github.io/linkedin/llms.txt) and
[`llms-full.txt`](https://hoyasumii.github.io/linkedin/llms-full.txt) for LLMs. `linkedin docs` opens it.

| Page                                                                                | What it covers                                            |
| ----------------------------------------------------------------------------------- | --------------------------------------------------------- |
| [Getting started](https://hoyasumii.github.io/linkedin/docs/intro)                  | what LinkedIn allows, installation, a first post          |
| [Creating the LinkedIn app](https://hoyasumii.github.io/linkedin/docs/linkedin-app) | the one-time setup on linkedin.com/developers             |
| [MCP server](https://hoyasumii.github.io/linkedin/docs/mcp/overview)                | setup, every tool, configuration, programmatic use        |
| [SDK](https://hoyasumii.github.io/linkedin/docs/sdk/overview)                       | the client, posts, media, errors                          |
| [CLI](https://hoyasumii.github.io/linkedin/docs/cli/overview)                       | `linkedin mcp config/install/status/logout`, Windows, WSL |
| [API reference](https://hoyasumii.github.io/linkedin/docs/api)                      | every exported class, type and function                   |

Unlike its siblings [`@hoyasumii/plane`](https://github.com/Hoyasumii/plane),
[`@hoyasumii/signoz`](https://github.com/Hoyasumii/signoz) and
[`@hoyasumii/libretranslate`](https://github.com/Hoyasumii/libretranslate), this package delivers an **MCP server
and an SDK**. Its CLI only signs you in and registers the server in your AI clients.

1. **MCP server** (`@hoyasumii/linkedin/mcp`, bin `linkedin-mcp`, stdio): `linkedin_create_post`,
   `linkedin_edit_post`, `linkedin_delete_post`, `linkedin_list_posts`, `linkedin_get_post` and `linkedin_whoami`.
2. **SDK** (`createLinkedInClient`): posts with text, images (1 to 20), a video (uploaded in parts), a document or an
   article link; edit the text; delete. Generated by [orval](https://orval.dev) from an OpenAPI 3.1 spec written
   for this package, with LinkedIn's _little_ text format escaped for you.
3. **CLI** (bin `linkedin`): `linkedin mcp config --web` signs you in to LinkedIn from a local page;
   `linkedin mcp install` registers the server in Claude Code, Codex or OpenCode.

> [!IMPORTANT]
> LinkedIn lets any app **write** a member's posts, but not **read** them: `r_member_social` is closed to new
> apps. The server keeps a local list of the posts it created or edited, and its "read" tools show that list.
> Posts made on linkedin.com can still be edited or deleted by their URN or URL.

> [!NOTE]
> An independent, **unofficial** client of LinkedIn's official API, MIT licensed. Not affiliated with or endorsed by
> LinkedIn Corporation. It posts only through an app you create and authorize, as you.

## Installation

```sh
npm i -g @hoyasumii/linkedin     # or: pnpm add -g, or clone + pnpm build + npm i -g .
```

Create [your LinkedIn app](https://hoyasumii.github.io/linkedin/docs/linkedin-app) once (a Company Page, the
**Share on LinkedIn** and **Sign In with LinkedIn using OpenID Connect** products, and the redirect URL
`http://localhost:3769/callback`), then:

```sh
linkedin mcp config --web        # paste the Client ID and Secret, sign in on LinkedIn
linkedin mcp install             # register linkedin-mcp in Claude Code / Codex / OpenCode
```

The token lasts 60 days: run `linkedin mcp config --web` again when `linkedin mcp status` says it expired.

## SDK

```ts
import { createLinkedInClient } from "@hoyasumii/linkedin";

const linkedin = createLinkedInClient({ accessToken: process.env.LINKEDIN_ACCESS_TOKEN! });

const { urn, url } = await linkedin.createPost({ text: "Shipped v1.0 (finally) #release" });
await linkedin.createPost({ text: "Screens", images: ["a.png", { file: "b.png", altText: "The dashboard" }] });
await linkedin.createPost({ text: "Demo", video: { file: "demo.mp4", title: "Demo" }, visibility: "CONNECTIONS" });
await linkedin.createPost({ text: "Our roadmap", document: "roadmap.pdf" });
await linkedin.editPost(urn, { text: "Shipped v1.0.1" });
await linkedin.deletePost(url);
```

A non-2xx answer throws `LinkedInApiError` (`status`, `code`, `serviceErrorCode`, `body`); an expired or missing
sign-in throws `LinkedInAuthError`. The token is never in an error.

## MCP server

| Tool                   | What it does                                                            |
| ---------------------- | ----------------------------------------------------------------------- |
| `linkedin_create_post` | Text, plus images, a video, a document or an article link; or a reshare |
| `linkedin_edit_post`   | Replaces a post's text (LinkedIn does not let media change)             |
| `linkedin_delete_post` | Deletes a post, with `confirm: true`                                    |
| `linkedin_list_posts`  | The posts made or edited through the server (local list)                |
| `linkedin_get_post`    | One of them                                                             |
| `linkedin_whoami`      | Who is signed in, and for how many more days                            |

By hand: `claude mcp add linkedin -s user -- npx -y -p @hoyasumii/linkedin linkedin-mcp`. The server reads the
saved sign-in on every call; `LINKEDIN_ACCESS_TOKEN` in its environment overrides it.

## Windows

Native Windows 10/11 (PowerShell, cmd) and WSL. From WSL, `linkedin mcp install` also reaches the clients
installed on the Windows side. See [Windows and WSL](https://hoyasumii.github.io/linkedin/docs/cli/windows).

## Development

```sh
pnpm install
pnpm codegen        # spec/openapi.yml → src/generated/ (orval)
pnpm test:unit      # a fake LinkedIn on node:http, no network
pnpm test:live      # posts, edits and deletes on the real LinkedIn (.env.test, see env.example)
pnpm docs:dev       # the docs site
```

See [CONTRIBUTING.md](CONTRIBUTING.md).

## Releasing

Every push to `main` runs [`.github/workflows/cd.yml`](.github/workflows/cd.yml): lint, format, types, knip, unit
tests and the build. Then:

- when `package.json`'s `version` is not on npm yet, it publishes it with provenance through
  [npm Trusted Publishing](https://docs.npmjs.com/trusted-publishers) (OIDC, no token in the repository), tags it
  `v<version>` and opens a GitHub release;
- when the push touches `website/` or `src/`, it rebuilds the docs site and deploys it to the `gh-pages` branch.

```sh
# bump "version" in package.json, then:
git commit -am "chore: release 0.1.1"
git push origin main
```

## License

[MIT](LICENSE) © Alan Reis Anjos