Governed LinkedIn marketing over MCP — draft, review, publish, comment, and analytics via the official LinkedIn API
Project description
English | 简体中文
Octopus LinkedIn
Governed LinkedIn marketing over MCP. Draft, review, publish, comment, and read engagement on LinkedIn — from Claude Desktop, Claude Code, or any MCP-compatible agent — using the official LinkedIn API.
Most "LinkedIn AI" tooling stops at writing the post. The obvious next step is publishing it — and that's where you want governance, not a black box. Octopus LinkedIn makes the whole loop explicit:
draft → review → approve → publish → comment → analyze
Drafting and approving are local-only — they never touch the network.
publish_draft is the single gate that sends anything out, and it refuses to
publish a draft that hasn't been explicitly approved.
Tools
| Tool | Sends to LinkedIn? | What it does |
|---|---|---|
get_profile |
read | Your identity + a connectivity check |
create_post |
✅ | Publish a text post |
share_link |
✅ | Publish a post with a URL preview card |
share_image |
✅ | Publish a post with one local image |
share_images |
✅ | Publish a post with up to 9 images |
delete_post |
✅ | Delete one of your posts |
list_comments |
read | List comments on your post |
reply_comment |
✅ | Comment on a post you control |
get_post_stats |
read | Likes + comments for a post |
create_draft |
⬜ local | Save a draft (text / link / image) |
list_drafts |
⬜ local | List drafts, optionally by status |
get_draft |
⬜ local | Read one draft |
update_draft |
⬜ local | Edit a draft (resets approval) |
approve_draft |
⬜ local | The review gate |
delete_draft |
⬜ local | Delete a draft |
schedule_draft |
⬜ local | Schedule an approved draft for later |
unschedule_draft |
⬜ local | Clear a draft's scheduled time |
publish_draft |
✅ | Publish an approved draft now |
publish_due |
✅ | Publish all approved drafts whose time has come |
Content intelligence (LLM-backed)
Conditioned on your brand voice; everything stays behind the approval gate.
| Tool | What it does |
|---|---|
llm_info |
Show the active LLM provider/model (config check) |
generate_draft |
Write a post from a brief → saved as a draft |
polish_text / polish_draft |
Tighten clarity and flow |
optimize_text / optimize_draft |
Rework for hook + structure + CTA |
ab_variants |
Generate N distinct A/B variants |
repurpose_url |
Turn an article URL into an original draft (SSRF-guarded) |
triage_comments |
Classify your post's comments + draft replies |
get_voice / set_voice |
Read/update your brand-voice profile |
Plus MCP prompts (draft_post, repurpose_article, reply_to_comments) and
resources (voice://profile, drafts://list) so MCP clients get task
templates and live context, not just raw tool calls.
Scope note: the official API only lets you comment on content you control (your own posts, or an org Page you admin). It cannot auto-comment on arbitrary third-party posts — by design. See docs/ARCHITECTURE.md.
LLM configuration
Set one provider and its key (see .env.example):
LLM_PROVIDER=anthropic # anthropic | openai | gemini
ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY / GEMINI_API_KEY
# LLM_MODEL=claude-sonnet-4-6 # optional override
Quick start
1. Install
pip install octopus-linkedin
This installs two commands: octopus-linkedin (CLI) and octopus-linkedin-mcp
(the MCP server). To work on the project from source instead, see
Development.
2. Create a LinkedIn app
At linkedin.com/developers, create a Standalone app tied to a Company Page, then add these products:
- Share on LinkedIn → grants
w_member_social(posting) - Sign In with LinkedIn using OpenID Connect → grants
openid profile email
In the app's Auth tab, add an authorized redirect URL:
http://localhost:8000/callback
3. Configure
cp .env.example .env
Edit .env and paste your Client ID and Client Secret (Auth tab).
4. Authorize (one time)
python -m linkedin.auth
This opens your browser; log in and approve. A token is cached to token.json
(gitignored, 0600). Member tokens last ~60 days; re-run this when it expires.
5. Run
python server.py
Connect to Claude Code
claude mcp add octopus-linkedin -- octopus-linkedin-mcp
Or add it to your MCP client config:
{
"mcpServers": {
"octopus-linkedin": {
"command": "octopus-linkedin-mcp"
}
}
}
Then just ask: "Draft a LinkedIn post about X, let me review it, then publish."
Example workflow
create_draft— "Save this post about our launch."list_drafts/get_draft— review the wording.approve_draft— sign off.publish_draft— it goes live (and only now).get_post_stats— check likes and comments later.
CLI
The same engine ships as a CLI for scripting and cron:
octopus-linkedin authorize
octopus-linkedin post "Hello, world" --visibility PUBLIC
octopus-linkedin draft "A post to review later"
octopus-linkedin drafts --status approved
octopus-linkedin approve drft_abc123 --note "lgtm"
octopus-linkedin schedule drft_abc123 2026-07-02T09:00:00Z
octopus-linkedin run-scheduler --interval 60 # loop: publish due drafts
octopus-linkedin stats urn:li:share:123
Scheduling
Scheduling is split so nothing publishes by surprise: you schedule_draft an
approved draft for a future UTC time, then a runner actually sends it when
due. Run the runner one of three ways:
octopus-linkedin run-scheduler— a simple foreground loop, oroctopus-linkedin publish-duefromcronevery few minutes, or- the
publish_dueMCP tool on demand.
Only drafts that are both approved and past their time are published.
Development
pip install -e ".[dev]"
ruff check . && ruff format --check . && pytest
See CONTRIBUTING.md.
Roadmap
Shipped:
- Scheduled publishing (publish an approved draft at a future time)
- Multi-image posts (up to 9)
- A standalone CLI alongside the MCP server
- Bilingual docs (English | 简体中文)
Content-intelligence layer (shipped):
- LLM backend — Anthropic / OpenAI / Gemini (write / polish / optimize)
- MCP
prompts+resourcessurface - Draft-from-URL / article repurposing (SSRF-guarded)
- Brand-voice memory (conditions every generation)
- Comment triage on your own posts (classify → draft reply → approve)
- A/B variant generation
Gated (need LinkedIn approval), tracked but not built:
- Company Page posting & engagement (Community Management API)
- Impressions / reach via
memberCreatorPostAnalytics(partner-gated, 2025) - PDF/document posts (need the versioned
/rest/posts+ Documents API)
Contributions to any of these are welcome.
Security
.env and token.json hold credentials and are gitignored — never commit them.
See SECURITY.md for reporting and credential handling.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file octopus_linkedin-0.2.0.tar.gz.
File metadata
- Download URL: octopus_linkedin-0.2.0.tar.gz
- Upload date:
- Size: 50.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27196ef169db4feb37665ee1907cbd88e66897d4ae8e6a0b365cdc6754f2bbd8
|
|
| MD5 |
2423debfb7e7ec19e128be7351252167
|
|
| BLAKE2b-256 |
5ddc30dd469871138f654c387cfd00a4fcc717a65c9cea34165ca77b07c7d934
|
Provenance
The following attestation bundles were made for octopus_linkedin-0.2.0.tar.gz:
Publisher:
publish.yml on octoryn/octopus-linkedin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
octopus_linkedin-0.2.0.tar.gz -
Subject digest:
27196ef169db4feb37665ee1907cbd88e66897d4ae8e6a0b365cdc6754f2bbd8 - Sigstore transparency entry: 2047276286
- Sigstore integration time:
-
Permalink:
octoryn/octopus-linkedin@906fe40114594e6f561dc45c66d5ace5261a5388 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/octoryn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@906fe40114594e6f561dc45c66d5ace5261a5388 -
Trigger Event:
release
-
Statement type:
File details
Details for the file octopus_linkedin-0.2.0-py3-none-any.whl.
File metadata
- Download URL: octopus_linkedin-0.2.0-py3-none-any.whl
- Upload date:
- Size: 37.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cda5a443a6b185232a155c915f913f94815bbc79ce41256afc5e3b6c4ad5eaaa
|
|
| MD5 |
3bdc078b5e1a665f899271aef23ff003
|
|
| BLAKE2b-256 |
91735d5b7b5e2bd2382ab5bb48b8eeca6e3072e06c1b7cf417fbf4bca1ee9a91
|
Provenance
The following attestation bundles were made for octopus_linkedin-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on octoryn/octopus-linkedin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
octopus_linkedin-0.2.0-py3-none-any.whl -
Subject digest:
cda5a443a6b185232a155c915f913f94815bbc79ce41256afc5e3b6c4ad5eaaa - Sigstore transparency entry: 2047276332
- Sigstore integration time:
-
Permalink:
octoryn/octopus-linkedin@906fe40114594e6f561dc45c66d5ace5261a5388 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/octoryn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@906fe40114594e6f561dc45c66d5ace5261a5388 -
Trigger Event:
release
-
Statement type: