Skip to main content
Glama
stepanic

linkedin-poster

by stepanic

linkedin-poster

Poste in deinen eigenen LinkedIn-Feed von Claude Code, einer Shell oder einem Cron-Job. Ein Cloudflare Worker, keine Abhängigkeiten, drei Oberflächen: ein MCP-Server, damit ein Agent direkt veröffentlichen kann, eine HTTP-API für Skripte und ein Sprach-Linter, der sich weigert, Texte zu veröffentlichen, die die Merkmale maschinengeschriebener Prosa tragen.

Gebaut, weil ein guter Beitrag es wert ist, automatisiert zu werden, und ein schlechter Gedankenstrich es nicht wert ist, veröffentlicht zu werden. Auch diese README enthält keine Gedankenstriche, genau das ist der Punkt.

Claude Code ──MCP──┐
                   ├──> Worker ──> LinkedIn Posts API ──> your feed
curl / CI ──HTTP───┘      │
                          └──> KV (one 60-day token) + daily cron reminder

Was es nicht ist

Dies postet als ein Mitglied: du. Es ist kein Planungs-SaaS, kein Multi-Tenant-Tool und es berührt kein Konto anderer. Alles, was es braucht, ist Self-Service; kein LinkedIn-Partnerprogramm ist beteiligt.

Die Einschränkung, die alles prägt

LinkedIn-Zugriffstokens halten 60 Tage, und programmatische Refresh-Tokens sind nur für genehmigte Marketing Developer Platform-Partner verfügbar. Eine Self-Service-App bekommt nie eines. Daran führt kein Weg vorbei, und jeder Leitfaden, der eine einmal eingerichtete LinkedIn-Automatisierung verspricht, ist falsch.

Was es gibt: Solange dein aktuelles Token noch gültig ist und du bei LinkedIn angemeldet bist, überspringt das erneute Aufrufen des Autorisierungs-Endpunkts den Zustimmungsbildschirm und leitet einfach weiter. Die Verlängerung ist also ein Klick alle sieben Wochen, solange du es tust, bevor das Token stirbt. Verpasst du das Zeitfenster, bekommst du den Zustimmungsbildschirm zurück, was zwei Klicks statt einem sind.

Deshalb wird dieser Dienst mit einem Cron-Trigger ausgeliefert. Er zählt die Tage herunter und benachrichtigt dich 14, 7, 3 und 1 Tag vor Ablauf, solange die stillschweigende Verlängerung noch funktioniert.

Einrichtung

1. LinkedIn-Seite (manuell, etwa zehn Minuten)

  1. Du brauchst eine LinkedIn-Seite. Das Entwicklerportal verlangt, dass du die App an eine Seite anhängst und ein Seiten-Administrator sie verifiziert.

  2. Erstelle die App unter linkedin.com/developers. Notiere dir die Client-ID und das Client-Secret.

  3. Produkte-Tab, fordere beide an (sie sind offene Berechtigungen und werden sofort genehmigt):

    • Anmelden mit LinkedIn über OpenID Connectopenid, profile

    • Auf LinkedIn teilenw_member_social

  4. Auth-Tab → füge die Redirect-URL hinzu. Sie muss HTTPS, absolut und zeichengenau mit REDIRECT_URI übereinstimmen: https://your-worker.example.com/auth/callback

2. Worker-Seite

git clone https://github.com/stepanic/linkedin-poster.git
cd linkedin-poster
npm install

# KV to hold the token
npx wrangler kv namespace create TOKENS
npx wrangler kv namespace create TOKENS --preview
# paste both ids into wrangler.jsonc

# edit wrangler.jsonc: name, routes, REDIRECT_URI, account_id

npx wrangler secret put LINKEDIN_CLIENT_ID
npx wrangler secret put LINKEDIN_CLIENT_SECRET
npx wrangler secret put API_TOKEN     # openssl rand -hex 32, guards /post and /mcp
npx wrangler secret put SETUP_KEY     # openssl rand -hex 32, guards /auth/start
npx wrangler secret put NOTIFY_WEBHOOK  # optional, any URL taking a JSON POST

npm run deploy

3. Verbinde dein Konto

Öffne https://your-worker.example.com/auth/start?key=<SETUP_KEY> in einem Browser, genehmige einmal, fertig. Die Seite zeigt dir das Ablaufdatum.

SETUP_KEY ist keine Dekoration. Ohne ihn könnte jeder, der die URL findet, sein LinkedIn-Konto an deinen Worker binden und dein gespeichertes Token überschreiben.

Verwendung mit Claude Code

claude mcp add --transport http linkedin https://your-worker.example.com/mcp \
  --header "Authorization: Bearer $API_TOKEN"

Drei Werkzeuge:

Tool

Was es tut

linkedin_post

Lintet und veröffentlicht dann. Lehnt bei Fehlern ab, außer mit force: true.

linkedin_check

Lintet ohne zu veröffentlichen. Verwende es beim Entwerfen.

linkedin_status

Als wer es postet und wie viele Tage das Token noch hat.

Dann, in einer Sitzung: „Prüfe diesen Entwurf gegen den Linter und poste ihn dann.“

Verwendung aus einer Shell

# dry run: lint only, publish nothing
curl -s -X POST https://your-worker.example.com/post \
  -H "Authorization: Bearer $API_TOKEN" -H 'Content-Type: application/json' \
  -d '{"text":"…","dry_run":true}'

# publish
curl -s -X POST https://your-worker.example.com/post \
  -H "Authorization: Bearer $API_TOKEN" -H 'Content-Type: application/json' \
  -d '{"text":"…","visibility":"PUBLIC"}'

# token state
curl -s https://your-worker.example.com/status -H "Authorization: Bearer $API_TOKEN"

/post gibt 201 mit der Post-URN und ihrer öffentlichen URL zurück, 422, wenn der Linter es blockiert, 503, wenn das Token fehlt oder abgelaufen ist.

Der Linter

Fehler blockieren die Veröffentlichung; Warnungen nicht.

Regel

Schweregrad

Warum

no-em-dash, no-en-dash

Fehler

Das deutlichste Zeichen generierter Prosa. Ein Komma oder ein Punkt funktioniert immer.

max-length

Fehler

LinkedIn lehnt Kommentare über 3000 Zeichen ab.

empty

Fehler

Offensichtlich, aber leicht zu treffen, wenn man aus einer Datei per Pipe einliest.

no-markdown-bold, no-markdown-link, no-markdown-heading, markdown-bullets

Warnung

LinkedIn rendert nichts davon. Sternchen und Rauten erscheinen wörtlich.

Bindestriche werden nie markiert. read-only tier, two-day sprint und per-client limits sind korrekt und müssen bleiben. Nur U+2014 und U+2013 sind Fehler.

Das Bearbeiten von src/lint.ts ist der vorgesehene Weg, um dies zu deinem zu machen. Die Regeln kodieren die Schreibkonventionen einer Person, keinen universellen Standard.

Dinge, die dich überraschen werden

  • Die Posts-API scraped keine URLs. Ein Link in deinem Text bleibt ein nackter Link. Eine echte Vorschaukarte benötigt ein über die Images-API hochgeladenes Thumbnail plus einen content.article-Block. Hier noch nicht implementiert.

  • LinkedIn-Version ist Pflicht und Versionen werden eingestellt. 202508 wurde am 17. August 2026 abgeschaltet. Behandle den Wert in wrangler.jsonc als Wartungspunkt.

  • /v2/ugcPosts ist veraltet. Dies verwendet /rest/posts, das es ersetzt hat.

  • Das Ändern der angeforderten Scopes invalidiert jedes bestehende Token. Du musst dich erneut autorisieren.

  • 150 Anfragen pro Mitglied pro Tag. Pro Mitglied, nicht pro App.

Aufbau

Datei

Enthält

src/index.ts

Routen, OAuth-Ablauf, Cron-Erinnerung

src/linkedin.ts

OAuth- und Posts-API-Aufrufe, alle Endpunkte an einem Ort

src/mcp.ts

MCP-Server, handgeschriebenes JSON-RPC, zustandslos

src/lint.ts

Der Sprach-Linter

src/tokens.ts

KV-Token-Datensatz, Ablauf-Mathematik, timing-sicherer Geheimnisvergleich

Lokale Entwicklung

cp .dev.vars.example .dev.vars   # fill in, never commit
npm run types                    # regenerate Env after editing wrangler.jsonc
npm run typecheck
npm run dev

wrangler dev --local gibt dir ein lokales KV, sodass der gesamte Ablauf außer den echten LinkedIn-Aufrufen ohne Anmeldedaten getestet werden kann.

Lizenz

MIT. Die Regeln in src/lint.ts sind meine; den Mechanismus kannst du übernehmen.

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stepanic/linkedin-poster'

If you have feedback or need assistance with the MCP directory API, please join our Discord server