tracking
MCP Tracking
Serveur MCP de suivi en temps reel avec dashboard terminal. Permet a Claude/Lyra de tracker n'importe quelle operation longue ET alimente automatiquement les sessions depuis le media-server (qBittorrent, Bazarr, conversion DV).
Sommaire
Related MCP server: Claude Session MCP
Architecture
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)Fichiers d'etat et configuration
Fichier | Emplacement | Surcharge |
|
|
|
|
|
|
|
|
|
| a cote du code, gitignore | -- |
Un ancien tracking_state.json a cote du code est migre automatiquement au premier
demarrage (copie, jamais supprime).
Variables d'environnement de retention :
Variable | Defaut | Role |
| 7 | Purge des sessions done / error / paused |
| 24 | Purge des sessions running orphelines (plus mises a jour) |
Flux de donnees complet
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)Le fichier d'etat est ecrit a chaque modification via ecriture atomique (os.replace) sous verrou
fichier (tracking_state.lock). Tous les processus (MCP, API, poller, dashboard) partagent cet
unique fichier ; chaque lecture verifie le mtime pour invalider son cache.
Toute mutation (HTTP ou MCP) passe par mutations.py, qui garantit le meme comportement sur les
deux chemins : started_at / finished_at poses sur les items et la session, historique de
progression (fenetre glissante de 40 points), niveaux de log info / warn / error,
auto-completion quand tous les items sont termines.
Metriques derivees
GET /sessions et tracking_get renvoient un bloc metrics calcule a la volee par metrics.py :
Champ | Sens |
| progression (plafonnee a 100) |
| vitesse sur les 120 dernieres secondes ( |
| temps restant estime (session running uniquement) |
| depuis |
|
|
Installation
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"Le MCP est enregistre dans Claude Code (scope user) :
claude mcp list # -> tracking: ConnectedPour reenregistrer :
claude mcp add tracking -s user -- \
/home/amineutron/dev/MCP/tracking/.venv/bin/python \
/home/amineutron/dev/MCP/tracking/server.pyServices systemd
Deux services tournent en permanence et se lancent au boot :
Service | Role | Port |
| API HTTP locale pour scripts externes | 127.0.0.1:8765 |
| Poll qBittorrent (10s) + Bazarr (60s) | -- |
Installation initiale et redeploiement
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 rapideLes instances MCP server.py deja ouvertes par des sessions Claude Code ne sont pas
redemarrees par deploy.sh : reconnecter tracking via /mcp dans ces sessions.
Commandes utiles
# 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/sessionsLancement
Dashboard (raccourci wofi)
Cherche "MCP Tracking" dans wofi/launcher. Lance le dashboard dans 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 errorsVia outil MCP (depuis 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 uniquementMode test (demo)
.venv/bin/python server.py --testSimule 4 sessions en parallele : download, machine (12 noeuds), free, movie (pipeline DV complet).
Dashboard
Layout d'une session
[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 --
-- --
-- --Icones items
Icone | Statut | Couleur |
| pending | gris |
| running | cyan |
| done | vert |
| error | rouge |
Couleurs de session
Couleur | Statut |
cyan | running |
vert | done |
rouge | error |
jaune | paused |
Raccourcis clavier
Touche | Action |
| Filtre suivant (cycle dynamique par template) |
| Basculer filtre erreurs uniquement |
| Refresh manuel |
| Stop propre d'une session (saisir l'ID) -> status paused |
| Kill force d'une session (saisir l'ID) -> suppression |
| Quitter |
Fleches / Molette | Scroll |
Modales stop/kill
Appuyer sur s ou k ouvre un modal avec un champ de saisie pour l'ID de session.
smarque la session enpausedet ajoute un logksupprime definitivement la session du dashboardEchapannule
Filtrage dynamique
Le cycle de filtres est construit automatiquement depuis les sessions presentes :
all -> download -> free -> movie -> lyra_task -> errors -> all -> ...alltoujours presentChaque template present dans le JSON s'ajoute automatiquement
errorsn'apparait que si au moins une session a une erreurFiltre actif affiche dans le sous-titre :
filtre: movie | 2/5 session(s)Si le template filtre disparait du JSON, retour automatique a
all
Integration media-server
qBittorrent (automatique)
Le poller interroge http://localhost:8080/api/v2/torrents/info toutes les 10 secondes.
Un torrent actif = une session
[DOWNLOAD]avec nom, taille, vitesse, ETALa session est supprimee automatiquement quand le torrent termine ou disparait
Credentials :
credentials/qbt-password.cred(chiffresystemd-creds --user, genere parmedia-server/scripts/secrets/rotate-secrets.sh)
Bazarr sous-titres manquants (automatique)
Le poller interroge l'API Bazarr toutes les 60 secondes.
Une session
[SUBTITLES]unique liste tous les episodes/films sans sous-titres FRLe titre de la session indique le total :
Sous-titres manquants (151)Les 50 premiers fichiers manquants sont listes comme items
API key Bazarr :
credentials/bazarr-api-key.cred(meme mecanisme). Sans credential, le poll concerne est simplement desactive.
Conversion Dolby Vision (automatique)
Declenche par dv-webhook.service quand Radarr/Sonarr importent un film DV Profile 4 ou 7.
Flux :
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 erreurLes 6 etapes trackees avec leurs metriques :
Etape | Outil | Metriques affichees |
1/6 extraction HEVC | ffmpeg | frame / speed / size / time |
2/6 demux BL/EL | dovi_tool | frames X/Y (%), bl: X GB, el: X GB |
3/6 extraction RPU + conv P8 | dovi_tool | frames X/Y (%), RPU: X KB |
4/6 injection RPU P8 dans BL | dovi_tool | frames X/Y (%), P8 HEVC: X GB |
5/6 reconstruction timestamps | ffmpeg | frame / fps / size |
6/6 remuxage MKV final | ffmpeg | frame / speed / size |
La barre de progression globale avance en continu pendant chaque etape (pas par sauts de 1/6 a la fin de chaque etape).
Mode manuel :
# 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/moviesEn mode manuel, la session tracking est creee automatiquement dans process_file.
API HTTP locale (port 8765)
Scripts externes peuvent creer/modifier des sessions directement :
# 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/sessionsCorps PUT complet (tous les champs optionnels) :
{
"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
}
}Outils 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 formatetracking_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
Ajoute un log sans modifier la progression.
Parametres:
session_id (str)
message (str)tracking_complete
Marque done a 100%.
Parametres:
session_id (str)
message (str, opt)tracking_error
Marque en erreur (prefixe "ERREUR:" auto, remonte dans colonne Erreurs).
Parametres:
session_id (str)
message (str)tracking_stop
Arrete proprement une session (status -> paused). Reste visible dans le dashboard.
Parametres:
session_id (str)
message (str, opt)tracking_kill
Supprime une session en force. Disparait immediatement du dashboard.
Parametres:
session_id (str)tracking_get
Retourne l'etat complet formate d'une session.
tracking_list
Parametres:
template (str, opt) Filtrer par template
status (str, opt) Filtrer par statut ("running", "done", "error", "paused")tracking_delete
Supprime une session (equivalent de tracking_kill).
tracking_templates
Affiche la liste des templates et leurs champs.
open_tracking_ui
Ouvre le dashboard dans un terminal Kitty.
Parametres:
filter_template (str, opt) Template a afficher au lancementTemplates
download
Telechargement de fichiers. Alimente automatiquement par qBittorrent via le poller.
Champs extra : speed, eta
Unite par defaut : MBmachine
Operations sur des machines (update, clone, snapshot, deploy). Utilise par Lyra pour les operations VM/cluster.
Champs extra : operation, target
Unite par defaut : machinesfree
Format libre. Utilise par le poller pour les sous-titres Bazarr manquants.
Aucun champ extra impose, aucune unite par defaut.lyra_task
Operations Lyra (VM clone, backup, update, snapshot).
Champs extra : operation, target, phase, eta
Unite par defaut : %movie
Pipeline complet d'un film : telechargement -> conversion Dolby Vision. Alimente automatiquement par dv_convert.py quand Radarr/Sonarr importent un fichier 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"Securite
api.pyecoute uniquement sur127.0.0.1:8765-- inaccessible depuis le reseaun8n restreint a
127.0.0.1:5678dansdocker-compose.ymldv_webhook_server.pyecoute sur0.0.0.0:8787(necessaire pour recevoir les webhooks Docker) -- proteger ce port avec un firewall si la machine est exposeeLes services systemd tournent avec
NoNewPrivileges=trueAucun secret en clair dans le code :
poller.pylit$CREDENTIALS_DIRECTORY(service user) ou dechiffrecredentials/*.credviasystemd-creds decrypt --user(service systeme), avec repli sur les variablesQBT_PASSWORD/BAZARR_KEYpour le debug
Ajouter un template
Ouvrir
templates.pyet ajouter une entree dansTEMPLATES:
"mon_template": {
"description": "Description courte",
"extra_fields": ["champ1", "champ2"],
"default_unit": " unites",
"example_extra": {"champ1": "valeur", "champ2": "valeur"},
},Optionnel : ajouter une simulation
_sim_mon_template()danssim.py.
Le template est immediatement disponible sans autre modification.
Sans toucher au code, un template peut aussi etre declare dans ~/.config/tracking/templates.json
(meme structure, cle = nom du template) ; il est charge au demarrage.
Tests
make test # unitaires (storage, metrics) + integration (API HTTP reelle sur port ephemere)La fixture autouse de conftest.py redirige la persistence vers un tmp_path : les tests ne
touchent jamais l'etat de production.
This server cannot be installed
Maintenance
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
- AlicenseBqualityCmaintenanceEnables Claude to coordinate multiple specialized AI agents by creating tasks, tracking their complete thought process and execution in real-time, and monitoring progress across parallel workflows with full transparency.18172MIT
- AlicenseAqualityDmaintenanceProvides 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.5MIT
- AlicenseNot gradedqualityDmaintenanceA 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.20MIT
- FlicenseNot gradedqualityDmaintenanceA 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.
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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