Skip to main content
Glama
jaimebg

youtube-studio-mcp

by jaimebg

YouTube Studio MCP

Un servidor MCP para auditar y mejorar la visibilidad de un canal de YouTube.

Conecta cualquier agente de IA compatible con MCP a los datos de tu propio canal: catálogo, métricas de la API de Analytics, curvas de retención, términos de búsqueda entrantes y las impresiones y el porcentaje de clics que solo una exportación de Studio CSV revela. Luego clasifica lo que vale la pena corregir por vistas recuperables en lugar de por porcentaje de clics; consulte Cómo se clasifican los de bajo rendimiento.

Ocho herramientas: auth_status, list_videos, get_video, query_analytics, get_search_terms, get_retention_curve, import_studio_data y find_underperformers.

Todo es de solo lectura y local: la caché SQLite, tus tokens OAuth y tus exportaciones de Studio nunca salen de tu máquina.

Requisitos

  • Node.js ≥ 22

  • Una cuenta de Google que sea propietaria del canal de YouTube

Related MCP server: MCP YouTube Intelligence

Configuración

1. Crea un proyecto de Google Cloud y habilita las API

  1. Ve a https://console.cloud.google.com/ y crea un proyecto.

  2. Habilita YouTube Data API v3 y YouTube Analytics API. (Ambas están en uso activo: la API de datos respalda la sincronización del catálogo y list_videos/get_video, y la API de Analytics respalda query_analytics, get_search_terms y get_retention_curve. Google Cloud Console solo te permite agregar un alcance de pantalla de consentimiento para una API que hayas habilitado, así que habilita ambas antes del siguiente paso).

2. Configura la pantalla de consentimiento de OAuth

  1. Ve a APIs y servicios → Pantalla de consentimiento de OAuth.

  2. Elige Externo y completa los campos obligatorios.

  3. Agrega estos alcances:

    • https://www.googleapis.com/auth/yt-analytics.readonly

    • https://www.googleapis.com/auth/youtube.readonly

    • https://www.googleapis.com/auth/youtube.force-ssl

Importante: publica la aplicación en Producción. Mientras la aplicación esté en Pruebas, Google caduca los tokens de actualización después de 7 días, por lo que tendrías que volver a autenticarte cada semana. Haz clic en Publicar aplicación. La aplicación permanece sin verificar, lo cual está bien: eres el único usuario y estás accediendo a tus propios datos. Verás una advertencia de "aplicación no verificada" una vez: elige Avanzado → Ir a (nombre de la aplicación).

3. Crea el cliente OAuth

  1. APIs y servicios → Credenciales → Crear credenciales → ID de cliente OAuth.

  2. Tipo de aplicación: Aplicación de escritorio.

  3. Descarga el JSON.

4. Instala y autentica

npm install
npm run build

Guarda el JSON del cliente OAuth descargado como credentials.json en el directorio de configuración del servidor (crea el directorio primero si no existe):

# Linux/macOS — adjust the source filename to match what Google actually
# named your download (it starts with "client_secret_")
mkdir -p ~/.config/youtube-studio-mcp
mv ~/Downloads/client_secret_*.json ~/.config/youtube-studio-mcp/credentials.json
# Windows (PowerShell) — same caveat about the source filename
New-Item -ItemType Directory -Force "$env:USERPROFILE\.config\youtube-studio-mcp" | Out-Null
Move-Item "$env:USERPROFILE\Downloads\client_secret_*.json" "$env:USERPROFILE\.config\youtube-studio-mcp\credentials.json"

Luego ejecuta:

node dist/index.js auth

Esto abre tu navegador automáticamente. Autoriza allí y los tokens se guardan en <config dir>/tokens.json. En Linux/macOS, el archivo se escribe con permisos de solo propietario (chmod 600); Windows no tiene bits de permisos de archivo equivalentes, por lo que ese paso no hace nada allí; confía en las protecciones normales de archivos de tu cuenta de usuario.

Si no se abre el navegador, el comando también escribe el enlace de autorización en <config dir>/authorize-url.txt; abre ese archivo y haz clic en el enlace. No copies manualmente la URL desde tu terminal: tiene ~520 caracteres, se envuelve en varias líneas y una copia truncada falla en Google con el error engañoso Required parameter is missing: response_type (el parámetro que falta está en la parte que se cortó, no en la solicitud que construimos).

Establece YTMCP_HOME para anular el directorio de configuración (por ejemplo, para un segundo canal o una configuración de prueba). Reemplaza toda la ruta ~/.config/youtube-studio-mcp, por lo que credentials.json, tokens.json y la caché SQLite se mueven con él.

5. Registra el servidor con tu agente de IA

El servidor habla MCP estándar a través de stdio, por lo que cualquier cliente compatible con MCP puede ejecutarlo. Necesitas una cosa en cada caso: la ruta absoluta a dist/index.js en este repositorio.

La mayoría de los clientes comparten la misma forma JSON. Sustituye tu propia ruta:

{
  "mcpServers": {
    "youtube-studio": {
      "command": "node",
      "args": ["/absolute/path/to/youtube-studio-mcp/dist/index.js"]
    }
  }
}

Agente

Dónde va ese JSON

Claude Code

claude mcp add youtube-studio -- node /absolute/path/to/dist/index.js

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json (macOS) · %APPDATA%\Claude\claude_desktop_config.json (Windows)

Cursor

~/.cursor/mcp.json para todos los proyectos, o .cursor/mcp.json dentro de uno

Windsurf

~/.codeium/windsurf/mcp_config.json

Cline

el cline_mcp_settings.json de la extensión, a través de MCP Servers → Configure

Continue

~/.continue/config.yaml (o config.json)

Gemini CLI

~/.gemini/settings.json

Zed

settings.json, bajo context_servers

Dos clientes usan una forma diferente.

VS Code / GitHub Copilot.vscode/mcp.json, con clave servers, no mcpServers:

{
  "servers": {
    "youtube-studio": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/youtube-studio-mcp/dist/index.js"]
    }
  }
}

OpenAI Codex CLI~/.codex/config.toml, TOML en lugar de JSON:

[mcp_servers.youtube-studio]
command = "node"
args = ["/absolute/path/to/youtube-studio-mcp/dist/index.js"]

Reinicia el agente después de editar su configuración. Pídele que ejecute auth_status: debería nombrar tu canal e informar la cuota restante. Si informa Authenticated: NO, vuelve a ejecutar node dist/index.js auth.

Si tu cliente no está en la lista, busca "MCP" en su configuración: el comando y los argumentos anteriores son todo lo que necesitan. Las rutas de configuración pueden cambiar entre versiones, así que consulta la documentación de tu cliente si una ruta aquí no existe.

Una nota sobre el comportamiento del agente

Cada herramienta está anotada con readOnlyHint: true, por lo que los agentes que muestran esa pista no pedirán confirmación de escritura. Nada en este servidor modifica tu canal: escribir metadatos de vuelta es una etapa posterior.

list_videos sirve desde la caché local a menos que se le pida sincronizar, y find_underperformers e import_studio_data nunca tocan la red. Solo las sincronizaciones explícitas y las consultas de Analytics gastan cuota, lo cual importa porque los agentes exploran: un agente que llama a list_videos veinte veces no cuesta nada, mientras que veinte sincronizaciones de catálogo agotarían el presupuesto de un día. auth_status informa lo que queda.

Herramientas

Herramienta

Propósito

auth_status

Estado de la conexión, identidad del canal, cuota restante, tamaño de la caché local

list_videos

Lista y filtra el catálogo; sync: true actualiza desde la API

get_video

Metadatos y estadísticas completos en caché para un video

query_analytics

Escape a la API de Analytics: métricas, dimensiones, filtros arbitrarios

get_search_terms

Las consultas de búsqueda que trajeron espectadores, referenciadas cruzadamente con los metadatos del video

get_retention_curve

Dónde dejan de ver los espectadores, como caídas anotadas en lugar de puntos brutos

import_studio_data

Importa impresiones y CTR desde una exportación CSV de Studio: la única métrica que la API de Analytics no expone. Lee un archivo local; no se necesita autenticación ni cuota

find_underperformers

Clasifica el catálogo por vistas recuperables: impresiones multiplicadas por la brecha hacia la línea base de CTR ponderado por impresiones del canal. Necesita una exportación de Studio importada primero; lee solo datos locales

list_videos sirve completamente desde la caché SQLite local a menos que pases sync: true; las lecturas simples (filtrar por Shorts/formato largo, recuento de vistas, fecha de publicación, título o clasificar) no cuestan cuota. Si aún no se ha sincronizado nada, te dice que lo llames de nuevo con sync: true en lugar de devolver una lista vacía.

get_search_terms y get_retention_curve almacenan en caché sus resultados por ventana de fecha (consulte Cuota a continuación); query_analytics no almacena en caché y siempre hace una llamada en vivo. get_search_terms devuelve como máximo 25 filas: Google limita el informe subyacente allí, por lo que un rango de fechas más amplio cambia qué términos se clasifican en los 25 principales en lugar de cuántas filas regresan.

Cuota

YouTube otorga 10,000 unidades/día más 100 llamadas search.list/día separadas. El servidor rastrea ambas y mantiene una reserva (500 unidades, 10 llamadas de búsqueda) para que una operación masiva no deje inutilizables las herramientas interactivas. La cuota se restablece a la medianoche del Pacífico, que es lo que informa auth_status.

Una sincronización completa del catálogo (list_videos con sync: true) hace una llamada channels.list, luego pagina la lista de reproducción de subidas (playlistItems.list, 50 videos por página) y obtiene los detalles de los videos en lotes (videos.list, 50 IDs por llamada), cada llamada cuesta 1 unidad. Eso equivale a 1 + ceil(videos/50) + ceil(videos/50) unidades: alrededor de 5 unidades para un canal de 100 videos.

La API de Analytics de YouTube tiene su propia cuota por proyecto en Cloud Console, separada de las 10,000 unidades de la API de datos. Las llamadas de Analytics se registran en el libro mayor local con costo cero, por lo que auth_status no mostrará que agotan tu presupuesto de la API de datos.

Los resultados de términos de búsqueda y curvas de retención se almacenan en caché por ventana de fecha, porque los informes subyacentes devuelven un top-N clasificado en un rango en lugar de filas por día. Una llamada repetida con las mismas fechas se sirve desde la caché; pasa refresh: true para volver a consultar.

Importación de impresiones y CTR

impressions e impressionClickThroughRate no existen en la API de Analytics de YouTube: son exclusivos de Studio. Para obtenerlos:

  1. YouTube Studio → AnalyticsModo avanzado (arriba a la derecha)

  2. Asegúrate de que las columnas Impresiones e Impresiones: porcentaje de clics estén visibles: la exportación contiene solo las columnas actualmente en pantalla

  3. ExportarValores separados por comas (.csv): obtienes un zip que contiene tres archivos

  4. Descomprímelo y luego ejecuta import_studio_data con la ruta de la carpeta

import_studio_data solo lee un archivo del disco: nunca llama a la API de datos de YouTube ni a la API de Analytics, por lo que no necesita autenticación ni cuesta cuota de API.

La ventana de fechas se lee del nombre de la carpeta (Studio la nombra como Contenido 2010-01-26_2026-08-09 Channel). Para anularla, pasa ambos rangeStart y rangeEnd (YYYY-MM-DD): proporcionar solo uno se rechaza con un error de validación en lugar de recurrir silenciosamente a la ventana del nombre de la carpeta, ya que eso podría colocar datos bajo fechas incorrectas sin advertencia. Ambas fechas deben ser fechas de calendario reales (2026-13-45 se rechaza, no se redondea) y rangeStart no debe ser posterior a rangeEnd.

Las impresiones y el CTR son un agregado del rango completo. De los tres archivos de la exportación, solo la tabla por vídeo (Datos de la tabla.csv / Table data.csv) contiene impresiones y CTR, y presenta una fila por vídeo sumada en todo el rango de fechas: no hay ningún CTR diario en la exportación. El archivo por día (Datos del gráfico.csv / Chart data.csv) y el archivo de totales del canal (Totales.csv / Totals.csv) solo contienen vistas. Por lo tanto, comparar entre períodos implica importar varias exportaciones con distintos rangos, no segmentar una sola.

import_studio_data acepta la carpeta de exportación o una ruta CSV concreta. Si se apunta a la carpeta, encuentra el archivo de tabla automáticamente. Si se apunta directamente a uno de los otros dos archivos, la importación se rechaza de plano: la cabecera de un CSV indica sin ambigüedad cuál de los tres informes es (reportType es table, chart o totals — ver src/studio/csvSchemas.ts), y solo table contiene algo que este importador pueda almacenar. El archivo de gráfico sí tiene un id de vídeo, por lo que una importación ingenua tendría éxito silenciosamente, sobrescribiendo las impresiones/CTR con NULL y las vistas con la cifra del último día en lugar del total del rango; el archivo de totales no tiene ningún id de vídeo. Ambos se rechazan antes de escribir nada, con un mensaje que indica Datos de la tabla.csv / Table data.csv como el archivo al que apuntar en su lugar.

Las filas de vídeos que ya no son públicos se almacenan y se notifican como no coincidentes; eso es lo esperado, no un error.

Shorts

Un vídeo se considera un Short solo si dura 180 segundos o menos y se publicó el 2020-09-14 o después, el día en que se lanzaron los Shorts.

La duración por sí sola no basta. En un catálogo de vídeos de formato largo naturalmente cortos — videoclips, ediciones, tráilers —, una regla basada solo en la duración clasifica erróneamente de forma masiva. La verificación en vivo contra un canal inactivo anterior a 2020 marcó aproximadamente el 70% de su catálogo como Shorts, todos ellos falsos positivos: la subida más reciente del canal se había publicado meses antes del lanzamiento de los Shorts, así que ninguno de ellos podía ser genuino. find_underperformers lee esta marca a través de su parámetro cohort. Pasar cohort: 'short' o cohort: 'long' restringe la línea base a esa mitad del catálogo, de modo que los Shorts y el formato largo solo se comparan con los de su propio tipo. El valor predeterminado, cohort: 'all', no hace esa segmentación — combina ambos en una única línea base mezclada. En un catálogo que ya es una sola cohorte (el caso real de este usuario, totalmente de formato largo), agrupar no tiene efecto; pero en un catálogo mixto el valor predeterminado mezcla dos poblaciones con CTR típicos diferentes; pasa cohort explícitamente para segmentarlas. Una marca incorrecta en un vídeo produciría un sinsentido con apariencia de certeza, en lugar de un error evidente, por eso la salvaguarda de la fecha de publicación es importante.

Cómo se clasifican los vídeos de bajo rendimiento

find_underperformers clasifica por vistas recuperables, no por la tasa de clics:

recoverable views = impressions x (baseline CTR - video CTR) / 100

Eso es una estimación de las vistas que un vídeo habría obtenido con la línea base del propio canal — la cantidad sobre la que vale la pena actuar. Clasificar solo por CTR induce a error, de tres maneras concretas:

  • Las impresiones se concentran. La mayoría de las impresiones de un canal se encuentran en una pequeña fracción de sus vídeos, por lo que el "peor CTR" y la "mayor oportunidad" son conjuntos casi disjuntos. El vídeo con la proporción más fea suele ser uno que casi no se mostró a nadie.

  • Cero impresiones producen un CTR de 0% por división, no por rendimiento. Ordenar ascendentemente coloca cada vídeo nunca mostrado en la parte superior de la lista de cosas a corregir, que es exactamente al revés.

  • El CTR más alto de un canal suele ser un denominador diminuto — un puñado de impresiones que casualmente convirtieron. Es ruido presentado como un triunfo.

De ahí se derivan dos reglas. Los vídeos por debajo de un umbral mínimo de impresiones se notifican como datos insuficientes y nunca se clasifican como de bajo rendimiento. Y la línea base está ponderada por impresiones, porque una media no ponderada está dominada por vídeos de bajo tráfico y no describe casi nada del tráfico que el canal recibe realmente.

Cada oportunidad está tipificada. weak_metadata significa que la puntuación de metadatos es lo bastante baja como para ser lo primero a corregir; low_ctr significa que los metadatos ya son correctos y la palanca es el encuadre de la miniatura o del título.

Desarrollo

npm test          # unit tests, no network
npm run typecheck
npm run build

npm run typecheck ejecuta dos proyectos: tsconfig.json (src/**, la compilación) y tsconfig.test.json (src/** + test/** + vitest.config.ts, solo noEmit). Ejecuta solo el proyecto de pruebas con npm run typecheck:test. Vitest en sí mismo solo elimina los tipos mediante esbuild y no comprueba tipos, así que npm run typecheck es lo que realmente detecta un error de tipo en un archivo de prueba.

A
license - permissive license
Not graded
quality - not tested
B
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 Servers

View all related MCP servers

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/jaimebg/youtube-studio-mcp'

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