TVsubtitles
Busca series de TV en tvsubtitles.net, lee la cobertura de subtítulos de una temporada y un registro. Sin clave de API.
Documentación
mcp-tvsubtitles
TVsubtitles.net cataloga subtítulos para series de televisión. Sus lectores suben un archivo para un episodio, sincronizado con una versión de video, y el sitio registra el idioma, la versión para la que fue cortado, quién lo subió y cuándo, el tamaño del archivo y con qué frecuencia se ha descargado. Contiene alrededor de trescientos mil de ellos, en unas ochenta y seis mil episodios en veinticuatro idiomas.
Este servidor conecta un cliente de chat con ese catálogo. Puedes buscar una serie, leer una temporada y ver qué idiomas tienen algo para cada episodio, leer los registros de un episodio y abrir un registro con la versión para la que fue cortado y quién lo subió. Cada registro lleva la dirección de su página en el sitio. No se necesita clave API ni cuenta.
Instalación
Instalación con un clic
Claude Code
claude mcp add tvsubtitles -- npx -y mcp-tvsubtitles
Cualquier cliente que lea mcpServers
{
"mcpServers": {
"tvsubtitles": {
"command": "npx",
"args": ["-y", "mcp-tvsubtitles"]
}
}
}
Con Docker
{
"mcpServers": {
"tvsubtitles": {
"command": "docker",
"args": ["run", "--rm", "-i", "ghcr.io/smeet666/mcp-tvsubtitles:1.0.1"]
}
}
}
El contenedor alcanza https://www.tvsubtitles.net y nada más.
Paquete, sin npm
Descarga mcp-tvsubtitles.mcpb desde el
último lanzamiento y
ábrelo con un host que instale paquetes MCP. Lleva sus dependencias, así que
solo necesita Node 24 o posterior.
Lo que puedes preguntar
- "¿Tiene tvsubtitles subtítulos en francés para Smallville?"
- "¿Qué idiomas cubren la temporada 3 de Harbour Lights?"
- "Enumera los subtítulos en inglés para el episodio 7 de esa temporada."
- "¿Para qué versión está sincronizado ese subtítulo y quién lo subió?"
- "Encuéntrame la página para descargar el subtítulo en polaco del final."
Herramientas
| Herramienta | Qué hace |
|---|---|
search_titles | Encuentra una serie de televisión por nombre y devuelve el id que usan las demás. |
list_subtitles | Lee la cobertura de una temporada, o los registros de subtítulos de un episodio. |
get_subtitle | Lee un registro, con su versión, su subidor y su página de descarga. |
list_languages | Enumera los idiomas que tiene el catálogo, o los que tiene una serie. |
search_titles
Busca en el catálogo por nombre. El sitio solo cataloga televisión, así que una búsqueda de una película se rechaza en lugar de responderse.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
query | cadena, 1–120 caracteres | sí | El nombre de una serie, o parte de ella. |
media_type | movie | tv | any | no | tv y any buscan en el catálogo. movie se rechaza. |
year | entero, 1900–2100 | no | Mantiene filas cuyos años publicados cubren este. |
limit | entero, 1–100, predeterminado 20 | no | Filas a mostrar. |
with_counts | booleano, predeterminado falso | no | Lee los recuentos de subtítulos, episodios y temporadas de cada fila desde el índice del catálogo, a costa de una solicitud adicional. |
A cambio: las series coincidentes, cada una con el id que usan las otras herramientas, los
años que publica el sitio y los idiomas para los que muestra una bandera. imdb_id y
tmdb_id son nulos, porque la búsqueda del sitio no publica ninguno. subtitle_count,
episode_count y season_count son nulos a menos que with_counts los pida,
ya que el sitio publica esos tres en su índice del catálogo en lugar de en la
página que responde una búsqueda; cada uno cuenta todas las temporadas de la serie juntas, lo que
counts_scope nombra, cada uno se lee por separado, y una serie que el índice no tiene
fila mantiene tres nulos. total_available cuenta las filas que devolvió esta búsqueda,
lo que total_counts nombra. Un año que no deja nada se aparta
y se nombra en filters_dropped.
list_subtitles
Lee lo que tiene una serie, en una de dos formas que kind nombra.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
id | cadena, 1–12 caracteres | sí | Un id de serie de search_titles. |
season | entero, 1–200 | no | Si se omite, se lee la temporada más reciente que tiene el sitio. |
episode | entero, 1–500 | no | Si se nombra, la respuesta son los registros de ese episodio. |
language | cadena, 1–40 caracteres | no | Un idioma de list_languages, por nombre, código del sitio o etiqueta BCP 47. |
limit | entero, 1–200, predeterminado 40 | no | Filas a mostrar. |
A cambio: con solo una temporada, kind lee coverage y cada fila es un
episodio, que lleva episode_id, el número de subtítulos que cuenta el sitio y los
idiomas que tienen algo. Con un episodio nombrado, kind lee subtitles y
cada fila es un registro que lleva el id que get_subtitle toma. season es la
temporada que sirvió el sitio y season_requested la que se pidió, que
difieren cuando se leyó la más reciente. seasons_available enumera las temporadas que tiene la serie.
Un idioma que no tiene nada se aparta, la respuesta vuelve
sin estrechar, y filters_dropped lo nombra.
get_subtitle
Lee un registro de un id list_subtitles devuelto.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
id | cadena, 1–12 caracteres | sí | Un id de subtítulo de list_subtitles. |
A cambio: el registro, con page_url para la página que un lector abre para
descargar el archivo. read_from lee record aquí y listing en una fila
list_subtitles produjo, que es lo que distingue un campo no leído de uno que el sitio
no publica: un listado no lleva file_name, ni size_text ni
comment, porque el sitio imprime esos solo en la página del registro. releases contiene las versiones de video que publicó el sitio y
release_match dice si publicó alguna: stated donde lo hizo, none
donde no, así que un registro marcado none no dice nada sobre a qué video está
sincronizado. uploader es nulo en aproximadamente dos de cada tres registros. published_at
es la marca del sitio leída en ISO 8601 y no lleva zona horaria, y
published_text mantiene la redacción propia del sitio. rating contiene dos contadores que
publica el sitio, donde un cero es una cifra que imprimió.
list_languages
Enumera los idiomas que cataloga el sitio, o los que tiene una serie.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
id | cadena, 1–12 caracteres | no | Un id de serie, para leer lo que tiene esa serie. |
season | entero, 1–200 | no | Qué temporada medir sobre una serie. Se ignora sin id. |
A cambio: cada idioma con el nombre que imprime el sitio, el código de dos letras
site_code con el que el sitio lo aborda, la etiqueta BCP 47 code donde ese mapeo es
seguro, y differs_from_iso. scope dice qué se midió: catalogue para
todo el sitio, o season cuando se pasó un id de serie, y count son entonces los
episodios de esa temporada que tienen el idioma.
Idiomas y los códigos que usa el sitio
El sitio muestra veinticuatro banderas y aborda cada idioma con dos letras de
su propia elección. Seis de ellas difieren de ISO 639-1, y una colisiona: el sitio
escribe br para portugués brasileño, que ISO asigna al bretón.
| Código del sitio | Idioma | BCP 47 |
|---|---|---|
br | Portugués brasileño | pt-BR |
gr | Griego | el |
cz | Checo | cs |
jp | Japonés | ja |
cn | Chino | zh |
ua | Ucraniano | uk |
language mantiene el nombre propio del sitio y language_code lleva la etiqueta, así que
no hay que derivar nada de las dos letras. list_subtitles acepta un
idioma escrito de cualquiera de las tres formas.
Configuración
No hay que configurar nada. Cada variable a continuación es opcional.
| Variable | Predeterminado | Rango | Qué hace |
|---|---|---|---|
TVS_USER_AGENT | sin definir | Se antepone al agente propio de este servidor, que permanece adjunto. | |
TVS_MIN_INTERVAL_MS | 2000 | 1500–60000 | Milisegundos entre dos solicitudes. 1500 es un mínimo. |
TVS_TIMEOUT_MS | 20000 | 1000–120000 | Plazo para un intento. |
TVS_BUDGET_MS | 60000 | 5000–600000 | Plazo para una lectura, con sus reintentos incluidos. |
TVS_MAX_RETRIES | 3 | 0–8 | Intentos después del primero. |
TVS_CACHE_TTL_MS | 900000 | 0–86400000 | Cuánto tiempo se mantiene una página en memoria. 0 apaga el almacén. |
TVS_CACHE_MAX_ENTRIES | 200 | 1–5000 | Páginas mantenidas antes de que se descarte la menos usada recientemente. |
TVS_MAX_BODY_BYTES | 8000000 | 100000–64000000 | La respuesta más grande leída para una página. |
TVS_LOG_LEVEL | error | silent, error, info, debug | Qué llega a stderr. |
Un valor fuera de su rango se rechaza en stderr y se mantiene el predeterminado.
Errores
| Código | Qué significa | Qué hacer |
|---|---|---|
not_found | El sitio respondió y no tiene tal cosa. | Verifica que el id provenga de un listado y no escrito a mano. |
invalid_input | Los argumentos no pudieron producir una solicitud. | Lee el mensaje, que nombra el argumento. |
rate_limited | El sitio pidió a este cliente que vaya más lento. | Espera y vuelve a preguntar. Lo solicitado aún existe. |
parse_failure | Llegó una respuesta en una forma que esto no puede leer. | Repórtalo con los argumentos usados. |
network_error | La solicitud no se completó. | Inténtalo de nuevo. |
timeout | No llegó ninguna respuesta dentro del plazo. | Inténtalo de nuevo, o eleva TVS_BUDGET_MS. |
Como biblioteca
La capa que lee el sitio se publica por separado, con el ritmo, el almacén y los códigos de error, y sin protocolo adjunto.
import { TvSubtitlesClient } from "mcp-tvsubtitles/client";
const client = new TvSubtitlesClient();
const found = await client.searchShows("Smallville");
const season = await client.getSeason(found.data.rows[0].id, 0);
console.log(season.data.showName, season.data.season, season.data.episodes.length);
Cada lectura devuelve { data, cached }, con skipped cuando se omitieron filas.
El constructor toma { config, logger, fetchImpl }, y el piso del intervalo
mantiene lo que se le pase.
Ritmo y atribución
Una solicitud a la vez, con dos segundos de separación, ampliándose cuando el sitio presiona y reduciéndose de nuevo tras una racha de respuestas limpias. El piso de 1.5 segundos no se puede bajar. La cadena de agente lleva el nombre del proyecto, su versión y la dirección de este repositorio, para que el sitio pueda contactar a una persona.
Los subtítulos son obra de quienes los escribieron y sincronizaron. Este servidor lee
el catálogo y no descarga ningún archivo de subtítulos: cada registro lleva page_url,
que es la página que un lector abre para descargarlo. Da crédito a tvsubtitles.net y enlaza
esa página cuando muestres un resultado.
Este servidor MCP no está afiliado a tvsubtitles.net.
Privacidad
Sin cuenta, sin clave, sin telemetría. El único host al que se accede es
https://www.tvsubtitles.net. Las páginas se mantienen en memoria durante quince minutos y
no se escribe nada en disco. Los diagnósticos van a stderr. Ver PRIVACY.md.
Desarrollo
npm install
npm run build:fixtures
npm test
npm run coverage
npm run check
npm run test:live hace una solicitud por ruta contra el sitio y se ejecuta
cada noche.
Contribuciones
Las issues y pull requests son bienvenidas. Ver CONTRIBUTING.md y SECURITY.md.
Licencia
MIT, ver LICENSE.
mcp-tvsubtitles (français)
TVsubtitles.net cataloga los subtítulos de series de televisión. Sus lectores suben un archivo para un episodio, ajustado a una versión de video, y el sitio registra el idioma, la versión para la que fue diseñado, quién lo subió y cuándo, el tamaño del archivo y el número de veces que se ha descargado. Tiene alrededor de trescientos mil, en unos ochenta y seis mil episodios, en veinticuatro idiomas.
Este servidor conecta un cliente de conversación con ese catálogo. Se puede buscar una serie, leer una temporada viendo qué idiomas tienen algo para cada episodio, leer las fichas de un episodio y abrir una ficha con la versión para la que fue diseñada y quién la subió. Cada ficha lleva la dirección de su página en el sitio. No se necesitan claves de API ni cuentas.
Instalación
Instalación en un clic
Claude Code
claude mcp add tvsubtitles -- npx -y mcp-tvsubtitles
Cualquier cliente que lea mcpServers
{
"mcpServers": {
"tvsubtitles": {
"command": "npx",
"args": ["-y", "mcp-tvsubtitles"]
}
}
}
Con Docker
{
"mcpServers": {
"tvsubtitles": {
"command": "docker",
"args": ["run", "--rm", "-i", "ghcr.io/smeet666/mcp-tvsubtitles:1.0.1"]
}
}
}
El contenedor incluye https://www.tvsubtitles.net y nada más.
Bundle, sin npm
Descargar mcp-tvsubtitles.mcpb desde la
última publicación
y abrirlo con un host que instale bundles MCP. Trae sus
dependencias, así que Node 24 o más reciente es suficiente.
Lo que se puede pedir
- «¿Tiene tvsubtitles subtítulos en francés para Smallville?»
- «¿Qué idiomas cubren la temporada 3 de Harbour Lights?»
- «Lista los subtítulos en inglés del episodio 7 de esa temporada.»
- «¿Sobre qué versión está ajustado este subtítulo y quién lo subió?»
- «Encuéntrame la página para descargar el subtítulo en polaco del último episodio.»
Las herramientas
| Herramienta | Qué hace |
|---|---|
search_titles | Encuentra una serie por su nombre y devuelve el id que las demás toman. |
list_subtitles | Lee la cobertura de una temporada, o las fichas de un episodio. |
get_subtitle | Lee una ficha, con su versión, su subidor y su página de descarga. |
list_languages | Lista los idiomas del catálogo, o los que tiene una serie. |
search_titles
Busca en el catálogo por el nombre. El sitio solo cataloga televisión, así que una búsqueda de película se rechaza en lugar de responderse.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
query | cadena, de 1 a 120 caracteres | sí | El nombre de una serie, o una parte. |
media_type | movie | tv | any | no | tv y any buscan en el catálogo. movie se rechaza. |
year | entero, de 1900 a 2100 | no | Mantiene las filas cuyos años publicados cubren este. |
limit | entero, de 1 a 100, por defecto 20 | no | Filas a devolver. |
with_counts | booleano, por defecto falso | no | Lee los conteos de subtítulos, episodios y temporadas de cada fila en el índice del catálogo, al costo de una solicitud más. |
En respuesta: las series encontradas, cada una con el id que toman las demás
herramientas, los años publicados por el sitio y los idiomas para los que dibuja
una bandera. imdb_id y tmdb_id valen null, ya que la búsqueda del sitio no
publica ninguno. subtitle_count, episode_count y season_count valen null
mientras with_counts no los pida, porque el sitio publica esas tres cifras
en el índice de su catálogo y no en la página que responde a una búsqueda;
cada uno cuenta todas las temporadas de la serie juntas, lo que counts_scope
nombra, cada uno se lee por separado, y una serie cuyo índice no tenga ninguna fila
mantiene tres null. total_available cuenta las filas que esta búsqueda
trajo, lo que total_counts nombra. Un año que no deja nada se deja de
lado y se nombra en filters_dropped.
list_subtitles
Lee lo que una serie tiene, en una de dos formas que kind nombra.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
id | cadena, de 1 a 12 caracteres | sí | Un id de serie venido de search_titles. |
season | entero, de 1 a 200 | no | Omitido, se lee la temporada más reciente. |
episode | entero, de 1 a 500 | no | Nombrado, la respuesta lleva las fichas de ese episodio. |
language | cadena, de 1 a 40 caracteres | no | Un idioma de list_languages, por su nombre, su código o su etiqueta BCP 47. |
limit | entero, de 1 a 200, por defecto 40 | no | Filas a devolver. |
En respuesta: con una temporada sola, kind vale coverage y cada fila es
un episodio, que lleva episode_id, el número de subtítulos que el sitio cuenta y
los idiomas que tienen algo. Con un episodio nombrado, kind vale
subtitles y cada fila es una ficha que lleva el id que toma
get_subtitle. season es la temporada servida por el sitio y season_requested
la solicitada, y ambas difieren cuando se leyó la más reciente.
seasons_available lista las temporadas que la serie tiene. Un idioma que no tiene
nada se deja de lado, la respuesta vuelve sin la restricción, y
filters_dropped lo nombra.
get_subtitle
Lee una ficha desde un id devuelto por list_subtitles.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
id | cadena, de 1 a 12 caracteres | sí | Un id de subtítulo venido de list_subtitles. |
En respuesta: la ficha, con page_url para la página que un lector abre para
descargar el archivo. read_from vale aquí record, y listing en una
fila venida de list_subtitles: eso es lo que distingue un campo no leído de un
campo que el sitio no publica, porque una lista no lleva ni file_name, ni
size_text, ni comment, que el sitio solo imprime en la página de una ficha. releases lleva las versiones de video publicadas por el
sitio y release_match dice si publicó una: stated cuando sí, none
cuando no, así que una ficha marcada none no dice nada sobre el video en el que
está ajustada. uploader vale null en aproximadamente dos de cada tres fichas.
published_at es la marca de tiempo del sitio leída en ISO 8601 y no lleva ninguna zona horaria,
y published_text mantiene la redacción del sitio. rating lleva dos contadores
que el sitio publica, donde un cero es una cifra que imprimió.
list_languages
Lista los idiomas que el sitio cataloga, o los que tiene una serie.
| Argumento | Tipo | Requerido | Qué hacer |
|---|---|---|---|
id | cadena, de 1 a 12 caracteres | no | Un id de serie, para leer lo que esa serie tiene. |
season | entero, de 1 a 200 | no | Sobre qué temporada medir. Ignorado sin id. |
En respuesta: cada idioma con el nombre que el sitio imprime, el site_code de
dos letras con el que lo dirige, el code BCP 47 cuando la correspondencia
es segura, y differs_from_iso. scope dice qué se midió:
catalogue para el sitio completo, o season cuando se pasó un id de serie, y
count vale entonces los episodios de esa temporada que tienen el idioma.
Los idiomas y los códigos del sitio
El sitio dibuja veinticuatro banderas y dirige cada idioma con dos letras
de su elección. Seis difieren del ISO 639-1, y una entra en colisión: el sitio
escribe br para el portugués brasileño, que el ISO atribuye al bretón.
| Código del sitio | Idioma | BCP 47 |
|---|---|---|
br | Portugués brasileño | pt-BR |
gr | Griego | el |
cz | Checo | cs |
jp | Japonés | ja |
cn | Chino | zh |
ua | Ucraniano | uk |
language guarda el nombre del sitio y language_code lleva la etiqueta, así que nada
se deduce de las dos letras. list_subtitles acepta un idioma escrito de cualquiera
de las tres formas.
Configuración
No hay nada que ajustar. Todas las variables siguientes son opcionales.
| Variable | Predeterminado | Límites | Qué hace |
|---|---|---|---|
TVS_USER_AGENT | ausente | Se coloca delante del agente del servidor, que permanece adjunto. | |
TVS_MIN_INTERVAL_MS | 2000 | 1500 a 60000 | Milisegundos entre dos solicitudes. 1500 es un mínimo. |
TVS_TIMEOUT_MS | 20000 | 1000 a 120000 | Tiempo de espera de un intento. |
TVS_BUDGET_MS | 60000 | 5000 a 600000 | Tiempo de espera de una lectura, reintentos incluidos. |
TVS_MAX_RETRIES | 3 | 0 a 8 | Reintentos después del primero. |
TVS_CACHE_TTL_MS | 900000 | 0 a 86400000 | Duración de conservación de una página en memoria. 0 apaga la caché. |
TVS_CACHE_MAX_ENTRIES | 200 | 1 a 5000 | Páginas guardadas antes de que la más antigua se elimine. |
TVS_MAX_BODY_BYTES | 8000000 | 100000 a 64000000 | Respuesta más grande leída para una página. |
TVS_LOG_LEVEL | error | silent, error, info, debug | Lo que llega a stderr. |
Un valor fuera de los límites se rechaza en stderr y se aplica el predeterminado.
Errores
| Código | Qué significa | Qué hacer |
|---|---|---|
not_found | El sitio respondió y no tiene esa cosa. | Verificar que el id proviene de una lista y no de una construcción. |
invalid_input | Los argumentos no pueden producir una solicitud. | Leer el mensaje, que nombra el argumento. |
rate_limited | El sitio pide a este cliente que reduzca la velocidad. | Esperar y volver a pedir. La cosa solicitada sigue existiendo. |
parse_failure | Una respuesta llegó en una forma ilegible. | Reportarlo con los argumentos utilizados. |
network_error | La solicitud no se completó. | Reintentar. |
timeout | Sin respuesta dentro del tiempo límite. | Reintentar, o ampliar TVS_BUDGET_MS. |
Como biblioteca
La capa que lee el sitio se publica sola, con su ritmo, su caché y sus códigos de error, sin protocolo adjunto.
import { TvSubtitlesClient } from "mcp-tvsubtitles/client";
const client = new TvSubtitlesClient();
const found = await client.searchShows("Smallville");
const season = await client.getSeason(found.data.rows[0].id, 0);
console.log(season.data.showName, season.data.season, season.data.episodes.length);
Toda lectura devuelve { data, cached }, con skipped cuando se han
descartado líneas. El constructor toma { config, logger, fetchImpl }, y el mínimo
de intervalo se mantiene sin importar lo que se le pase.
Ritmo y atribución
Una solicitud a la vez, dos segundos de diferencia, ampliado cuando el sitio rechaza y reducido después de una serie de respuestas limpias. El mínimo de un segundo y medio no se puede reducir. La cadena de agente lleva el nombre del proyecto, su versión y la dirección de este repositorio, para que el sitio pueda contactar a una persona.
Los subtítulos son obra de quienes los escribieron y ajustaron. Este servidor lee
el catálogo y no descarga ningún archivo de subtítulos: cada ficha lleva
page_url, la página que un lector abre para descargarlo. Acreditar
tvsubtitles.net y enlazar esa página al mostrar un resultado.
Este servidor MCP no está afiliado a tvsubtitles.net.
Privacidad
Sin cuentas, sin claves, sin telemetría. El único host contactado es
https://www.tvsubtitles.net. Las páginas se guardan quince minutos en memoria
y nada se escribe en el disco. Los diagnósticos van a stderr. Ver
PRIVACY.md.
Desarrollo
npm install
npm run build:fixtures
npm test
npm run coverage
npm run check
npm run test:live hace una solicitud por ruta contra el sitio, y se ejecuta cada
noche.
Contribuir
Las issues y las pull requests son bienvenidas. Ver CONTRIBUTING.md y SECURITY.md.
Licencia
MIT, ver LICENSE.