tracking
Tracks qBittorrent torrent activity by polling its API every 10 seconds, turning active torrents into tracking sessions with name, size, speed, and ETA, and automatically removing sessions when torrents finish or disappear.
Click on "Install 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., "@trackingcreate a new session to track my qBittorrent downloads"
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.
MCP Tracking
Server MCP de suivi en temps réel 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).
Wait, I need to translate to English, not reproduce French. Let's do the actual final translation.
MCP Tracking
Real-time MCP tracking server with a terminal dashboard. Allows Claude/Lyra to track any long-running operation AND automatically feeds sessions from the media-server (qBittorrent, Bazarr, DV conversion).
Table of Contents
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)State and configuration files
File | Location | Override |
|
|
|
|
|
|
|
|
|
| next to the code, gitignored | -- |
An old tracking_state.json next to the code is automatically migrated at first
startup (copied, never deleted).
Retention envirnoment variables:
Variable | Default | Role |
| 7 | Purge sessions with status done / error / paused |
| 24 | Purge orphanned running sessions (no longer updated) |
Complete data flow
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)The state file is written on every change via atomic write (os.replace) under a file
lock (tracking_state.lock). All processes (MCP, API, poller, dashboard) share this
single file; every read checks the mtime to invalide its cache.
Every mutation (HTTP or MCP) goes through mutations.py, which guarantees the same behavior on
both paths: started_at / finished_at set on items and the session, progress
history (slding window of 40 points), info / warn / error log levels,
auto-completion when all items are finished.
Derived metrics
GET /sessions and tracking_get return a metrics block computed on the fly by metrics.py:
Field | Meaning |
| progress (capped at 100) |
| speed over the last 120 seconds ( |
| estimated time remaining (running session only) |
| from |
|
|
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"The MCP is registered in Claude Code (user scope):
claude mcp list # -> tracking: ConnectedTo re-register:
claude mcp add tracking -s user -- \
/home/amineutron/dev/MCP/tracking/.venv/bin/python \
/home/amineutron/dev/MCP/tracking/server.pysystemd Services
Two services run permanently and start at boot:
Service | Role | Port |
| Local HTTP API for external scripts | 127.0.0.1:8765 |
| Polls qBittorrent (10s) + Bazarr (60s) | -- |
Initial installation and redeployment
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 rapideMCP instances of server.py already open by Claude Code sessions are not
restarted by deploy.sh: reconnect tracking via /mcp in those sessions.
Useful commands
# 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/sessionsLaunch
Dashboard (wofi shortcut)
Search for "MCP Tracking" in wofi/launcher. Launch the dashboard in 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 MCP tool (from 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 uniquementTest mode (demo)
.venv/bin/python server.py --testSimulates 4 sessions in parallel: download, machine (12 nodes), free, movie (complete DV pipeline).
Dashboard
Session layout
[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 --
-- --
-- --Item icons
Icon | Status | Color |
| pending | gray |
| running | cyan |
| done | green |
| error | red |
Session colors
Color | Status |
cyan | running |
green | done |
red | error |
yellow | paused |
Keyboard shortcuts
Key | Action |
| Next filter (dynamic cycle by template) |
| Toggle errors-only filter |
| Manual refresh |
| Clean stop of a session (enter the ID) -> status paused |
| Force kill a session (enter the ID) -> deletion |
| Quit |
Arrows / Wheel | Scroll |
Stop/kill modals
Pressing s or k opens a modal with an input field for the session ID.
smarks the session aspausedand adds a logkpermanently deletes the session from the dashboardEsccancels
Dynamic filtering
The filter cycle is built automatically from the sessions present:
all -> download -> free -> movie -> lyra_task -> errors -> all -> ...allalways presentEach template present in the JSON is added automatically
errorsappears only if at least one session has an errorActive filter displayed in the subtitle:
filter: movie | 2/5 session(s)If the filtered template disappears from the JSON, automatic return to
all
media-server Integration
qBittorrent (automatic)
The poller queries http://localhost:8080/api/v2/torrents/info every 10 seconds.
An active torrent = a
[DOWNLOAD]session with name, size, speed, ETAThe session is automatically deleted when the torrent finishes or disappears
Credentials:
credentiales/qbt-password.cred(encrypted withsystemd-creds --user, generated bymedia-server/scripts/secrets/rotate-secrets.sh)
Bazarr missing subtitles (automatic)
The poller queries the Bazarr API every 60 seconds.
A single
[SUBTITLES]session lists all episodes/movies without French subtitlesThe session title shows the total:
Sous-titres manquants (151)The first 50 missing files are listed as items
Bazarr API key:
credentiales/bazarr-api-key.cred(same mechanism). Without a credential, that poll is simply disabled.
Dolby Vision conversion (automatic)
Triggered by dv-webhook.service when Radarr/Sonarr import a DV Profile 4 or 7 movie.
Flow:
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 erreurThe 6 tracked steps with their metrics:
Step | Tool | Metrics shown |
1/6 HEVC extraction | ffmpeg | frame / speed / size / time |
2/6 BL/EL demux | dovi_tool | frames X/Y (%), bl: X GB, el: X GB |
3/6 RPU extraction + P8 conversion | dovi_tool | frames X/Y (%), RPU: X KB |
4/6 RPU P8 injection into BL | dovi_tool | frames X/Y (%), P8 HEVC: X GB |
5/6 timestamp reconstruction | ffmpeg | frame / fps / size |
6/6 final MKV remux | ffmpeg | frame / speed / size |
The overall progress bar advances continuously during each step (not in jumps of 1/6 at the end of each step).
Manual mode:
# 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/moviesIn manual mode, the tracking session is automatically created in process_file.
Local HTTP API (port 8765)
External scripts can create/modify sessions directly:
# 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/sessionsComplete PUT body (all fields optional):
{
"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
}
}MCP Tools
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
Adds a log without modifying the progression.
Parametres:
session_id (str)
message (str)tracking_complete
Marks done at 100%.
Parametres:
session_id (str)
message (str, opt)tracking_error
Marks as error (auto "ERREUR:" prefix, surfaced in the Erreurs column).
Parametres:
session_id (str)
message (str)tracking_stop
Cleanly stops a session (status -> paused). Remains visible in the dashboard.
Parametres:
session_id (str)
message (str, opt)tracking_kill
Force-deletes a session. Disapears immediately from the dashboard.
Parametres:
session_id (str)tracking_get
Returns the complete formatted state of a session.
tracking_list
Parametres:
template (str, opt) Filtrer par template
status (str, opt) Filtrer par statut ("running", "done", "error", "paused")tracking_delete
Deletes a session (equivalent to tracking_kill).
tracking_templates
Displays the list of templates and their fields.
open_tracking_ui
Opens the dashboard in a Kitty terminal.
Parametres:
filter_template (str, opt) Template a afficher au lancementTemplates
download
File download. Automatically fed by qBittorrent via the poller.
Champs extra : speed, eta
Unite par defaut : MBmachine
Operations on machines (update, clone, snapshot, deploy). Used by Lyra for VM/cluster operations.
Champs extra : operation, target
Unite par defaut : machinesfree
Free format. Used by the poller for missing Bazarr subtitles.
Aucun champ extra impose, aucune unite par defaut.lyra_task
Lyra operations (VM clone, backup, update, snapshot).
Champs extra : operation, target, phase, eta
Unite par defaut : %movie
Complete pipeline for a movie: download -> Dolby Vision conversion. Automatically fed by dv_convert.py when Radarr/Sonarr import a DV P4/P7 file.
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"Security
api.pylistens only on127.0.0.1:8765-- inaccessible from the networkn8n restricted to
127.0.0.1:5678indocker-compose.ymldv_webhook_server.pylistens on0.0.0.0:8787(necessary to receive Docker webhooks) -- protect this port with a firewall if the machine is exposedsystemd services run with
NoNewPrivileges=trueNo plaintext secrets in the code:
poller.pyreads$CREDENTIALS_DIRECTORY(user service) or decryptscredentiales/*.credviasystemd-creds decrypt --user(system service), with fallback to theQBT_PASSORD/BAZARR_KEYvariables for debugging
Add a template
Open
templates.pyand add an entry toTEMPLATES:
"mon_template": {
"description": "Description courte",
"extra_fields": ["champ1", "champ2"],
"default_unit": " unites",
"example_extra": {"champ1": "valeur", "champ2": "valeur"},
},Optional: add a
_ sim_mon_template()simulation insim.py.
The template is immediately available without any other modification.
Without touching the code, a template can also be declared in ~/.config/tracking/templates.json
(same structure, key = template name); it is loaded at startup.
Tests
make test # unitaires (storage, metrics) + integration (API HTTP reelle sur port ephemere)The autouse fixture in conftest.py redirects persistence to a tmp_path: the tests never
touch the production state.
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