Skip to main content
Glama
marouabah

tracking

by marouabah

MCP Tracking

Servidor MCP de seguimiento en tiempo real con dashboard de terminal. Permite a Claude/Lyra rastrear cualquier operación larga Y alimenta automáticamente las sesiones desde el media-server (qBittorrent, Bazarr, conversión DV).


Sumario


Related MCP server: Claude Session MCP

Arquitectura

MCP/tracking/
  server.py              -- Serveur MCP (outils Claude/Lyra) + point d'entree --ui / --test
  api.py                 -- API HTTP locale (127.0.0.1:8765) pour les scripts externes
  mutations.py           -- Mutations d'une session, partagees par api.py ET server.py
                            (horodatage items, historique, niveaux de log, auto-completion)
  metrics.py             -- Metriques derivees (vitesse, ETA, ecoule, stale) -- logique pure,
                            calculees a la lecture, jamais stockees
  storage.py             -- Persistence JSON atomique + verrou fichier + cache mtime + purge TTL
  models.py              -- Modeles pydantic (TrackingSession, TrackingItem, LogEntry, ProgressPoint)
  templates.py           -- Templates builtin + templates utilisateur (JSON)
  ui.py                  -- Dashboard Textual (TUI temps reel) + modales stop/kill
  sim.py                 -- Simulations de demo (server.py --test)
  poller.py              -- Daemon polling qBittorrent (10s) + Bazarr (60s)
  tracking-api.service   -- Unite systemd (systeme) pour api.py
  tracking-poller.service -- Unite systemd (systeme) pour poller.py
  install.sh / deploy.sh -- Installation initiale / redeploiement des services
  Makefile               -- make test | smoke | deploy | ui
  tests/                 -- unitaires (storage, metrics) + integration/ (API HTTP reelle)

Archivos de estado y configuración

Archivo

Ubicación

Anulación

tracking_state.json

~/.local/state/tracking/

TRACKING_STATE_DIR

poller_state.json

~/.local/state/tracking/

TRACKING_STATE_DIR

templates.json (plantillas de usuario, opcional)

~/.config/tracking/

TRACKING_TEMPLATES_FILE

credentials/*.cred (qBittorrent, Bazarr)

junto al código, gitignore

--

Un tracking_state.json antiguo junto al código se migra automáticamente en el primer arranque (copia, nunca se elimina).

Variables de entorno de retención:

Variable

Valor predeterminado

Función

TRACKING_TTL_DAYS

7

Purga de sesiones done / error / paused

TRACKING_TTL_RUNNING_H

24

Purga de sesiones running huérfanas (sin actualizaciones posteriores)

Flujo de datos completo

Claude/Lyra (outils MCP)
      |
      v
  server.py ─────────────────────────────────────────┐
                                                      |
qBittorrent API (poll 10s)                            |
      |                                               |
Bazarr API (poll 60s)    ──> poller.py ──> api.py ──> mutations.py ──> storage.py ──> ~/.local/state/tracking/tracking_state.json
      |                                               |                        |
dv_webhook_server.py                                  |                        v
      |                                               |                     ui.py
      v                                               |               (rafraichit chaque seconde)
dv_convert.py ──────────────────────────────────────>
   (metriques temps reel ffmpeg/dovi_tool)

El archivo de estado se escribe en cada modificación mediante escritura atómica (os.replace) bajo un bloqueo de archivo (tracking_state.lock). Todos los procesos (MCP, API, poller, dashboard) comparten este único archivo; cada lectura verifica el mtime para invalidar su caché.

Toda mutación (HTTP o MCP) pasa por mutations.py, que garantiza el mismo comportamiento en ambas rutas: started_at / finished_at establecidos en los elementos y la sesión, historial de progreso (ventana deslizante de 40 puntos), niveles de log info / warn / error, autocompletado cuando todos los elementos están terminados.

Métricas derivadas

GET /sessions y tracking_get devuelven un bloque metrics calculado sobre la marcha por metrics.py:

Campo

Significado

percent

progreso (limitado a 100)

rate, rate_str

velocidad en los últimos 120 segundos (2.0 MB/s, 30.0 u/min)

eta_seconds, eta_str

tiempo restante estimado (solo sesión running)

elapsed_seconds, elapsed_str

desde created_at hasta finished_at o ahora

idle_seconds, stale

stale = running sin actualización desde hace 10 min (se muestra en el TUI)


Instalación

cd /home/amineutron/dev/MCP/tracking

# Creer le venv et installer les dependances
uv venv .venv
uv pip install "mcp[cli]>=1.0.0" "pydantic>=2.0" "textual>=0.80.0" "fastapi"

El MCP está registrado en Claude Code (ámbito de usuario):

claude mcp list        # -> tracking: Connected

Para volver a registrarlo:

claude mcp add tracking -s user -- \
  /home/amineutron/dev/MCP/tracking/.venv/bin/python \
  /home/amineutron/dev/MCP/tracking/server.py

Servicios systemd

Dos servicios systemd se ejecutan permanentemente y se inician al arranque:

Servicio

Rol

Puerto

tracking-api.service

API HTTP local para scripts externos

127.0.0.1:8765

tracking-poller.service

Sondeo de qBittorrent (10s) + Bazarr (60s)

--

Instalación inicial y redespliegue

cd /home/amineutron/dev/MCP/tracking
./install.sh        # premiere fois : venv + services (demande sudo)
sudo ./deploy.sh    # apres chaque mise a jour du code : stop, unites, restart, verif
make smoke          # sante rapide

Las instancias MCP server.py ya abiertas por las sesiones de Claude Code no se reinician con deploy.sh: vuelve a conectar tracking mediante /mcp en esas sesiones.

Comandos útiles

# Etat
systemctl status tracking-api.service tracking-poller.service

# Logs en direct
journalctl -fu tracking-poller.service
journalctl -fu tracking-api.service

# Redemarrage
sudo systemctl restart tracking-api.service tracking-poller.service

# Test API
curl http://127.0.0.1:8765/health
curl http://127.0.0.1:8765/sessions

Lanzamiento

Dashboard (acceso directo de wofi)

Busca "MCP Tracking" en wofi/launcher. Inicia el dashboard en Kitty.

Dashboard (terminal)

# Toutes les sessions
/home/amineutron/dev/MCP/tracking/.venv/bin/python \
  /home/amineutron/dev/MCP/tracking/server.py --ui

# Filtre direct au lancement
.venv/bin/python server.py --ui --filter download
.venv/bin/python server.py --ui --filter movie
.venv/bin/python server.py --ui --filter errors

Mediante la herramienta MCP (desde Claude/Lyra)

open_tracking_ui()                             # toutes les sessions
open_tracking_ui(filter_template="lyra_task")  # vue Lyra uniquement
open_tracking_ui(filter_template="errors")     # erreurs uniquement

Modo de prueba (demo)

.venv/bin/python server.py --test

Simula 4 sesiones en paralelo: download, machine (12 nodos), free, movie (pipeline DV completo).


Dashboard

Diseño de una sesión

[TEMPLATE]  Nom de la session  id:xxxxxxxx  (status)
  [=============>            ] 54.2%  27100 MB / 50000 MB
  champ_extra1: valeur  |  champ_extra2: valeur

  [ok]  item-1                          100.0 GB     -- termine
  [>]   item-2                          frame: 94231 / 172800  (54.5%)  speed: 3.2x
  [ ]   item-3                          --
  [!]   item-4                          erreur detail

  Logs                                  Erreurs
  14:32:01  Message log 1               [!] item-4
  14:32:04  Message log 2               14:32:08  ECHEC: details
  14:32:07  Message log 3               --
  --                                    --
  --                                    --

Iconos de elementos

Icono

Estado

Color

[ ]

pending

gris

[>]

running

cian

[ok]

done

verde

[!]

error

rojo

Colores de sesión

Color

Estado

cian

running

verde

done

rojo

error

amarillo

paused

Atajos de teclado

Tecla

Acción

f

Siguiente filtro (ciclo dinámico por plantilla)

e

Alternar filtro solo errores

r

Refresco manual

s

Detención limpia de una sesión (introducir el ID) -> estado paused

k

Kill forzado de una sesión (introducir el ID) -> eliminación

q

Salir

Flechas / Rueda

Desplazamiento

Modales de stop/kill

Pulsar s o k abre un modal con un campo de entrada para el ID de sesión.

  • s marca la sesión como paused y añade un log

  • k elimina definitivamente la sesión del dashboard

  • Echap cancela

Filtrado dinámico

El ciclo de filtros se construye automáticamente a partir de las sesiones presentes:

all -> download -> free -> movie -> lyra_task -> errors -> all -> ...
  • all siempre presente

  • Cada plantilla presente en el JSON se añade automáticamente

  • errors solo aparece si al menos una sesión tiene un error

  • Filtro activo mostrado en el subtítulo: filtre: movie | 2/5 session(s)

  • Si la plantilla filtrada desaparece del JSON, retorno automático a all


Integración media-server

qBittorrent (automático)

El poller consulta http://localhost:8080/api/v2/torrents/info cada 10 segundos.

  • Un torrent activo = una sesión [DOWNLOAD] con nombre, tamaño, velocidad, ETA

  • La sesión se elimina automáticamente cuando el torrent termina o desaparece

  • Credenciales: credentials/qbt-password.cred (cifradas con systemd-creds --user, generadas por media-server/scripts/secrets/rotate-secrets.sh)

Subtítulos faltantes de Bazarr (automático)

El poller consulta la API de Bazarr cada 60 segundos.

  • Una sesión [SUBTITLES] única lista todos los episodios/películas sin subtítulos FR

  • El título de la sesión indica el total: Sous-titres manquants (151)

  • Los 50 primeros archivos faltantes se listan como elementos

  • API key de Bazarr: credentials/bazarr-api-key.cred (mismo mecanismo). Sin credencial, el sondeo correspondiente simplemente se desactiva.

Conversión Dolby Vision (automática)

Desencadenado por dv-webhook.service cuando Radarr/Sonarr importan una película DV Profile 4 o 7.

Flujo:

Radarr/Sonarr import
      |
      v
dv_webhook_server.py (port 8787)
      |-- cree session tracking via api.py
      |-- passe DV_TRACKING_SESSION_ID en env
      v
dv_convert.py
      |-- 6 etapes avec metriques temps reel
      |-- ffmpeg   : frame / speed / size / time (parse stderr)
      |-- dovi_tool: frames X/Y ou X% (parse stderr indicatif)
      v
session tracking completee ou en erreur

Las 6 etapas rastreadas con sus métricas:

Etapa

Herramienta

Métricas mostradas

1/6 extracción HEVC

ffmpeg

frame / speed / size / time

2/6 demux BL/EL

dovi_tool

frames X/Y (%), bl: X GB, el: X GB

3/6 extracción RPU + conv P8

dovi_tool

frames X/Y (%), RPU: X KB

4/6 inyección RPU P8 en BL

dovi_tool

frames X/Y (%), P8 HEVC: X GB

5/6 reconstrucción de timestamps

ffmpeg

frame / fps / size

6/6 remuxado MKV final

ffmpeg

frame / speed / size

La barra de progreso global avanza de forma continua durante cada etapa (no a saltos de 1/6 al final de cada etapa).

Modo manual:

# Fichier unique
python /home/amineutron/dev/media-server/scripts/dv_convert.py /chemin/film.mkv

# Scan dossier
python /home/amineutron/dev/media-server/scripts/dv_convert.py --scan /mnt/media/media/movies

En modo manual, la sesión de tracking se crea automáticamente en process_file.

API HTTP local (puerto 8765)

Los scripts externos pueden crear/modificar sesiones directamente:

# Creer une session
curl -X POST http://127.0.0.1:8765/sessions \
  -H "Content-Type: application/json" \
  -d '{"name":"Mon operation","template":"free","total":100,"unit":"%"}'
# -> {"id": "a1b2c3d4"}

# Mettre a jour
curl -X PUT http://127.0.0.1:8765/sessions/a1b2c3d4 \
  -H "Content-Type: application/json" \
  -d '{"processed":45,"log":"Etape 2/5 en cours","extra":{"phase":"etape 2"}}'

# Mettre a jour un item
curl -X PUT http://127.0.0.1:8765/sessions/a1b2c3d4 \
  -H "Content-Type: application/json" \
  -d '{"item":{"name":"mon-item","status":"done","note":"100 frames  speed: 2x"}}'

# Supprimer
curl -X DELETE http://127.0.0.1:8765/sessions/a1b2c3d4

# Lister
curl http://127.0.0.1:8765/sessions

Cuerpo PUT completo (todos los campos opcionales):

{
  "processed": 45.0,
  "total":     100.0,
  "status":    "running",
  "extra":     {"phase": "etape 2"},
  "log":       "message de log",
  "item": {
    "name":      "nom-de-l-item",
    "status":    "running",
    "note":      "metriques ici",
    "processed": 50.0,
    "total":     100.0
  }
}

Herramientas MCP

tracking_create

Parametres:
  name      (str)          Nom de la session
  template  (str)          "download" | "machine" | "free" | "movie" | "lyra_task" |
                           "subtitles" | "series_episode" | "series_season" | template utilisateur
  total     (float)        Valeur totale
  unit      (str, opt)     Unite affichee (ex: " MB", " machines", "%")
  items     (list, opt)    Liste d'elements a suivre
  extra     (dict, opt)    Champs specifiques au template

Format items:
  [{"name": "fichier.iso", "total": 5100, "unit": " MB", "note": "info"}]

Retourne: ID de session + etat initial formate

tracking_update

Parametres:
  session_id    (str)          ID de la session
  processed     (float, opt)   Nouvelle valeur de progression
  message       (str, opt)     Message de log
  item_updates  (list, opt)    Mises a jour des items
  extra         (dict, opt)    Champs extra a merger

Format item_updates:
  [{"name": "item-1", "status": "done", "processed": 1200, "note": "detail"}]
  Status: "pending" | "running" | "done" | "error"

tracking_log

Añade un log sin modificar la progresión.

Parametres:
  session_id  (str)
  message     (str)

tracking_complete

Marca done al 100%.

Parametres:
  session_id  (str)
  message     (str, opt)

tracking_error

Marca en error (prefijo "ERREUR:" automático, aparece en la columna Errores).

Parametres:
  session_id  (str)
  message     (str)

tracking_stop

Detiene limpiamente una sesión (estado -> paused). Permanece visible en el dashboard.

Parametres:
  session_id  (str)
  message     (str, opt)

tracking_kill

Elimina una sesión por la fuerza. Desaparece inmediatamente del dashboard.

Parametres:
  session_id  (str)

tracking_get

Devuelve el estado completo formateado de una sesión.

tracking_list

Parametres:
  template  (str, opt)   Filtrer par template
  status    (str, opt)   Filtrer par statut ("running", "done", "error", "paused")

tracking_delete

Elimina una sesión (equivalente a tracking_kill).

tracking_templates

Muestra la lista de plantillas y sus campos.

open_tracking_ui

Abre el dashboard en un terminal Kitty.

Parametres:
  filter_template  (str, opt)   Template a afficher au lancement

Plantillas

download

Descarga de archivos. Alimentado automáticamente por qBittorrent a través del poller.

Champs extra : speed, eta
Unite par defaut : MB

machine

Operaciones en máquinas (update, clone, snapshot, deploy). Utilizado por Lyra para las operaciones VM/cluster.

Champs extra : operation, target
Unite par defaut : machines

free

Formato libre. Utilizado por el poller para los subtítulos faltantes de Bazarr.

Aucun champ extra impose, aucune unite par defaut.

lyra_task

Operaciones de Lyra (VM clone, backup, update, snapshot).

Champs extra : operation, target, phase, eta
Unite par defaut : %

movie

Pipeline completo de una película: descarga -> conversión Dolby Vision. Alimentado automáticamente por dv_convert.py cuando Radarr/Sonarr importan un archivo DV P4/P7.

Champs extra : phase, quality, codec, audio, source, dv, speed, eta
Unite par defaut : %

Les 6 etapes DV trackees avec metriques temps reel :
  "1/6 extraction HEVC"
  "2/6 demux BL/EL"
  "3/6 extraction RPU + conv P8"
  "4/6 injection RPU P8 dans BL"
  "5/6 reconstruction timestamps"
  "6/6 remuxage MKV final"

Seguridad

  • api.py escucha únicamente en 127.0.0.1:8765 -- inaccesible desde la red

  • n8n restringido a 127.0.0.1:5678 en docker-compose.yml

  • dv_webhook_server.py escucha en 0.0.0.0:8787 (necesario para recibir los webhooks de Docker) -- proteger este puerto con un firewall si la máquina está expuesta

  • Los servicios systemd se ejecutan con NoNewPrivileges=true

  • Ningún secreto en claro en el código: poller.py lee $CREDENTIALS_DIRECTORY (servicio de usuario) o descifra credentials/*.cred mediante systemd-creds decrypt --user (servicio de sistema), con respaldo a las variables QBT_PASSWORD / BAZARR_KEY para el debug


Añadir una plantilla

  1. Abrir templates.py y añadir una entrada en TEMPLATES:

"mon_template": {
    "description": "Description courte",
    "extra_fields": ["champ1", "champ2"],
    "default_unit": " unites",
    "example_extra": {"champ1": "valeur", "champ2": "valeur"},
},
  1. Opcional: añadir una simulación _sim_mon_template() en sim.py.

La plantilla está disponible inmediatamente sin ninguna otra modificación.

Sin tocar el código, una plantilla también puede declararse en ~/.config/tracking/templates.json (misma estructura, clave = nombre de la plantilla); se carga al inicio.


Pruebas

make test     # unitaires (storage, metrics) + integration (API HTTP reelle sur port ephemere)

La fixture autouse de conftest.py redirige la persistencia hacia un tmp_path: los tests nunca tocan el estado de producción.

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

  • A
    license
    A
    quality
    D
    maintenance
    Provides Claude Code with programmatic session awareness to track context usage, session history, and task progress. It enables intelligent context reset recommendations and automatic synchronization of project planning documentation.
    5
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A comprehensive project management and workflow tracking system that integrates with Claude Code via MCP, automatically capturing sessions, tools, agents, and project tasks into a centralized dashboard and database.
    20
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A comprehensive MCP server for monitoring Claude Code sessions, agent performance, cost tracking, project management, and GitHub synchronization with 89 tools and a real-time dashboard.

View all related MCP servers

Related MCP Connectors

  • Uptime, SSL, DNS and domain monitoring you can talk to from Claude or any MCP client.

  • Let your AI sessions talk to each other — messaging, tasks, sessions, and alerts

  • AI agent run monitoring with incident replay and SLA receipts.

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/marouabah/mcp-tracking'

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