Substack MCP (unofficial)
Servidor MCP y CLI no oficial para creadores de Substack: borradores enriquecidos en Markdown, etiquetas de borradores, Notas, analíticas de publicaciones y posts, búsqueda en archivo, lectura de perfiles públicos y Notas, y segmentación de suscriptores. Los posts de formato largo permanecen como borradores; las Notas se publican inmediatamente. No afiliado a Substack.
Documentación
substack-mcp
Crea y gestiona tu boletín de Substack desde tu asistente de IA o terminal. Prepara borradores enriquecidos, busca en tu archivo, publica Notas, inspecciona análisis y gestiona suscriptores gratuitos con consentimiento explícito en todas las publicaciones. Revisa y publica artículos de formato largo en Substack.

La demo ejecuta manejadores MCP reales contra datos de muestra sin conexión. No se realizan llamadas API en vivo ni publicaciones. Sigue el flujo de trabajo de borradores para crear, encontrar, exportar y revisar una publicación.
Seguro por diseño, con una excepción bien visible: Este servidor no puede publicar ni eliminar artículos de formato largo. Las herramientas de publicación solo crean y editan borradores; tú revisas y publicas manualmente a través del editor de Substack. La excepción son las Notas de Substack: create_note y create_note_with_link publican Notas de formato corto inmediatamente, porque las Notas no tienen estado de borrador en Substack. Trata las herramientas de Notas como acciones de publicación pública: no hay paso de vista previa ni deshacer desde este servidor. La división es una revisión proporcional, la pieza de infraestructura de confianza para agentes que más le importa a este servidor: la superficie de alto riesgo tiene una puerta humana, y la excepción se declara en voz alta.
Este servidor no impone ninguna verificación de estado de Bestseller. Usa una cuenta autenticada con permiso para gestionar la publicación; las operaciones individuales dependen de tu acceso a Substack. Conéctate a través de stdio local o HTTP autoalojado.
Para la cobertura de configuración 1.0 y la elegibilidad de cuenta, consulta compatibilidad. Los mantenedores pueden usar la lista de verificación de lanzamiento y el inventario de distribución.
Contenido: Inicio rápido · Configuración · Herramientas · CLI de operador · Flujo de trabajo de borradores · De análisis a borrador · Exportación · Markdown · Múltiples publicaciones · Transportes · Compatibilidad
Inicio rápido
-
Instala e inicia sesión. El inicio de sesión por navegador necesita la dependencia opcional de Playwright:
npm install @conorbronsdon/substack-mcp playwright npx playwright install chromium npx substack-mcp login https://yourblog.substack.com --user-id 12345Usa el ID de usuario de tu propia cuenta. La sesión se guarda solo después de que una lectura autenticada acotada tenga éxito. Para pegar credenciales en su lugar, consulta Opción B.
-
Verifica una lectura.
npx substack-mcp doctor --json --check-authrealiza una lectura acotada por publicación. Confirma el acceso de lectura, no tu ID de usuario ni el permiso de escritura. -
Conecta tu cliente MCP. Añade el servidor a Claude Desktop o Claude Code, o usa el plugin de Codex. Las variables de entorno tienen prioridad; omítelas para usar la sesión de inicio de sesión por navegador guardada. Luego pregunta a tu asistente: "¿Cuántos suscriptores de Substack tengo?"
-
Prepara un borrador para revisión. Sigue el flujo de trabajo de borradores:
create_draft,search_posts,export_draft,preflight_draft, luegoplan_draft_updateyupdate_draft. Los artículos de formato largo permanecen como borradores sin publicar hasta que los publiques en el editor de Substack.create_noteycreate_note_with_linkpublican inmediatamente.
Recorrido de la comunidad
El artículo de Jonathan Price Usé Codex para conectar ChatGPT a Substack. Luego redactó esta publicación. recorre el uso de Codex para instalar el MCP localmente, conectar ChatGPT a través del Túnel MCP Seguro de OpenAI y crear un borrador privado para publicación manual. Usó la conexión para crear el borrador de la propia guía.
La guía documenta su configuración del 18 de septiembre de 2026 con la versión 1.2.0. Su get_post 404 reportado está corregido en 1.2.1. Las interfaces de cliente y los requisitos de acceso pueden cambiar; usa las instrucciones de configuración a continuación para la configuración actual de este paquete. Este es un recorrido de la comunidad, no un servicio alojado proporcionado por este proyecto.
Configuración
Requiere Node.js 22 o más reciente (CI cubre Node 22 y 24). El inicio de sesión por navegador requiere adicionalmente Playwright.
Puedes proporcionar credenciales de dos maneras: pegarlas como variables de entorno (abajo) o ejecutar el inicio de sesión por navegador opcional que las captura y almacena por ti.
Opción A — Inicio de sesión por navegador (opcional, sin copiar cookies manualmente)
Instala el servidor y la dependencia opcional de Playwright juntos en un directorio de herramientas local, luego inicia sesión:
npm install @conorbronsdon/substack-mcp playwright
npx playwright install chromium
npx substack-mcp login https://yourblog.substack.com --user-id 12345
substack-mcp-login sigue siendo un alias compatible. Se solicitan la URL de publicación y el ID de usuario faltantes. Proporciona el ID de usuario de tu propia cuenta; la firma de un autor de una publicación no verifica tu identidad. El navegador se abre para iniciar sesión, incluido cualquier CAPTCHA. Solo se captura una cookie aplicable a la API de publicación, y una lectura autenticada acotada debe tener éxito antes de guardar. Esto verifica el acceso de lectura, no el ID de usuario configurado ni el permiso de escritura.
Sin --profile, el inicio de sesión guarda ~/.substack-mcp/session.json (anulación de directorio: SUBSTACK_MCP_HOME). El servidor usa esta sesión heredada cuando las variables de entorno de credenciales de publicación y SUBSTACK_PROFILES no están configuradas.
Almacenamiento predeterminado (SUBSTACK_CREDENTIAL_STORE=file): las sesiones usan AES-256-GCM con una clave derivada de la cuenta del sistema operativo y la máquina. Los permisos de archivo solicitan 0600; el acceso en Windows también depende de las ACL del directorio. Este es un archivo vinculado a la máquina, no un llavero del sistema operativo ni una bóveda de secretos. El código que se ejecuta como tu usuario del sistema operativo puede derivar la clave. Usa credenciales de entorno si tu cliente MCP gestiona secretos por ti.
Llavero del sistema operativo opcional: configura SUBSTACK_CREDENTIAL_STORE=keychain tanto en el proceso de inicio de sesión como en el entorno del cliente MCP. macOS usa Keychain a través de /usr/bin/security; Linux necesita libsecret y secret-tool más un Secret Service desbloqueado; Windows usa Credential Manager a través de PasswordVault de PowerShell. Los tres se ejercitan con credenciales sintéticas por el flujo de trabajo CI de keychain en ejecutores alojados en GitHub (un llavero temporal de macOS desbloqueado y una sesión de gnome-keyring en Linux); las configuraciones de escritorio con llaveros bloqueados pueden seguir solicitando. El inicio de sesión escribe la cuenta seleccionada en el llavero, y el servidor la lee allí. La selección explícita de llavero nunca lee el archivo cifrado como respaldo. El llavero ayuda contra otros usuarios del sistema operativo, discos copiados y algunos malware limitados al acceso de archivos. El código que se ejecuta como tu usuario generalmente puede consultar el llavero. Mantén la cuenta del sistema operativo y el código en ejecución como confiables. En Linux, secret-tool lookup puede salir con 1 sin un mensaje de error tanto por una entrada ausente como por un llavero bloqueado. Las escrituras nombradas sin --force buscan y desbloquean primero, y rechazan sobrescrituras cuando se encuentra una entrada.
Perfiles nombrados y migración
npx substack-mcp login https://yourblog.substack.com --user-id 12345 --profile work
npx substack-mcp profiles list
# Copy an existing legacy session without changing its file:
npx substack-mcp profiles migrate --name personal
# Copy a file session or named file profile into the keychain; source remains:
npx substack-mcp profiles migrate --to keychain
npx substack-mcp profiles migrate --to keychain --name work
Las claves comienzan con una letra ASCII minúscula y contienen solo letras minúsculas, dígitos y guiones, hasta 64 caracteres. Los perfiles existentes requieren --force explícito para reemplazarse. La salida de la lista contiene claves, estado de legibilidad, orígenes de publicación y tiempos de guardado de archivos; excluye cookies e IDs de usuario. Los perfiles ilegibles permanecen visibles pero no se pueden seleccionar. El tiempo de guardado registra la persistencia local, incluida la migración; no es el tiempo de emisión o expiración del token. El listado está limitado a 32 perfiles.
El almacenamiento de perfiles requiere un sistema de archivos local que admita enlaces duros (como NTFS o un sistema de archivos Linux típico), por lo que la creación puede instalar un archivo cifrado completo sin sobrescribir un nombre existente. FAT/exFAT y algunos montajes de red no son compatibles: configura SUBSTACK_MCP_HOME en un directorio local adecuado. No uses --force para solucionar un sistema de archivos no compatible.
Configura SUBSTACK_PROFILES=work,personal en el entorno de tu cliente MCP para seleccionar hasta 32 perfiles distintos. Elimina primero todas las variables de credenciales de publicación: combinar la selección de perfiles con variables de credenciales heredadas o nombradas es un error, incluidas las variables vacías. Los perfiles seleccionados faltantes, corruptos o inválidos detienen el inicio; nunca recurren a otra cuenta. Los perfiles en disco nunca se activan por descubrimiento. Con múltiples perfiles, las herramientas requieren una clave de publicación explícita y las lecturas de CLI requieren --publication.
Para revertir, desconfigura SUBSTACK_PROFILES y restaura tu configuración de entorno anterior. La migración preserva la sesión heredada byte por byte. Estos archivos usan el formato de cifrado existente. profiles list lista los perfiles de archivo; selecciona perfiles de llavero explícitamente con SUBSTACK_PROFILES después de la migración o el inicio de sesión. Ejecuta substack-mcp status --json para diagnósticos de configuración sin conexión o substack-mcp doctor --check-auth --json para una lectura acotada por cuenta seleccionada.
Opción B — Obtén tus credenciales manualmente
Abre tu Substack en un navegador, luego:
- Token de sesión: Navega a tu publicación, abre DevTools → Application → Cookies → copia el valor de
connect.sid(cadena codificada en URL que comienza cons%3A) - ID de usuario: Usa el ID numérico de tu cuenta de Substack con sesión iniciada desde tus datos de cuenta autenticados. No uses el ID de firma de una publicación: las publicaciones pueden tener múltiples autores. Este servidor no verifica de forma independiente el ID proporcionado.
- URL de publicación: Tu URL de Substack, incluido el dominio personalizado si lo tienes (por ejemplo,
https://newsletter.yourdomain.comohttps://yourblog.substack.com)
2. Configura tu cliente MCP
Claude Desktop
Añade a tu claude_desktop_config.json:
{
"mcpServers": {
"substack": {
"command": "npx",
"args": ["-y", "@conorbronsdon/substack-mcp"],
"env": {
"SUBSTACK_PUBLICATION_URL": "https://yourblog.substack.com",
"SUBSTACK_SESSION_TOKEN": "your-session-token",
"SUBSTACK_USER_ID": "your-user-id"
}
}
}
}
La configuración del plugin de Claude Code y Codex está disponible junto con la configuración manual de MCP. El marketplace del repositorio y el plugin local son separados de la aceptación del directorio curado o el soporte alojado de ChatGPT.
Claude Code
Añade a tu .mcp.json:
{
"mcpServers": {
"substack": {
"command": "npx",
"args": ["-y", "@conorbronsdon/substack-mcp"],
"env": {
"SUBSTACK_PUBLICATION_URL": "https://yourblog.substack.com",
"SUBSTACK_SESSION_TOKEN": "your-session-token",
"SUBSTACK_USER_ID": "your-user-id"
}
}
}
}
3. Verifica
Pregunta a tu asistente de IA: "¿Cuántos suscriptores de Substack tengo?"
La compatibilidad de salida de herramientas, los límites de respuesta y el versionado están documentados en el contrato de herramientas.
Diagnósticos de operador
El CLI expone comandos de operador y verificaciones de configuración a través de los mismos manejadores MCP y la resolución de credenciales que el servidor. drafts create escribe un borrador privado; los otros comandos de operador leen:
substack-mcp status --json
substack-mcp doctor --json --check-auth
substack-mcp drafts list --limit 10
Los comandos, el sobre JSON, los códigos de salida, los plazos de solicitud y los límites de respuesta están documentados en CLI de operador y diagnósticos.
Herramientas
Cada herramienta declara anotaciones explícitas de efectos secundarios de MCP; consulta anotaciones de herramientas. Las descripciones de herramientas llevan la redacción autoritativa.
Lectura
| Herramienta | Descripción |
|---|---|
get_subscriber_count | Obtén el número actual de suscriptores de tu publicación |
list_subscribers | Lee una página limitada de registros privados de suscriptores |
search_subscribers | Filtra y pagina registros privados de suscriptores; campos opcionales de actividad, fecha, indicadores e ingresos |
get_subscriber | Busca una membresía por correo electrónico exacto; concilia adiciones pendientes |
list_published_posts | Lista publicaciones publicadas con paginación |
get_publication | Lee la identidad/configuración proyectada de la publicación, verifica el host configurado e informa campos faltantes; no verifica la identidad de la cuenta ni el rol |
list_publication_tags | Lee definiciones de etiquetas, incluidas las etiquetas ocultas por defecto, con paginación local limitada |
get_post_tags | Resuelve asociaciones de etiquetas de publicaciones; conserva IDs sin resolver e informa incertidumbre de identidad en resultados vacíos. La cobertura de borradores se verifica en vivo solo para respuestas vacías |
search_posts | Busca en un archivo de publicación por consulta y estado; páginas limitadas con metadatos de continuación |
plan_draft_update | Revisa cambios propuestos, preflight y un recibo para detección de desactualización de mejor esfuerzo; sin escrituras |
export_draft | Markdown editable, cuerpo original exacto, diagnósticos de conversión, preflight y enlace al editor |
preflight_draft | Comprobaciones de solo lectura para título, audiencia, estructura del cuerpo, imágenes y muros de pago, con enlace al editor |
list_drafts | Lista publicaciones en borrador |
get_post | Obtén el contenido completo de una publicación publicada por ID |
get_draft | Obtén el contenido completo de un borrador por ID |
get_post_comments | Obtén comentarios de una publicación publicada |
get_sections | Lista las secciones (categorías) de tu publicación con sus IDs |
get_post_analytics | Obtén las estadísticas de una publicación publicada (vistas, aperturas, registros, suscripciones, reacciones) por ID |
rank_posts | Clasifica publicaciones por vistas, aperturas, envíos, tasas, registros, suscripciones, valor estimado o fecha, manteniendo valores nulos y faltantes distintos |
get_publication_stats | Lee el resumen del panel y métricas de publicación por rango, con estados faltantes y no disponibles |
get_growth_sources | Lee atribución de crecimiento por fuente limitada y eventos opcionales |
list_scheduled_posts | Lista publicaciones programadas para publicación futura (solo lectura; la programación permanece en el editor de Substack) |
get_user_profile | Lee un perfil público mínimo de usuario por handle, de forma anónima |
get_profile_feed | Lee una página de feed de perfil público con continuación por cursor, de forma anónima |
get_note_thread | Lee una Nota pública, ancestros y una página de respuestas, de forma anónima |
list_public_posts | Lee una página de archivo público limitada, de forma anónima |
get_public_post | Lee una publicación pública anónima por URL con estado del cuerpo e indicadores de truncamiento |
Lectura pública
Estas cinco herramientas usan un lector anónimo separado. Envía solo User-Agent y
Accept, nunca la cookie de publicación configurada ni otras credenciales. La
publicación configurada selecciona el origen de archivo predeterminado; los llamadores pueden proporcionar un
origen de publicación HTTPS en la lista permitida. Los hosts permitidos son substack.com, de una etiqueta
*.substack.com, orígenes de publicación configurados y orígenes exactos en
SUBSTACK_PUBLIC_READ_ORIGINS (orígenes HTTPS separados por comas sin puertos,
rutas ni userinfo). Las redirecciones se rechazan. Una publicación *.substack.com puede
redirigir a su dominio personalizado (por ejemplo, lenny.substack.com); las lecturas JSON no
siguen esa redirección. Agrega el origen HTTPS personalizado a
SUBSTACK_PUBLIC_READ_ORIGINS y lee a través de ese origen. Con múltiples
publicaciones, la clave publication sigue siendo obligatoria para cada herramienta.
Las páginas de feed de perfil tienen el tamaño del upstream; has_more: null significa que el upstream omitió
metadatos de continuación. Las páginas de hilos pueden omitir respuestas cuando more_branches o
next_cursor está presente; completeness: "unknown" significa que los metadatos de continuación
se omitieron.
Las páginas completas de archivo tienen has_more: null porque no se devuelve un total. El
body_status de publicación pública es una heurística basada en audiencia y presencia del cuerpo; no
establece acceso completo. El lector anónimo no usa derechos de suscripción.
Las suscripciones del lector y la bandeja de entrada no son compatibles: la
sesión de publicación configurada recibió 401 en las rutas de cuenta de lector substack.com,
que requieren una sesión de lector separada que este servidor no gestiona.
Búsqueda de archivo y revisión de borradores
search_posts acepta query (1–500 caracteres), status (published, drafts,
o scheduled, predeterminado published), offset (predeterminado 0) y limit (1–50,
predeterminado 25). Realiza una solicitud de archivo autenticada y devuelve
metadatos proyectados, returned, total, has_more y next_offset. Continúa con
next_offset y la misma consulta/estado. Cuando Substack omite el total y una
página está completa, has_more es nulo (desconocido); otra página puede estar vacía. Substack
controla la coincidencia y la indexación: esto no es un escaneo de texto completo garantizado. Usa
get_post o get_draft para recuperar el contenido completo. La paginación no es una instantánea;
las ediciones concurrentes pueden mover resultados entre páginas.
preflight_draft acepta draft_id, lo lee una vez y devuelve checks_passed,
hallazgos con severidad/código/mensaje, recuentos de contenido y un enlace al editor. Comprueba título,
audiencia, forma JSON/cuerpo, envoltorios de imágenes y fuentes HTTPS, y recuento de muros de pago
y colocación en los bordes. Los nodos desconocidos y las imágenes externas producen advertencias de revisión.
Los cuerpos de más de dos millones de caracteres, 10,000 nodos o profundidad 100 no se
comprueban por completo; counts.complete es falso y las comprobaciones agregadas se omiten después de un
límite de escaneo. Las advertencias de nodos desconocidos nombran hasta cinco tipos para revisión del editor.
Esta es una comprobación estática enfocada, no una validación completa de ProseMirror ni
aprobación de publicación. No obtiene enlaces/imágenes, verifica la configuración de acceso ni
prueba la representación final. Revisa el borrador en Substack; no se modifica ningún contenido.
Ambas herramientas requieren publication cuando se configuran múltiples publicaciones.
Escritura (borradores privados; la carga de imágenes devuelve una URL pública)
| Herramienta | Descripción |
|---|---|
create_draft | Crea un nuevo borrador desde markdown (privado) |
update_draft | Aplica un recibo de cambio revisado; vuelve a comprobar el estado no publicado e informa los resultados de lectura posterior |
update_draft_tags | Planifica o cambia etiquetas de borrador; simulación por defecto, solo borrador, con una lectura posterior después de las escrituras |
upload_image | Sube una imagen al CDN de Substack desde un archivo, URI de datos o URL HTTPS pública — devuelve una URL de acceso público (no listada) |
Revisión antes de cambiar un borrador
En 0.9, llama a plan_draft_update, revisa su salida y luego llama a update_draft con
los mismos campos y el recibo devuelto. Los borradores publicados o conocidos como desactualizados se
rechazan. La carrera de lectura/escritura permanece; comprueba los resultados de lectura posterior y revisa en
Substack. La CLI comparte este flujo a través de drafts plan y drafts apply.
Consulta cambios de borrador y migración para ejemplos y límites.
Publicar (Notas — públicas inmediatamente)
| Herramienta | Descripción |
|---|---|
create_note | Publica una Nota de Substack (formato corto, publica inmediatamente) |
create_note_with_link | Publica una Nota con un adjunto de tarjeta de enlace (publica inmediatamente) |
Las Notas no tienen estado de borrador en Substack, por lo que no hay opción de borrador primero para estas dos herramientas.
Gestión de suscriptores
add_free_subscriber agrega un lector que consiente al boletín gratuito. Es
un cambio de distribución: ese lector puede recibir futuros correos del boletín. Puede
solicitar un correo de bienvenida con send_welcome_email: true (desactivado por defecto).
Nunca otorga acceso de pago ni anula la supresión de Substack de
direcciones previamente dadas de baja. Sus anotaciones MCP lo identifican
como una escritura externa (readOnlyHint: false, openWorldHint: true).
{"email":"reader@example.org","consent_confirmed":true,"consent_evidence":{"source":"booking:message-id","recorded_at":"2026-09-01T00:00:00Z"},"dry_run":true}
La simulación es el valor predeterminado. Después de verificar el consentimiento real del boletín, establece
dry_run: false para ejecutar. Las adiciones en vivo requieren la referencia de origen y la marca de tiempo
en consent_evidence; esta atestación se repite con la clave de publicación para
auditoría y no reemplaza la verificación del registro de consentimiento subyacente.
Las configuraciones de múltiples publicaciones también requieren el
selector publication, igual que cualquier otra herramienta.
Los resultados distinguen existing, dry_run, verified, blocked y
unverified, busy y retryable. busy no realiza ninguna escritura; espera la
otra operación. retryable significa que la autenticación o la limitación de velocidad rechazaron la
solicitud; resuelve esa condición antes de reintentar explícitamente. Un acuse de recibo de API vacío no es prueba de adición.
verified significa que una búsqueda de membresía exacta tuvo éxito después de la solicitud; no
prueba que esta solicitud creó originalmente la membresía. Los datos del panel
pueden retrasarse. Un lector faltante también puede haberse dado de baja previamente.
Para unverified, vuelve a comprobar con get_subscriber; nunca repitas automáticamente la
adición. Para blocked, revisa en Substack sin omitir la supresión. Los llamadores
automatizados deben persistir un registro de intentos antes de enviar cada solicitud en vivo.
La protección de duplicados en memoria del cliente no sobrevive reinicios ni sesiones HTTP
separadas. Mantén las identidades de suscriptores y la evidencia de consentimiento fuera de repositorios
compartidos, indicaciones a servicios públicos no aprobados y registros rutinarios.
Notas de implementación y verificación en vivo: API de suscriptores.
Para las opciones de reserva de Google Calendar, el asistente de sincronización de calendario proporciona un escaneo limitado de Gmail, selección de la última respuesta, un registro de intentos durable privado y reconciliación de solo lectura después de escrituras inciertas. La programación es un paso de configuración local explícito; instalar el MCP no inicia un trabajo en segundo plano.
Excluido intencionalmente
- Publicar publicaciones — Publicar publicaciones de formato largo debe ser una acción humana deliberada (las Notas son la excepción documentada anteriormente)
- Eliminar — Demasiado destructivo para una herramienta de IA
- Programar — Usa el editor de Substack para programar. (
list_scheduled_postslee lo que has puesto en cola allí, pero este servidor nunca crea, edita ni cancela una programación).
Para un programador siempre activo con estado de nube durable e informes semanales por correo, consulta Sincronización de Cloud Calendar.
Múltiples publicaciones
¿Ejecutas más de una publicación detrás de un solo servidor? Establece un triplete SUBSTACK_PUB_<KEY>_* por publicación en lugar de las variables SUBSTACK_* simples. <KEY> es cualquier nombre que elijas (letras, dígitos, guiones bajos) — se convierte en la clave en minúsculas y con guiones de la publicación, p. ej. KEVIN_MULDOON → kevin-muldoon.
"env": {
"SUBSTACK_PUB_KEVIN_MULDOON_PUBLICATION_URL": "https://kevinmuldoon.substack.com",
"SUBSTACK_PUB_KEVIN_MULDOON_SESSION_TOKEN": "token-1",
"SUBSTACK_PUB_KEVIN_MULDOON_USER_ID": "111",
"SUBSTACK_PUB_SAPERE_PUBLICATION_URL": "https://sapere.substack.com",
"SUBSTACK_PUB_SAPERE_SESSION_TOKEN": "token-2",
"SUBSTACK_PUB_SAPERE_USER_ID": "222"
}
Cada triplete es independiente, y establecer cualquier variable SUBSTACK_PUB_<KEY>_* declara esa publicación. Un triplete incompleto — una variable faltante, un valor vacío o un valor de solo espacios en blanco — falla al inicio con un error que nombra la clave, en lugar de eliminar silenciosamente esa publicación. Eso importa porque una publicación eliminada no es "una publicación menos": elimina la única y el servidor vuelve a tu sesión de inicio de sesión de navegador almacenada; elimina una de dos y cada herramienta pierde su parámetro publication, por lo que una llamada destinada a la publicación eliminada se enruta silenciosamente a la superviviente.
Las claves se comparan sin distinguir mayúsculas y minúsculas, con _ plegado a -. Dos nombres que se resuelven a la misma clave (SUBSTACK_PUB_ALPHA_* y SUBSTACK_PUB_Alpha_*) también son un error de inicio — fusionarlos silenciosamente permitiría que la URL de una publicación se emparejara con el token de sesión de otra.
<KEY> acepta letras ASCII, dígitos y guiones bajos; los tres sufijos deben estar en mayúsculas y el nombre completo no debe tener espacios en blanco sueltos. Cualquier cosa que comience con SUBSTACK_PUB_ pero no se ajuste a esa forma — un guion en la clave, un sufijo en minúsculas, un carácter acentuado, un espacio final — es un error de inicio que nombra la variable, no una variable que se ignora silenciosamente. Por la misma razón que antes: una publicación ignorada no es una publicación menos, es un redireccionamiento silencioso a otra diferente.
Con dos o más publicaciones configuradas, cada herramienta gana un parámetro publication obligatorio — una de tus claves configuradas (p. ej. kevin-muldoon, sapere arriba). El modelo que llama debe especificar uno en cada llamada; un valor no reconocido se rechaza antes de que se realice cualquier llamada a la API de Substack, por lo que una escritura errónea no puede aterrizar en la publicación equivocada. Con exactamente una publicación configurada — el caso común, ya sea mediante variables SUBSTACK_* simples o un trío SUBSTACK_PUB_<KEY>_* único — no se añade ningún parámetro publication en absoluto; el esquema de cada herramienta no cambia respecto al modo de publicación única.
No mezcles los dos estilos: si se establece alguna variable SUBSTACK_PUB_<KEY>_*, las variables SUBSTACK_* simples se ignoran (con una advertencia de inicio) en lugar de tratarse como una publicación adicional sin nombre.
SUBSTACK_USER_AGENT y SUBSTACK_REQUEST_TIMEOUT_MS se aplican a cada publicación configurada — no son por publicación. El inicio de sesión del navegador también admite perfiles nombrados explícitos; consulta Perfiles nombrados y migración.
Expiración del token
Los tokens de sesión de Substack expiran periódicamente (normalmente ~90 días). Si recibes errores de autenticación, obtén una cookie connect.sid fresca de tu navegador y actualiza la variable de entorno (asegúrate de que los bloqueadores de anuncios estén desactivados al copiar la cookie) — o, si usaste el inicio de sesión del navegador, simplemente vuelve a ejecutar substack-mcp-login para actualizar la sesión almacenada.
Dominios personalizados y Cloudflare
Esta sección cubre llamadas autenticadas a la API de creadores. La lectura pública anónima utiliza las reglas de origen de lectura pública anteriores.
Las publicaciones de Substack servidas en un dominio personalizado (p. ej. blog.example.com) están detrás de Cloudflare, que puede rechazar solicitudes que no sean de navegador con 403 error code: 1010. Para evitar esto, el servidor envía un User-Agent de navegador y un Referer por defecto, y se dirige a la publicación por su host canónico *.substack.com.
- Usa el host canónico. Establece
SUBSTACK_PUBLICATION_URLa la dirección*.substack.comde la publicación en lugar del dominio personalizado. Las llamadas al host canónico se sirven directamente; las llamadas al dominio personalizado pueden redirigir con 301 y luego dar 401. - Anula el User-Agent (opcional) mediante
SUBSTACK_USER_AGENTsi necesitas una firma de navegador diferente:
"env": {
"SUBSTACK_PUBLICATION_URL": "https://yourblog.substack.com",
"SUBSTACK_SESSION_TOKEN": "your-session-token",
"SUBSTACK_USER_ID": "your-user-id",
"SUBSTACK_USER_AGENT": "Mozilla/5.0 ..."
}
Tiempo de espera de solicitud
Cada solicitud a Substack está limitada por un plazo de 30 segundos. Node no aplica ningún tiempo de espera de solicitud propio — solo un tiempo de espera de conexión de 10 segundos — por lo que un host que acepta la conexión y luego se queda en silencio (un proxy que descarta paquetes en lugar de rechazarlos) colgaría una llamada de herramienta indefinidamente. Una solicitud que alcanza el plazo falla con un TimeoutError que nombra el endpoint y el límite.
Súbelo o bájalo con SUBSTACK_REQUEST_TIMEOUT_MS (milisegundos; un valor no numérico o no positivo se ignora con una advertencia y se usa el predeterminado):
"env": {
"SUBSTACK_REQUEST_TIMEOUT_MS": "60000"
}
Transportes
Por defecto, el servidor habla MCP sobre stdio, que es lo que asumen las configuraciones de cliente anteriores. Establece MCP_TRANSPORT=http para un servidor HTTP Streamable sin estado (POST /mcp, GET /health) en un despliegue persistente autoalojado. La configuración, las variables del listener y el modelo de seguridad están en Transporte HTTP.
Qué aceptará este listener
El listener HTTP comienza cerrado: listas de permitidos de loopback Host y Origin por defecto, un token bearer opcional (MCP_HTTP_TOKEN) y un límite de cuerpo de 10 MiB. Las comprobaciones de Host y Origin no son autenticación; establece un token dondequiera que otros procesos puedan alcanzar el puerto. Consulta la política del listener.
Imágenes GHCR versionadas y verificación de transporte: distribución de contenedores.
Errores tipados
Los fallos de API se asignan a errores tipados (AuthenticationError, RateLimitError, ValidationError, NotFoundError, ServerError, TimeoutError y la base SubstackAPIError). El mapeo de estados y el análisis del cuerpo del error están documentados en errores tipados.
Exportación de borradores
Usa export_draft para un paquete Markdown/JSON de solo lectura, o ejecuta:
substack-mcp export 42 --output draft-export.json
substack-mcp export 42 --format markdown --output draft.md
Las exportaciones Markdown conservan el cuerpo original exacto en un archivo lateral .source.json. Inspecciona unsupported_nodes antes de reutilizar. Los archivos existentes requieren --force. Consulta comportamiento de exportación y CLI para selección de publicaciones, límites, exportaciones parciales y recuperación de archivos.
Soporte de Markdown
Los borradores aceptan Markdown CommonMark/GFM: encabezados, negrita/cursiva/tachado anidados, enlaces y enlaces de referencia, imágenes con pies de foto y destinos enlazados, listas anidadas con números iniciales, código, citas en bloque, reglas y saltos duros. Un bloque <!-- paywall --> independiente añade un muro de pago a un borrador de formato largo.
El contenido no compatible devuelve unsupported_nodes antes de una escritura. Después de revisar esos diagnósticos, los llamadores de borradores pueden establecer explícitamente allow_unsupported: true para conservar respaldos literales. Las tablas permanecen como Markdown dentro de bloques de código; las tablas nativas, los avisos y los embebidos arbitrarios no se anuncian como compatibles. Las notas al pie en párrafos de nivel superior se asignan a las notas al pie nativas del editor en borradores de formato largo. Las notas rechazan la conversión no compatible antes de la creación de la publicación o el adjunto y no tienen anulación de respaldo.
Consulta Autoría en Markdown para mapeos, límites, cambios de compatibilidad y la distinción entre fixtures fuera de línea y comprobaciones del editor en vivo.
Notas importantes
- Este servidor usa la API no oficial de Substack. Puede romperse si Substack cambia sus endpoints.
- Los tokens de sesión se envían como cookies. Mantén tu
SUBSTACK_SESSION_TOKENseguro. - El servidor comprueba tus credenciales al inicio, después de que se complete el handshake de MCP, y solo advierte — nunca bloquea el inicio en una llamada de red. Las herramientas aún fallan individualmente si el token está expirado, que es donde el fallo es accionable.
SIGTERMySIGINTse manejan: el servidor cierra su transporte y sale con 0, por lo quedocker stopregresa rápidamente en lugar de esperar el período de gracia.
Desarrollo
Para comprobaciones de lectura en vivo opcionales, consulta evidencia de contrato en vivo. La sonda está desactivada en CI ordinario y nunca publica ni escribe.
Antes de lanzar, ejecuta npm run test:package. Instala el tarball construido con dependencias de producción en un directorio temporal limpio, comprueba ambos puntos de entrada ejecutables y verifica la versión de MCP y el catálogo completo de herramientas registradas sin credenciales reales.
git clone https://github.com/conorbronsdon/substack-mcp.git
cd substack-mcp
npm install
npm run build
Ejecuta localmente:
SUBSTACK_PUBLICATION_URL=https://yourblog.substack.com \
SUBSTACK_SESSION_TOKEN=your-token \
SUBSTACK_USER_ID=your-id \
npm start
Contribuciones
Las issues y pull requests son bienvenidas. Debido a que este servidor usa la API no oficial de Substack, las contribuciones más útiles son correcciones cuando un endpoint cambia. Si una herramienta deja de funcionar, abre una issue con el nombre de la herramienta y el error. El límite seguro por diseño se mantiene: sin publicar, sin eliminar, sin programar publicaciones de formato largo. Las notas se publican inmediatamente por diseño y deben seguir diciéndolo claramente en sus descripciones.
Acerca de
Construido y mantenido por Conor Bronsdon para el flujo de trabajo de producción del podcast Chain of Thought, donde redacta y revisa publicaciones de boletines antes de que un humano pulse publicar. Conor presenta Chain of Thought, un programa sobre infraestructura de IA y cómo los profesionales realmente construyen con ella. Más herramientas para creadores viven en ai-tools-for-creators. Encuentra a Conor en X en @ConorBronsdon.
Herramientas complementarias:
- Transistor MCP: el servidor MCP oficial de Transistor.fm. Episodios, publicación y análisis.
- podcastindex-mcp: busca en el Podcast Index y rastrea apariciones de invitados
- op3-mcp: reporta descargas, geografía de oyentes y aplicaciones desde OP3
- apple-podcasts-mcp: obtén reproducciones, seguidores y escucha por episodio desde Apple Podcasts Connect
- gsc-mcp: consulta rendimiento de búsqueda, palabras clave y sitemaps en Google Search Console
- podcast-benchmark: compara un programa con sus pares usando solo datos públicos
Descargo de responsabilidad
Este es un proyecto personal independiente, no afiliado, patrocinado ni respaldado por ninguna empresa. Todas las opiniones expresadas son mías.
Plugin de Codex
El repositorio incluye un manifiesto de Codex en .codex-plugin/plugin.json y una configuración de MCP en .mcp.json. Ejecuta el paquete npm publicado sobre stdio usando npx; Node.js y npm deben estar disponibles. La versión del paquete está fijada en .mcp.json, por lo que actualizar el servidor del plugin es un cambio explícito.
Configura tus credenciales de Substack fuera del plugin usando las variables de entorno o la sesión de inicio de sesión del navegador descritas anteriormente. Nunca confirmes un token de sesión. La instalación no autentica una cuenta ni otorga aprobación para publicar. Las publicaciones de formato largo permanecen como borradores; las notas se publican inmediatamente.
Licencia
MIT