linkedin-poster
linkedin-poster
Publica en tu propio feed de LinkedIn desde Claude Code, una shell o un cron job. Un Cloudflare Worker, sin dependencias, tres superficies: un servidor MCP para que un agente publique directamente, una API HTTP para scripts y un linter de voz que se niega a publicar texto que delate prosa generada por máquina.
Creado porque una buena publicación merece automatización y una mala raya em no merece publicarse. Este README tampoco tiene rayas em, que es el punto.
Claude Code ──MCP──┐
├──> Worker ──> LinkedIn Posts API ──> your feed
curl / CI ──HTTP───┘ │
└──> KV (one 60-day token) + daily cron reminderLo que no es
Esto publica como un miembro: tú. No es un SaaS de programación, no es una herramienta multiinquilino y no toca la cuenta de nadie más. Todo lo que necesita es autogestionado; no implica ningún programa de socios de LinkedIn.
La restricción que lo condiciona todo
Los tokens de acceso de LinkedIn duran 60 días y los tokens de actualización programáticos están limitados a socios aprobados del Marketing Developer Platform. Una aplicación autogestionada nunca obtiene uno. No hay forma de evitarlo, y cualquier guía que prometa automatización de LinkedIn de configurar y olvidar está equivocada.
Lo que sí hay: mientras tu token actual siga siendo válido y tengas la sesión iniciada en LinkedIn, volver a acceder al endpoint de autorización omite la pantalla de consentimiento y simplemente redirige. Así que la renovación es un clic cada siete semanas, siempre que lo hagas antes de que el token expire. Si pierdes la ventana, vuelves a ver la pantalla de consentimiento, que son dos clics en lugar de uno.
Por eso este servicio incluye un disparador cron. Cuenta los días hacia atrás y te avisa a 14, 7, 3 y 1 día, mientras la renovación silenciosa sigue funcionando.
Configuración
1. Lado de LinkedIn (manual, unos diez minutos)
Necesitas una Página de LinkedIn. El portal para desarrolladores te obliga a asociar la aplicación a una y a que un administrador de la página la verifique.
Crea la aplicación en linkedin.com/developers. Anota el Client ID y el Client Secret.
Pestaña Products, solicita ambos (son Open Permissions y se aprueban al instante):
Sign In with LinkedIn using OpenID Connect →
openid,profileShare on LinkedIn →
w_member_social
Pestaña Auth → añade la URL de redirección. Debe ser HTTPS, absoluta y coincidir con
REDIRECT_URIcarácter por carácter:https://your-worker.example.com/auth/callback
2. Lado del Worker
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 deploy3. Conecta tu cuenta
Abre https://your-worker.example.com/auth/start?key=<SETUP_KEY> en un navegador,
aprueba una vez, listo. La página te indica la fecha de caducidad.
SETUP_KEY no es decoración. Sin él, cualquiera que encontrara la URL podría vincular
su cuenta de LinkedIn a tu Worker y sobrescribir tu token almacenado.
Usarlo desde Claude Code
claude mcp add --transport http linkedin https://your-worker.example.com/mcp \
--header "Authorization: Bearer $API_TOKEN"Tres herramientas:
Herramienta | Qué hace |
| Aplica el linter y luego publica. Se niega si hay errores salvo que |
| Aplica el linter sin publicar. Úsalo mientras redactas. |
| En nombre de quién publica y cuántos días le quedan al token. |
Luego, en una sesión: "revisa este borrador con el linter y luego publícalo."
Usarlo desde una 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 devuelve 201 con el URN de la publicación y su URL pública, 422 cuando el linter
lo bloquea, 503 cuando el token falta o está caducado.
El linter
Los errores bloquean la publicación; las advertencias no.
Regla | Severidad | Por qué |
| error | La señal más clara de prosa generada. Una coma o un punto siempre funcionan. |
| error | LinkedIn rechaza comentarios de más de 3000 caracteres. |
| error | Obvio, pero fácil de alcanzar al canalizar desde un archivo. |
| warning | LinkedIn no renderiza nada de eso. Los asteriscos y las almohadillas aparecen literalmente. |
Los guiones nunca se marcan. read-only tier, two-day sprint y
per-client limits son correctos y deben permanecer. Solo U+2014 y U+2013 son errores.
Editar src/lint.ts es la forma prevista de hacer esto tuyo. Las reglas codifican
las convenciones de escritura de una persona, no un estándar universal.
Cosas que te sorprenderán
La API de Posts no extrae URLs. Un enlace en tu texto permanece como enlace simple. Una tarjeta de vista previa real necesita una miniatura subida mediante la API de Imágenes más un bloque
content.article. Aún no implementado aquí.LinkedIn-Versiones obligatorio y las versiones se retiran.202508dejó de estar disponible el 17 de agosto de 2026. Trata el valor enwrangler.jsonccomo un elemento de mantenimiento./v2/ugcPostsestá obsoleto. Esto usa/rest/posts, que lo reemplazó.Cambiar los ámbitos solicitados invalida todos los tokens existentes. Tendrás que volver a autorizar.
150 solicitudes por miembro al día. Por miembro, no por aplicación.
Estructura
Archivo | Contenido |
| Rutas, flujo OAuth, recordatorio cron |
| Llamadas a la API de OAuth y Posts, todos los endpoints en un solo lugar |
| Servidor MCP, JSON-RPC hecho a mano, sin estado |
| El linter de voz |
| Registro de token en KV, cálculos de caducidad, comparación de secretos a prueba de tiempos |
Desarrollo local
cp .dev.vars.example .dev.vars # fill in, never commit
npm run types # regenerate Env after editing wrangler.jsonc
npm run typecheck
npm run devwrangler dev --local te da un KV local, así que todo el flujo salvo las llamadas reales
a LinkedIn se puede probar sin credenciales.
Licencia
MIT. Las reglas en src/lint.ts son mías; el mecanismo es tuyo para llevarlo.
This server cannot be installed
Maintenance
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
Give AI agents the LinkedIn tools to find, qualify, engage, and follow up with prospects.
Live LinkedIn data for AI agents: profiles, companies, jobs, posts, email finding. No account risk.
Managed LinkedIn MCP server for AI agents: search, connect, message and enrich on accounts you own.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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