musebot
New to Muse? Join at muse.ai/join and use invite code Referral: using this code gives the site owner credits.

muse linkedin connector

Muse connects to LinkedIn for profile and posting management

How to add it to Muse

This connector is a skill: copy its SKILL.md (from the copy box or the source) into a Muse chat and ask Muse to set it up. If it needs a key, enter it only where Muse asks for a credential (its secure store), never in the chat. Meta doesn't review custom connectors.

New to Muse? Join at muse.ai/join and use invite code Referral: using this code gives the site owner credits.

There's no official Muse install link, so musebot never makes one up. Connector For the Muse app, web or WhatsApp.

Setup prompt to copy

---
name: "linkedin_token"
description: "Work with the user's own LinkedIn account through LinkedIn's official API: fetch the authenticated member's profile; publish posts in every organic format (text, image/multi-image, video, document, article, poll, celebration, reshare, @mentions) with per-post audience control; schedule posts; and edit or delete published posts. Comments and reactions are implemented but require LinkedIn's vetted Community Management scope. Use for LinkedIn profile lookups and LinkedIn posting. Does not cover job search/apply, inbox messaging, people search, or connection invitations — LinkedIn restricts those to partner programs and they are unavailable to this connector."
---

# LinkedIn

## Purpose
Give Muse these capabilities on the user's own LinkedIn account, via
the official API only: read the member's profile; publish, schedule,
edit, and delete posts as the member; and (once LinkedIn approves the
extra scope) comment and react. No browser automation is involved.

## Tooling
- `bin/linkedin_profile.py` — prints the authenticated member's profile
  (OpenID Connect `GET /v2/userinfo`). `--status` is the connector
  health check: compact proof the stored token works.
- `bin/linkedin_post.py` — publishes or schedules a post via
  `POST /rest/posts`. Content types: text, image (repeatable; 2+ =
  multi-image), `--video` (with `--video-captions`/`--video-thumbnail`),
  `--document`, `--article-url`, `--poll-*`, `--celebration-*`,
  `--reshare <URN>`, and `--mention 'Name=URN'` (@mentions). Audience/
  interaction flags: `--visibility public|connections|logged_in`,
  `--comments anyone|connections|none` (recorded intent — LinkedIn's
  public API has no comment-control field; the script surfaces this
  rather than faking it), `--disable-reshare`, and `--schedule-at
  <ISO8601>` to queue the post locally for Muse to publish at that
  time (`--list-queue`, `--cancel-queued`, `--publish-due`; failed
  posts stop after 3 attempts). Published posts are recorded locally
  (`--history`: URN + URL) because reading them back needs a restricted
  scope; `--edit-post <URN>` and `--delete-post <URN>` manage them.
  Always run with `--dry-run` first and show the user the exact payload
  before a real post.
- `bin/linkedin_engage.py` — `comment`, `react`, `unreact`,
  `delete-comment` on a post URN. **Scope-gated:** these need
  `w_member_social_feed` (vetted Community Management API product);
  with a standard token they return 403 and the CLI explains why.
- `bin/linkedin_api.py` — shared client (auth, headers, error handling).

## Auth
The working connection is an **access-token registration**
(`custom.linkedin-token`): the user mints a token from their own
LinkedIn app via a manual authorization-code exchange and registers
the token itself with Muse. The OAuth registration
(`custom.linkedin`, Client ID/Secret entered on Muse's connect page)
currently **fails at Muse's hosted token exchange** with
`401 invalid_client` despite proven-good credentials — a known
Muse-side issue, reproduced repeatedly and reported. Full story and
both setup paths: README, Part 2.

The underlying LinkedIn app configuration the token comes from:

- Authorization URL: `https://www.linkedin.com/oauth/v2/authorization`
- Token URL: `https://www.linkedin.com/oauth/v2/accessToken`
  (client_id + client_secret in the POST body)
- API hosts: `api.linkedin.com` (API calls) and `www.linkedin.com`
  (media upload URLs returned by initializeUpload; uploads carry the
  Authorization header, the file's real Content-Type, and a
  browser-like User-Agent — a bare PUT is rejected with an HTML 400)
- Scopes: `openid profile email w_member_social`
- REST version pinned in `bin/linkedin_api.py` (`202608`; override with
  `LINKEDIN_API_VERSION`). LinkedIn retires each monthly version after
  ~a year — bump it on a yearly cadence.
- Redirect URI registered on the LinkedIn app:
  `https://agent.meta.ai/api/hatch/oauth/callback`

The credential lives in Muse's Secure Credentials Store; the scripts
resolve it at call time through the connector helper (see the integration
point in `bin/linkedin_api.py`). Never ask the user to paste a token or
secret into chat, and never print or log a token.

> Note: after the connector is connected, this skill is regenerated by the
> connector scaffolder, which rewrites the Tooling/Auth sections with the
> live credential mechanics. Keep the Operating Rules below when merging.

## Operating Rules
1. **Posting needs explicit approval.** Show the user the final post text,
   media, visibility, and requested comment setting, plus the `--dry-run`
   payload, and post only after they approve that exact content. An edit
   after approval needs a new approval. Scheduling captures that approval
   at queue time — never queue or publish anything unapproved.
2. **Profile reads are read-only** and may run without extra approval.
3. **Comment control is UI-only.** If the user asks for connections-only
   or no comments, say plainly that the API cannot set it, publish only
   with their OK on that basis, and remind them to set it on the post in
   LinkedIn afterwards. Never claim it was applied.
4. A 401/403 is a question about the request before the credential: check
   the token was attached, then token expiry (~60 days), then that the
   app's products granted the needed scope (`openid profile` for reads,
   `w_member_social` for posting). Reconnect rather than retrying an
   unchanged failing request.
5. **Engagement is a write too.** Comments and reactions act publicly
   as the user: show the exact text/target and get approval first, same
   as posting. Edits and deletes of published posts likewise need the
   user's OK for that specific post; a delete is destructive, so name
   the post (use `--history` for its URL) before running it.
6. **Never request `w_member_social_feed` early.** That scope unlocks
   comments/reactions but is granted only via the vetted Community
   Management API product

SKILL.md from the repo, MIT licence. Read it before pasting. Muse asks before it acts.

What the source says

A custom connector for Meta Muse AI Agent to connect linkedIn

Quoted from the source, by gops22. Licence: MIT.

Where we found it