tvtracker-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@tvtracker-mcp найди сериал, я не помню названия — там сотрудникам хирургически разделяют память"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
tvtracker-mcp
MCP-сервер, который находит сериал по описанию сюжета, ведёт прогресс просмотра и отвечает на вопрос «что включить» одним вызовом.
Ты: найди сериал, я не помню названия — там сотрудникам хирургически разделяют память
Severance (2022–, Apple TV+, идёт) · Drama/Science-Fiction/Mystery · 49 мин · 7.6
Mark Scout leads a team at Lumon Industries, whose employees have undergone a
severance procedure, which surgically divides their memories between their work…
→ отслеживаю, остановился на 2x03Найдено за один вызов среди 89 664 сериалов. В TVmaze такого запроса нет вообще: их API ищет только по названию.
Зачем он нужен, если есть API
Обёртка транслирует эндпоинты в инструменты один к одному. Ценность такого сервера нулевая: то же самое агент получил бы через generic-инструмент HTTP.
Сервер оправдан, только когда отвечает на вопросы, на которые ни TVmaze, ни локальная база поодиночке ответить не могут. Здесь таких три:
Вопрос | Почему API не отвечает | Кто считает |
«Найди сериал по описанию» | в TVmaze поиска по тексту описаний нет | FTS5 + BM25 по локальному корпусу |
«Что у меня накопилось» | нужен личный прогресс, которого у API нет | пересечение трекинга с |
«Стоит ли продолжать» | оценки серий лежат мёртвым грузом | агрегация рейтингов по сезонам |
Всё три считает наш код. Это и есть граница между продуктом и обёрткой.
Related MCP server: Movie Search MCP Server
Установка
Нужен uv и Python 3.11+. Ключ API не нужен: TVmaze отдаёт данные без авторизации.
git clone https://github.com/seno76/tvtracker-mcp.git && cd tvtracker-mcp
uv sync --all-groups
cp .env.example .env
uv run tvtracker sync --full # корпус: ~380 запросов, около четырёх минут
uv run tvtracker status # сериалов: 89664Подключение к хосту:
uv run mcp install src/tvtracker/server.py # Claude Code / Claude Desktop
uv run mcp dev src/tvtracker/server.py # MCP Inspector, посмотреть примитивыТранспорт — stdio. Обслуживание базы вынесено в CLI: четыре минуты внутри вызова инструмента — гарантированный таймаут у хоста.
Инструменты (5)
Инструмент — это сценарий, а не эндпоинт. Типовой запрос закрывается за один-два вызова; изменения состояния собраны в один инструмент с enum-действием вместо шести. Все возвращают текст, а не сырой JSON, и каждый сериал в выдаче помечен твоим состоянием отслеживания — этого в TVmaze нет ни при каком запросе.
show_search — найти сериал
show_search(query="", by="auto"|"title"|"description", genre=None, status=None,
language=None, year_from=None, year_to=None, min_rating=None,
limit=8, response_format="concise"|"detailed")Три режима в одном инструменте, потому что для пользователя это один сценарий:
Режим | Как вызвать | Что делает |
по названию |
| точные и частичные совпадения, ранжирование по популярности |
по описанию |
| BM25 по очищенным аннотациям — главная функция сервера |
по фильтрам |
| отбор каталога без поиска |
by="auto" решает сам: короткий запрос — название, фраза — описание. Если название не
нашлось, он пробует корпус, прежде чем сказать «ничего», — это экономит целый вызов.
Severance (2022–, Apple TV+, идёт) · Drama/Science-Fiction/Mystery · 49 мин · 7.6
Mark Scout leads a team at Lumon Industries, whose employees have undergone a severance
procedure, which surgically divides their memories between their work and personal lives.
→ отслеживаю, остановился на 2x03
I Need Romance (2011–2014, tvN, завершён) · Drama/Comedy/Romance · 60 мин · 6.8
A drama about the lives of employees at a home shopping company and the love between
friends in their 30s.
→ брошен (1x04)
Это лучшие совпадения по описанию, а не полный список.
Сузить: genre="Science-Fiction" или year_from=2020.Шесть полей на сериал, а не сорок. image, _links, externals отбрасываются при
загрузке и физически не могут попасть в контекст.
show_profile — расскажи про сериал
show_profile(show, response_format="concise"|"detailed")Агрегат четырёх эндпоинтов TVmaze плюс два блока, которых в API нет: рейтинговый профиль по сезонам и позиция пользователя. Обёртка потратила бы здесь четыре вызова и не дала бы ни того ни другого.
Severance (2022–, Apple TV+, идёт) · Drama/Science-Fiction/Mystery · 49 мин · 7.6
Mark Scout leads a team at Lumon Industries, whose employees have undergone a severance
procedure, which surgically divides their memories between their work and personal lives.
→ отслеживаю, остановился на 2x03
Рейтинг по сезонам — с1: 8.1 (7) · с2: 7.7 (5). Тренд: проседает.
Ты на 2x03. Впереди 2 серии, ~1 ч 40 мин.Строка «с1: 8.1 · с2: 7.7 · тренд проседает» — это и есть то, ради чего затевалась агрегация: без неё формулировка «перетерпи до 3x05» невозможна.
episode_search — найти серию по описанию
episode_search(query, show=None, season=None, include_specials=False,
include_unwatched=False, limit=5)«Серия, где они застряли в лифте» — запрос, на который TVmaze не отвечает. Работает по кэшу эпизодов, то есть по отслеживаемым сериалам; если сериал указан, а эпизодов нет, подгружает их на лету.
Защита от спойлеров. По умолчанию описания серий после текущей позиции не показываются — только факт наличия. Такого поведения у обёртки не может быть в принципе: оно требует знания прогресса.
Severance 2x01 «Season Two, Part 1» — The severed floor deals with the aftermath.
Severance 2x02 «Season Two, Part 2» — The severed floor deals with the aftermath.
Severance 2x03 «Season Two, Part 3» — The severed floor deals with the aftermath.
Severance 2x04 «Season Two, Part 4» — ты до неё ещё не дошёл, описание скрыто
(include_unwatched=true покажет).
Severance 2x05 «Season Two, Part 5» — ты до неё ещё не дошёл, описание скрыто.Граница проходит ровно по позиции: просмотренное показано, непросмотренное скрыто, но о его существовании сказано честно.
tracking_update — изменить состояние просмотра
tracking_update(show, action="track"|"untrack"|"progress"|"rate"|"pause"|"finish",
episode=None, rating=None, note=None)Один инструмент вместо шести. episode принимает человеческий формат "2x03"
(кириллическая «х» тоже). При action="track" эпизоды сериала загружаются и индексируются.
Ответ подтверждает изменение и сразу даёт следующий шаг — иначе «отметил серию» превращается во второй вызов «а что дальше»:
Отмечено: Severance 2x04. Дальше — 2x05, «Season Two, Part 5», 50 мин, вышла.Единственный инструмент, помеченный как изменяющий данные (readOnlyHint = false).
После него сервер шлёт уведомление об изменении ресурсов, и хост перечитывает их сам.
watch_next — что включить
watch_next(minutes=60, include_new=False, limit=3)Не поиск, а решение. Берёт бэклог, фильтрует по свободному времени (с запасом 10 %), ранжирует по своим оценкам и размеру долга. Тот вызов, ради которого затевается сервер: вопрос «что посмотреть» закрывается одним обращением, без предварительных поисков.
Из накопившегося за 60 мин:
Severance 2x04 «Season Two, Part 4» — 50 мин, накопилось 2, твоя оценка сериала 9
The Bear 3x09 «Course 9» — 30 мин, накопилось 2, твоя оценка сериала 7Если ничего не укладывается — одна альтернатива, а не список: список из шести вариантов возвращает пользователя ровно в ту растерянность, из-за которой он и спросил.
Ресурсы (5)
Ресурс — данные, которые подаёт приложение, а не добывает модель. Критерий включения один: содержимое нужно в контексте до того, как модель начала рассуждать. Всё, что «может понадобиться, а может нет», — инструмент.
Общие решения:
text/plain, а не JSON. JSON тратит на скобки и повторяющиеся имена полей в полтора-два раза больше токенов при той же информации, а читает это только модель.Всё считается из локальной БД. Ответ за миллисекунды, работает даже когда TVmaze лежит.
Бюджет — 275 токенов на все пять при ориентире дизайна ~1100. Это цена, которую платишь в каждом запросе, где хост их подставил.
Шаблонных ресурсов (show://{slug}) в дизайне сознательно нет: данные по конкретному
сериалу нужны не всегда, а по запросу — это работа show_profile.
tracking://watching — что я смотрю сейчас
Профиль пользователя в этом домене. Любой вопрос про сериалы требует его; оформив это инструментом, вы обязали бы модель догадаться сходить за историей.
Смотрю сейчас (3):
Severance — 2x03, обновлено 2026-09-08, моя оценка 9
The Bear — 3x08, обновлено 2026-09-08, моя оценка 7
Slow Horses — 4x06, обновлено 2026-09-08, моя оценка 8
На паузе (1): Foundation (2x04)tracking://backlog — накопившиеся серии
Сердце проекта. Такого ответа нет ни в TVmaze, ни в локальной базе: он рождается на
их пересечении — позиция из трекинга минус вышедшие по airstamp серии, с отброшенными
спецвыпусками и суммированием длительности.
Накопилось (по свежести выхода):
Severance — 2 сер., 1 ч 40 мин, свежая вышла 2 дн. назад, 2x04, 2x05
The Bear — 2 сер., 1 ч, свежая вышла 4 нед. назад, 3x09, 3x10
Slow Horses — 0 серий, новых серий нет
Итого: 4 сер., 2 ч 40 мин. Спецвыпуски не учитываются.Строка «0 серий, новых серий нет» — тоже ответ: видно, ждать ли продолжения.
сериал закончился и долгов больше не будет;
серия вышла сегодня, но по UTC ещё не наступила — поэтому берётся
airstamp, а неairdate;runtime = null→ падаем наaverageRuntimeсериала, а при отсутствии обоих не выдумываем;дейли-шоу с нумерацией по годам (
season: 2026, number: 178);пропущенный сезон — это долг, а не повод считать сериал досмотренным;
спецвыпуски и
insignificantв долг не идут.
tracking://schedule — календарь моих сериалов
Единственный из пяти, который меняется сам по себе, без действий пользователя. Модель не может знать, что его стоит перепроверить, — значит подавать его должен хост.
Ближайшие 14 дней (сегодня 2026-09-08):
сб 12.09 Severance 2x06 «The Next One»
пн 14.09 Slow Horses 4x07 «Cold Water»tracking://taste — профиль вкуса
Основание любой рекомендации. Если добывать его инструментом, модель будет то запрашивать его, то нет, и качество советов станет случайным от разговора к разговору.
Профиль вкуса (по 6 сериалам, из них 6 с оценкой):
Люблю: Drama 7.6 (5)
Прохладно: Comedy 7 (3)
Досматриваю: 67% из закрытого.
Длина: предпочитаю 30–60 мин.
Площадки: Apple TV+ (2), Channel 4 (1), FX (1)
Языки: English (5), Korean (1)
Последние оценки: Severance 9, The Bear 7, Shogun 9, Slow Horses 8, I Need Romance 5При выборке меньше пяти оценок добавляется строка «выборка мала — считай эти цифры наброском». Без неё модель выдаёт статистику из четырёх сериалов за устойчивый вкус.
catalog://facets — допустимые значения фильтров
Значения для фильтров show_search:
genre: Drama, Comedy, Romance, Crime, Action, Adventure, Mystery, Anime, History, …
status: Ended | Running | To Be Determined | In Development
type: Scripted | Documentary | Reality | Animation | Variety | Talk Show | Game Show
language: English (44.9k), Russian (6.4k), Japanese (6.2k), … всего 30
Жанры чувствительны к написанию: "Science-Fiction", не "Sci-Fi" и не "sci fi".Последняя строка — не украшение, а профилактика самой частой ошибки. Без справочника модель угадывает написание, получает пустую выдачу и делает ложный вывод «в каталоге ничего нет».
Промпты (4)
Промпт задаёт рассуждению рамку целиком; инструмент решает подзадачу внутри него. Общее правило: промпты втягивают контекст из ресурсов, а не добывают его инструментами. Шаблон, начинающийся с «сначала вызови такой-то инструмент, чтобы узнать историю», означал бы, что примитивы разложены неверно.
Промпт | Аргументы | Втягивает | Инструментов | Отвечает |
|
| backlog, watching, taste | ≤ 1 | 2–3 варианта, по строке обоснования |
|
| backlog, schedule, watching | 0 | что вышло / что впереди / один совет |
|
| facets, taste | 1–2 | 3–5 кандидатов либо один уточняющий вопрос |
|
| watching, taste | ровно 1 | «продолжай» / «перетерпи до N» / «бросай» |
Два решения, которые стоит заметить. catch_up требует ровно один совет, а не
список: список из шести вариантов возвращает пользователя в ту же растерянность.
season_verdict прямо разрешает ответ «бросай» и запрещает подслащивать — доля
брошенного в профиле показывает, что пользователь и сам так делает.
Архитектура
Смысл разделения один: доменную логику можно проверить на выдуманных данных за миллисекунды, а транспорт поменять со stdio на HTTP, не тронув её ни на строку. Импорт разрешён только вниз; правило проверяется прогоном по AST.
7 server.py, cli.py точки входа
6 tools/, resources.py, слой MCP: регистрация примитивов, никакой логики
prompts.py
5 runtime.py как обработчики добираются до зависимостей
4 mapping.py, services.py строки БД → доменные структуры
3 storage/ SQLite: схема с FTS5, репозиторий, синхронизация
2 tvmaze/, index/ источник и полнотекстовый поиск
1 domain/ чистая логика: бэклог, вкус, вердикт, рендер
0 config, errors, log, основание
clockДоменный слой не знает ни про SQL, ни про сеть, ни про MCP, ни про системные часы: «сейчас» приходит аргументом — только поэтому случай «серия вышла сегодня, но по UTC ещё не наступила» вообще поддаётся проверке.
Подробнее — docs/ARCHITECTURE.md.
Данные
Таблица | Что хранит |
| корпус ~90k сериалов, FTS5 внешнего содержимого |
| лениво: только для отслеживаемых сериалов |
| позиция, состояние, оценка, заметка |
| метки последней синхронизации |
Корпус полный, эпизоды ленивые. 90k сериалов с описаниями — это один обход и ~77 МБ;
эпизоды для всех — миллионы строк. Классический just-in-time retrieval: серии тянутся
в момент tracking_update(action="track").
Политика бюджета контекста
Список эпизодов целиком не отдаётся никогда — только окно вокруг позиции.
image,_links,url,externalsотбрасываются при загрузке, а не при рендере.summaryчистится от HTML и режется до ~200 символов в concise-режиме.Любое усечение сопровождается счётчиком и конкретной подсказкой, чем сузить.
Целевой размер concise-ответа — до ~600 токенов.
Тестирование
uv run pytest -m unit -q # домейн, миллисекунды, без сети и без БД
uv run pytest -q --cov # весь набор с покрытием
uv run ruff check . && uv run mypy207 тестов, покрытие 91 % (domain/ — 95–98 % при пороге 90 %). Сети нет ни на одном
уровне: HTTP мокается через respx, включая
искусственный 429 для проверки backoff и потолка попыток.
Маркер | Что покрывает | Шт. |
| чистый домейн на фикстурах | 127 |
| SQLite в | 43 |
| примитивы MCP через in-memory клиент SDK | 24 |
| закреплённые сценарии evals и сам прогонщик | 13 |
Контрактные тесты подключают Client прямо к объекту сервера — без подпроцесса и порта
(документация SDK).
Оценка качества
uv run python -m evals.runner # 12 сценариев, отчёт в evals/reports/12 из 12 сценариев проходят, все пороги дизайна выполнены:
Порог | Значение | Факт |
Типовой сценарий | 1–2 вызова | медиана 1 |
Ответ concise | до ~600 токенов | максимум 351 |
Сериал с 450 сериями | до 2000 токенов | 195 |
Все пять ресурсов | ~1100 токенов | 275 |
Прогон измеряет цену намеченного плана вызовов, а не то, угадает ли модель этот план:
для второго нужен агент в петле. Разбор всех правок, сделанных по числам, — таблица
«было/стало» в docs/EVALS.md.
Отказы и ограничения
Ошибки чинят следующий вызов. Не «404», а что именно не так и что подставить:
По запросу «Zzqqwx» ничего не найдено.
Или опиши сюжет — я умею искать по описанию (by="description").
Ожидаю "2x03" или season=2, number=3. Получено "S02E03".
Отмечено: Arrested Development. Список серий подтянуть не удалось: источник временно
ограничил доступ. Сама подписка сохранена, повтори через ~10 секунд.Лимит источника. TVmaze разрешает ~20 запросов за 10 секунд на IP. Клиент разносит
запросы (1.8 rps), на 429 уходит в экспоненциальный backoff с джиттером и уважает
Retry-After; число попыток ограничено явно, бесконечного ретрая нет.
Непрямая инъекция промпта. Описания сериалов и серий на TVmaze пишут пользователи, и этот текст попадает в контекст модели. Меры: очистка HTML, жёсткое усечение, обрамление маркером источника. Полностью проблема не решается — это ограничение, которое надо знать. Не давайте серверу инструментов с побочными эффектами вне трекинга.
Прочее по безопасности. SQL только параметризованный; строка пользователя
экранируется перед попаданием в FTS5-запрос, так что операторы NEAR, *, OR не
выполняются; путь к БД берётся из конфига без интерполяции ввода.
Что не сделано
Честный список, а не умолчание:
Неделя реального использования — единственная проверка из дизайна, которую не заменяет ни один прогон: какие вопросы задаются на самом деле.
sync --updatesне гонялся против живого API — покрыт только моками. Полный обход при первом реальном запуске вскрыл коллизию slug, которую моки не ловили.Нет CI и pre-commit — контур гоняется вручную.
Python 3.12 не проверялся, хотя
requires-python = ">=3.11"его обещает.Опционально по дизайну: гибридный поиск (
fastembed+sqlite-vec, слияние с BM25 через RRF) и Streamable HTTP.
Документация
Файл | О чём |
что где лежит и зачем — разбор каждого файла и формата | |
дизайн примитивов и обоснование каждого решения | |
карта слоёв, правило зависимостей, что где тестируется | |
этапы, система логирования, регрессионный контур | |
замеры, таблица «было/стало», разбор правок |
Стек
Официальный Python SDK для MCP 2.x, httpx,
pydantic-settings. SQLite с FTS5 — из стандартной библиотеки, отдельной поисковой
системы не требуется. Разработка: pytest, respx, ruff, mypy --strict.
Атрибуция
Данные о сериалах предоставлены TVmaze и распространяются по лицензии CC BY-SA. Этот проект использует их на тех же условиях и ссылается на TVmaze как на источник. API: https://www.tvmaze.com/api.
Лицензия
MIT для кода — см. LICENSE. Данные — CC BY-SA (см. выше).
Available Tools
5 toolsepisode_searchНайти сериюARead-only
Найти серию по описанию среди отслеживаемых сериалов.
Описания серий, до которых ты ещё не дошёл, по умолчанию скрыты — показывается только факт, что такая серия есть.
Inputs: query (required), show, limit, season, +2 more. Returns: result
show_profileПрофиль сериалаARead-only
Профиль сериала: факты, рейтинги по сезонам и твоя позиция в нём.
Показывает, где сериал раскачивается и где проседает, — этого нет ни в одном
клиенте TVmaze, хотя оценка каждой серии в API лежит.
Inputs: show (required), response_format. Returns: result
show_searchНайти сериалARead-only
Найти сериал по названию, по описанию сюжета или отобрать по фильтрам.
Три режима в одном инструменте:
- название: `query="Severance"`;
- описание сюжета: `query="офис, где сотрудникам разделяют память"` — так TVmaze
искать не умеет вообще;
- только фильтры, **без query**: `genre="Comedy", status="Ended", min_rating=8`
для «комедии, которые уже закончились».
Точное написание значений фильтров — в ресурсе `catalog://facets`
(`"Science-Fiction"`, не `"Sci-Fi"`). Каждый результат помечен твоим состоянием
отслеживания.
Inputs: by, genre, limit, query, +6 more. Returns: result
tracking_updateОтметить просмотрAIdempotent
Изменить состояние просмотра: подписаться, отметить серию, оценить, бросить.
При `action="track"` эпизоды сериала загружаются и индексируются — после этого
по ним работает поиск и считается бэклог.
Inputs: show (required), action (required), note, rating, +1 more. Returns: result
watch_nextЧто включитьARead-only
Выбрать, что посмотреть прямо сейчас, из накопившегося.
Предлагает только вышедшие серии из бэклога и только те, что укладываются в заданное время.
Inputs: limit, minutes, include_new. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 5 tools
Each tool targets a distinct workflow stage: show discovery, show profile viewing, episode search within tracked shows, tracking state updates, and next-episode recommendation. The descriptions clearly separate show-level search from episode-level search, so there is little risk of selecting the wrong tool.
show_search and episode_search follow a consistent entity_search pattern, but show_profile uses entity_noun, tracking_update uses action-based naming, and watch_next is a verb phrase. All names are readable, but the set mixes naming conventions rather than following a uniform verb_noun or object_action pattern.
Five tools is well-scoped for a personal TV tracking server: discovery, detail, search, state mutation, and recommendation are each covered by one focused tool. No tool feels redundant or missing from the core set.
The main tracking workflow is mostly covered, but there is no explicit way to list all tracked shows, which is a notable gap for a tracking server. An agent would have to rely on broad searches or the watch_next recommendation to reconstruct the user's watchlist, creating potential dead ends.
Maintenance
Related MCP Connectors
MCP server for Russian books search, details, and recommendation candidates.
Personal knowledge base MCP server with semantic search, auto-categorization, metadata extraction
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- MIT
- AlicenseDqualityDmaintenanceAn MCP server that allows users to search for movies, get detailed information, receive genre-based recommendations, and discover popular/trending films using OMDb and TMDb APIs.515 npmMIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables users to search for movie and TV show resources across multiple sources and validate video link playability. It supports both STDIO and SSE transport modes for seamless integration with AI applications.46 npm5MIT
- FlicenseAqualityDmaintenanceAn MCP server that wraps the TMDB API, enabling search of movies and TV shows, retrieval of details, trending titles, recommendations, and streaming provider information.8-