Upload-Post

Publica, programa y analiza publicaciones en TikTok, Instagram, YouTube, LinkedIn, Facebook, X, Threads, Pinterest, Reddit, Bluesky, Google Business, Discord y Telegram desde una sola clave de API (servidor OAuth remoto + paquete npm).

Documentación

@upload-post/mcp

Servidor oficial del Protocolo de Contexto de Modelo (MCP) para Upload-Post.

smithery badge Glama npm

Permite que cualquier agente de IA compatible con MCP (ChatGPT, Claude Desktop, Claude Code, Cursor, …) publique, programe, analice y gestione redes sociales en TikTok, Instagram, YouTube, LinkedIn, Facebook, Pinterest, Threads, Reddit, Bluesky, X, Google Business, Discord, Telegram y más con una sola clave de API.

Construido sobre el upload-post oficial y la API REST pública de Upload-Post.


Úsalo en ChatGPT (sin configuración)

Upload-Post es una aplicación revisada en el directorio de aplicaciones de ChatGPT. Añade Upload-Post en ChatGPT — o busca Upload-Post en Apps — haz clic en Conectar e inicia sesión con OAuth. Sin modo Desarrollador, sin URL de MCP que pegar, y obtienes el widget de Upload Studio para publicar archivos de video directamente desde tu computadora.

¿Prefieres configurarlo manualmente? Activa el modo Desarrollador en Configuración → Apps → Configuración avanzada, haz clic en Crear aplicación, apunta a https://mcp.upload-post.com/mcp y establece la autenticación en OAuth.


Dos formas de ejecutarlo tú mismo

A) stdio local (usuario único) — la más sencilla

El servidor se ejecuta en tu máquina, iniciado por el cliente MCP. Añádelo a ~/.claude/mcp.json (o a la configuración de Cursor, etc.):

{
  "mcpServers": {
    "upload-post": {
      "command": "npx",
      "args": ["-y", "@upload-post/mcp"],
      "env": { "UPLOAD_POST_API_KEY": "YOUR_API_KEY" }
    }
  }
}

Obtén tu clave de API en https://app.upload-post.com → API Keys. Reinicia el cliente — deberías ver 58 herramientas de upload-post.

B) HTTP alojado (multiinquilino) — comparte un servidor con muchos usuarios

Ejecuta el servidor en cualquier host compatible con Docker (Fly, Railway, Cloud Run, tu propio servidor…) y deja que cada usuario se conecte con su propia clave de API de Upload-Post. El servidor no almacena nada por usuario.

{
  "mcpServers": {
    "upload-post": {
      "url": "https://mcp.your-domain.com/mcp",
      "headers": {
        "Authorization": "ApiKey YOUR_OWN_UPLOAD_POST_API_KEY"
      }
    }
  }
}

Authorization: Bearer <key> también se acepta, para clientes que solo permiten Bearer.


¿Qué puede hacer el agente?

El servidor expone las herramientas de la API de Upload-Post más un lanzador de interfaz de aplicación de ChatGPT.

GrupoHerramientas
Subidaupload_video, upload_photos, upload_text, upload_document, open_upload_studio
Preparación de medioscreate_media_upload, complete_media_upload, get_media_upload, delete_media_upload
Estadoget_status, get_job_status, get_history, get_media
Programaciónlist_scheduled, cancel_scheduled, edit_scheduled
Analíticasget_analytics, get_total_impressions, get_post_analytics, get_cached_post_analytics, get_platform_metrics
Audienciaget_audience, get_suggestions
Usuariosget_account_info, list_users, get_connect_link, create_user, delete_user, generate_jwt, validate_jwt
Páginas/tablerosget_facebook_pages, get_linkedin_pages, get_pinterest_boards, get_google_business_locations, get_google_business_reviews, reply_to_google_business_review, get_reddit_detailed_posts
Publicacionesretry_post, unpublish_post
Comentariosget_post_comments, create_comment, delete_comment, comment_action, reply_to_comment, public_reply_to_comment
TikToktiktok_music_trending, tiktok_music_search, tiktok_location_search, tiktok_publishing_settings
Mensajes directossend_dm, list_dm_conversations, manage_autodms
FFmpegsubmit_ffmpeg_job, get_ffmpeg_job, download_ffmpeg_result, get_ffmpeg_consumption
Colaget_queue_settings, update_queue_settings, preview_queue

Las subidas asíncronas devuelven un request_id. El agente debe consultar get_status hasta que success: true.

Una herramienta por pregunta, no por red

La API de Upload-Post no tiene un endpoint por red social: tiene un endpoint por pregunta, y un parámetro platform que indica a quién se le pregunta. get_post_comments, get_post_analytics, get_audience, get_suggestions y comment_action funcionan así, de modo que un agente aprende una forma y la reutiliza para cada red. Solo las cuatro herramientas de tiktok_* son específicas de red, porque lo que devuelven (la Biblioteca de Música Comercial, los lugares de TikTok, la configuración de publicación por cuenta de TikTok) solo existe en TikTok.

  • get_audience — quién sigue el perfil, dónde están, cuándo están en línea, qué tocan. También benchmark_categories, y los promedios del nicho para comparar cuando benchmarkCategory está establecido. El servidor limita la ventana a un máximo de 60 días que terminan antes de hoy, por lo que un rango más amplio se recorta en lugar de rechazarse, y range en la respuesta indica qué ventana se usó.
  • get_suggestions — hashtags (con view_count) o búsquedas de palabras clave relacionadas, diferenciados por type, no por una herramienta distinta.
  • get_post_comments — comentarios de nivel superior en una publicación o, con commentId, las respuestas debajo de uno de ellos.
  • comment_action — moderar un comentario en TikTok (ocultar / dar me gusta / fijar), Facebook (ocultar / dar me gusta / editar), Instagram (ocultar, o habilitar / deshabilitar comentarios en una publicación), YouTube (ocultar / retener) y Threads (ocultar / aprobar / ignorar). Cada valor lleva su propio inverso, por lo que nada es permanente.
  • get_post_analytics — métricas por publicación. post_metrics es lo que la plataforma informa, por lo que su forma varía: en TikTok añade retention, impression_sources, audience_types, new_followers, reach y los tiempos de visualización (average_time_watched, total_time_watched, full_video_watched_rate).

Los errores también se comparten: platform_not_supported (400, con la lista de las redes que pueden responder), invalid_parameter (400), tiktok_reconnect_required (400), reauth_required (409) y 502 cuando la red upstream falla.

Capacidades de TikTok

get_post_comments, create_comment, delete_comment y comment_action aceptan platform: "tiktok", y firstComment funciona en TikTok como en cualquier otra red.

Lo que una cuenta de TikTok puede hacer depende de cómo esté conectada. list_users devuelve un array de capabilities en cada cuenta de TikTok — music, location, cover_image, cover_timestamp, draft, video_privacy, photo_privacy, profile_analytics, comments, trend_search — y la descripción de cada herramienta nombra la que necesita. Se otorgan cuando el usuario conecta TikTok, por lo que una cuenta conectada antes de que existiera una capacidad debe reconectarse antes de que las herramientas correspondientes respondan; eso es lo que significa un error de tiktok_reconnect_required.

get_media y get_cached_post_analytics están paginados por cursor: devuelve el next_cursor de la respuesta como cursor hasta que has_more sea falso. LinkedIn, Discord y Telegram no admiten cursores de medios y aceptan solo limit. Prefiere get_cached_post_analytics sobre get_post_analytics al escanear muchas publicaciones — reproduce resultados obtenidos previamente y así evita el límite de velocidad de analíticas en vivo de 100 solicitudes / 5 minutos. Solo contiene publicaciones obtenidas previamente a través de un endpoint en vivo por publicación; no hay actualización en segundo plano, por lo que captured_at es la última vez que esa publicación se leyó en vivo.

Los trabajos de FFmpeg aceptan una URL pública a través de input_url o varias URLs a través de files. Consulta get_ffmpeg_job hasta que se complete, luego llama a download_ffmpeg_result; devuelve la URL del resultado sin transmitir el binario procesado a través de MCP.

Interfaz de subida de video de ChatGPT

open_upload_studio renderiza un componente de ChatGPT Apps para la publicación de video basada en archivos. El widget crea una subida de preparación de Upload-Post/R2 de corta duración, hace PUT del video local directamente a R2, completa la subida y luego llama a upload_video con la URL de medios temporal devuelta.

El widget habla el puente del SDK de ChatGPT Apps, por lo que solo se anuncia a ChatGPT (detectado desde clientInfo en initialize; anula la coincidencia con UPLOAD_POST_STUDIO_CLIENTS=<regex>). Cualquier otro host (claude.ai, Claude Desktop, Claude Code, Cursor, …) no ve la herramienta ni su recurso ui://; en su lugar, create_media_upload / complete_media_upload se exponen al modelo con guía paso a paso, y upload_video le dice al asistente que pida una URL pública o envíe al usuario al panel cuando el cliente no pueda hacer PUT del archivo por sí mismo.

El objeto de preparación se elimina después de 24 horas, se use o no. Las publicaciones programadas/en cola permanecen seguras porque upload_video copia la URL temporal en el almacenamiento de programación duradero existente antes de la ejecución.

Claude y otros clientes MCP pueden usar el mismo flujo sin la interfaz de ChatGPT: llama a create_media_upload, haz PUT del archivo a upload_url, llama a complete_media_upload, luego pasa media_url a upload_video.

Establece UPLOAD_POST_R2_CONNECT_DOMAINS en el host MCP a los orígenes separados por comas utilizados por las URLs firmadas de R2 del backend cuando difieren de los valores predeterminados (por ejemplo, https://<account>.r2.cloudflarestorage.com,https://<bucket>.<account>.r2.cloudflarestorage.com) para que el componente CSP de ChatGPT permita el PUT del navegador.

La política CORS del bucket R2 debe permitir subidas desde el navegador. Una política restrictiva puede incluir el origen real de tu widget; para la validación más rápida, usa:

[
  {
    "AllowedOrigins": ["*"],
    "AllowedMethods": ["PUT", "GET", "HEAD"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3600
  }
]

Local / desarrollo

git clone https://github.com/Upload-Post/upload-post-mcp.git
cd upload-post-mcp
npm install
npm run build

# stdio (default — used by Claude Desktop, Cursor)
UPLOAD_POST_API_KEY=... node dist/index.js

# HTTP streamable (for hosted deployments)
UPLOAD_POST_API_KEY=... node dist/index.js --http --port 8080

Inspecciona la superficie de herramientas en vivo con el inspector oficial:

npx @modelcontextprotocol/inspector node dist/index.js

Configuración

Variable de entornoModoValor predeterminadoDescripción
UPLOAD_POST_API_KEYstdio— (obligatorio)Clave de API de Upload-Post del usuario único. Se ignora en modo --http — las claves llegan por solicitud.
UPLOAD_POST_BASE_URLamboshttps://api.upload-post.com/apiAnulación para autoalojado / staging.
UPLOAD_POST_MCP_PORThttp8080Puerto para el modo --http.
OPENAI_APPS_CHALLENGE_TOKENhttpToken de desafío actual de Upload-PostAnulación opcional para la verificación de dominio de ChatGPT Apps en /.well-known/openai-apps-challenge.

Banderas de CLI:

  • --http — inicia el transporte HTTP de flujo continuo en lugar de stdio
  • --port <n> — puerto para el modo HTTP

Endpoints HTTP:

  • POST /mcp — JSON-RPC sobre HTTP de flujo continuo de MCP. Requiere Authorization: ApiKey <key> (o Bearer <key>) en cada solicitud. La clave es la clave de API de Upload-Post del propio usuario; el servidor la usa solo para esa sesión y no almacena nada.
  • GET /healthz — sonda de actividad, siempre abierta. Devuelve {"ok":true}.

El modelo de autenticación en modo --http es el mismo patrón que Resend, Tavily, Brave Search y otros servicios nativos de clave de API usan para sus MCP alojados: la clave upstream es la autenticación.


Despliega con Docker

El repositorio incluye un Dockerfile de múltiples etapas y un .dockerignore. En cualquier PaaS compatible con Docker (Fly.io, Railway, Render, Cloud Run, máquinas fly, tu propio servidor…):

  1. Apunta el PaaS a este repositorio y selecciona Dockerfile como paquete de compilación.
  2. Puerto: 8080 (coincide con EXPOSE 8080).
  3. Variables de entorno: no se requiere ninguna. Opcionalmente, establece UPLOAD_POST_BASE_URL si apuntas a staging.
  4. Ruta de verificación de salud: /healthz (HTTP, puerto 8080).
  5. Dominio: adjunta un dominio, p. ej., mcp.your-domain.com, y aprovisiona TLS (la mayoría de los PaaS lo hacen automáticamente mediante Let's Encrypt).

Despliega. El servidor ya está listo para cualquier número de usuarios. Cada usuario añade el endpoint a su configuración de cliente MCP con su propia clave de API de Upload-Post:

{
  "mcpServers": {
    "upload-post": {
      "url": "https://mcp.your-domain.com/mcp",
      "headers": {
        "Authorization": "ApiKey USER_OWN_UPLOAD_POST_API_KEY"
      }
    }
  }
}

Sin un encabezado Authorization, el servidor devuelve 401. El encabezado es la única credencial — las claves de Upload-Post inválidas aparecerán como errores upstream en la primera llamada a una herramienta.

Prueba local de la imagen de producción:

docker build -t upload-post-mcp .
docker run --rm -p 8080:8080 upload-post-mcp
curl http://localhost:8080/healthz   # → {"ok":true}
curl -i -X POST http://localhost:8080/mcp \
  -H "content-type: application/json" \
  -d '{}'                               # → 401 (no Authorization)

Consejos para dar instrucciones al agente

  • Prefiere URLs públicas sobre rutas locales al subir archivos: las rutas locales solo funcionan si el servidor MCP se ejecuta en la máquina del usuario.
  • En las aplicaciones de ChatGPT, prefiere open_upload_studio para archivos de video seleccionados por el usuario. Esto evita problemas de transferencia de rutas locales al subir a un almacenamiento temporal de Upload-Post/R2 y luego pasar una URL de medios temporal a upload_video.
  • En cualquier otro cliente con un archivo local: si el cliente puede ejecutar solicitudes HTTP (Claude Code, Cursor, un script), súbelo con create_media_upload → envía los bytes a upload_url → complete_media_upload, y luego pasa el media_url devuelto a upload_video. Los chats alojados sin esa capacidad (claude.ai) necesitan una URL HTTPS pública o el panel en https://app.upload-post.com..
  • Para enviar bytes de video directamente (un cliente que tiene el archivo en lugar de una URL), pasa videoBase64 a upload_video en lugar de videoPathOrUrl. El servidor lo escribe en un archivo temporal, lo sube y luego lo elimina. Los bytes en línea están limitados a UPLOAD_POST_MAX_INLINE_MB (100 MB por defecto); para videos más grandes, usa una URL pública.
  • Siempre crea el perfil primero (create_user) y conecta las redes sociales en el panel de Upload-Post antes de publicar.
  • Para publicaciones programadas, pasa fechas ISO 8601 con zona horaria, por ejemplo, "2026-12-25T10:00:00Z" + "timezone": "Europe/Madrid".

Privacidad y manejo de datos

Este servidor es un proxy sin estado hacia la API de Upload-Post. Por solicitud, los únicos datos que procesa son la clave API del usuario (o el token de acceso OAuth resuelto a uno) y los argumentos de la llamada a la herramienta que se está ejecutando. El contenedor MCP no persiste ningún dato del usuario.

  • Lo que recibimos por solicitud: el encabezado Authorization, el nombre de la herramienta MCP + argumentos, y cualquier URL/ruta de medios que el agente pase.
  • Lo que reenviamos: los argumentos de la herramienta a la API de Upload-Post en nombre del usuario autenticado.
  • Lo que almacenamos: nada por usuario. Los tokens OAuth se almacenan en el backend de Upload-Post, con hash (SHA-256), por lo que una violación del almacenamiento de tokens no puede suplantar a los usuarios.
  • Lo que registramos: método HTTP, ruta, código de estado y un ID de solicitud opaco. Sin argumentos de herramientas, sin claves API, sin tokens.

Política de privacidad completa de Upload-Post (recopilación de datos, retención, intercambio con terceros, contacto, GDPR/CCPA): https://upload-post.com/privacy

Para revocar el acceso de un conector en cualquier momento, abre Aplicaciones conectadas en app.upload-post.com.


Seguridad

  • Todo el tráfico termina en TLS en el borde (solo HTTPS).
  • /mcp requiere un encabezado Authorization válido en cada solicitud; los tokens de acceso OAuth son de corta duración (1 h de acceso + 90 d de actualización con rotación según RFC 6749 §10.4).
  • El servidor valida el encabezado Origin contra una lista de permitidos (claude.ai, claude.com, chatgpt.com, chat.openai.com, app.upload-post.com, localhost) para mitigar ataques de rebote DNS desde clientes basados en navegador. Extiende con OAUTH_EXTRA_ALLOWED_ORIGINS (separado por comas) al autoalojar detrás de un panel personalizado.
  • Si ChatGPT muestra redirect_uri not on allow-list durante OAuth, agrega el redirect_uri exacto de la solicitud de autorización fallida a la lista de permitidos de redirección OAuth del backend de Upload-Post. Para clientes de ChatGPT, esto suele estar en https://chatgpt.com/.../oauth/callback o https://chat.openai.com/.../oauth/callback.
  • Las devoluciones de llamada de redirección OAuth están preautorizadas para: Claude (claude.ai/claude.com), ChatGPT, Cursor, VS Code (estable + Insiders), Smithery, Glama, Toolhouse, Perplexity (estándar + Enterprise), depurador de Mistral Studio y Postman, además de cualquier redirección http://localhost/loopback (RFC 8252), que cubre Claude Code, Windsurf, Cline, Continue, Goose, Gemini CLI y otros clientes de estilo mcp-remote. Las plataformas sin una devolución de llamada fija documentada (por ejemplo, Grok, Le Chat en producción) se agregan a solicitud.
  • Todas las herramientas declaran anotaciones MCP readOnlyHint/destructiveHint para que los clientes puedan mostrar avisos de confirmación para operaciones destructivas.

Reporta un problema de seguridad: info@upload-post.com (PGP cifrado disponible a solicitud).


Licencia

MIT © Upload-Post