Skip to content

MCP Server FR

Kheopsian edited this page Oct 12, 2026 · 2 revisions

🇬🇧 English · 🇫🇷 Français

Serveur MCP (clients IA)

S'applique à Hydranos 4.4.

Cette page est pour vous si vous voulez qu'un assistant IA, ou tout autre client MCP, consulte votre bibliothèque et agisse dessus via le Model Context Protocol. À la fin, vous saurez connecter un client, quels outils il obtient, lesquels peuvent supprimer des données et comment les déverrouiller, et ce que le serveur refuse. Vocabulaire : Concepts & glossaire.

De quoi il s'agit

Chaque instance Hydranos sert un serveur MCP sur la même écoute que l'interface web, port 8199, à POST /mcp. Il n'y a rien à installer ni à activer, et aucun écran ne lui est consacré dans l'interface web.

  • Transport : « streamable HTTP » sans état. Chaque POST /mcp transporte un message JSON-RPC 2.0 et reçoit une réponse JSON. Il n'y a ni session ni flux SSE : GET /mcp et DELETE /mcp répondent 405 avec Allow: POST.
  • Versions du protocole : 2025-06-18, 2025-03-26, 2024-11-05. Si le client demande une autre version, le serveur répond avec 2025-06-18.
  • Méthodes : initialize, ping, tools/list, tools/call. Le serveur propose uniquement des outils : ni ressources, ni prompts. serverInfo vaut {"name": "hydranos", "title": "Hydranos", "version": "4.x.y"} (la version en cours d'exécution). La réponse à initialize contient aussi de courtes instructions qui disent au modèle de commencer par overview, de paginer avec find_torrents et de désigner les torrents par leur info hash.
  • Pendant le démarrage d'Hydranos, /mcp répond 503 avec Retry-After: 5, comme toutes les routes de l'API, jusqu'à ce que le catalogue soit chargé (API REST, Pendant le démarrage d'Hydranos).
  • Les lots (un tableau JSON de messages) sont refusés. Un message sans id est une notification : 202 avec un corps vide.
  • Les écritures passent par l'API REST. Chaque outil d'écriture, sauf add_torrent, envoie sa requête à la vraie route /api à l'intérieur du processus, et subit donc les mêmes contrôles et refus que l'interface web. add_torrent appelle la même fonction d'ajout que les routes d'ajout, sans passer par une route. Aucune écriture ne prend de filtre : chaque écriture désigne ses torrents par info hash.
sequenceDiagram
    participant C as Client MCP
    participant M as Hydranos POST /mcp
    participant A as Routes /api dans le processus
    C->>M: initialize avec la clé en Authorization Bearer
    M-->>C: protocolVersion, capacité tools, serverInfo hydranos
    C->>M: notifications/initialized, sans id
    M-->>C: 202, sans corps
    C->>M: tools/list
    M-->>C: 19 outils, ou 21 avec allow_destructive
    C->>M: tools/call find_torrents
    M->>M: construit une page à partir de la liste du moteur
    M-->>C: résultat avec content text et structuredContent
    C->>M: tools/call pause avec info_hashes
    loop chaque moteur qui détient une partie des hashes
        M->>A: POST /api/engines/ENGINE/torrents/bulk
        A-->>M: statut et réponse
    end
    M-->>C: résultat, isError false, ok et statut par moteur
    Note over C,M: isError true quand l'outil lui-même échoue<br/>(arguments invalides, outil désactivé, torrent inconnu,<br/>ajout refusé, lecture en échec). Les échecs d'écriture<br/>par torrent restent isError false avec ok false
Loading

Connecter un client

Il vous faut deux choses : l'URL http://<host>:8199/mcp et la clé API de l'instance ([daemon] api_key, voir Sécurité & accès). Le serveur accepte la clé sous l'une de ces formes :

Comment Exemple
En-tête Authorization: Bearer (ce qu'envoient les clients MCP) Authorization: Bearer YOUR_API_KEY
En-tête X-Api-Key X-Api-Key: YOUR_API_KEY
Paramètre de requête apikey, pour les clients qui ne peuvent pas définir d'en-têtes http://192.0.2.10:8199/mcp?apikey=YOUR_API_KEY
Le cookie SID posé par la connexion au shim qBittorrent (POST /api/v2/auth/login) inutile pour un client MCP ; l'interface web elle-même n'utilise aucun cookie

Une clé absente ou erronée reçoit 401 avec WWW-Authenticate: Bearer et {"error": "Invalid or missing API key"}. Si api_key est vide, personne n'entre. La forme en paramètre de requête met la clé dans les URL, qui finissent dans les journaux du proxy : utilisez un en-tête quand votre client le permet.

Configuration générique d'un client (HTTP)

La plupart des clients MCP lisent un fichier JSON avec un objet mcpServers. Ajoutez Hydranos comme serveur HTTP :

{
  "mcpServers": {
    "hydranos": {
      "type": "http",
      "url": "http://192.0.2.10:8199/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Certains clients appellent ce type streamable-http ou streamableHttp au lieu de http ; Hydranos ne s'en soucie pas, il ne voit que les POST. Si votre client ne prend en charge que les serveurs locaux (stdio), intercalez un pont stdio vers HTTP et donnez-lui la même URL et le même en-tête.

Avec Claude Code, par exemple, la même chose tient en une commande :

claude mcp add --transport http hydranos http://192.0.2.10:8199/mcp \
  --header "Authorization: Bearer YOUR_API_KEY"

Tester avec curl

# Handshake
curl -s http://192.0.2.10:8199/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'

# List the tools
curl -s http://192.0.2.10:8199/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# Ten torrents of the hoard engine in error with their tracker
curl -s http://192.0.2.10:8199/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"find_torrents","arguments":{"engine":"hoard","error_class":"dead","limit":10}}}'

Comme le serveur est sans état, vous pouvez envoyer tools/call sans initialize préalable ; la poignée de main n'existe que pour les clients qui l'attendent.

Outils

19 outils sont listés par défaut. Chacun porte des annotations MCP (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) pour que le client puisse décider quand vous demander confirmation avant l'appel. Les arguments engine prennent un identifiant de moteur tel que overview le liste ; s'il est omis, les lectures utilisent hoard (ou le premier moteur s'il n'y a pas de hoard).

Outils de lecture

Outil Arguments Ce qu'il renvoie
overview aucun Chaque moteur de cette instance : identifiant, rôle, en écoute ou non, nombre de torrents, débits d'envoi/réception en direct, pairs actifs, comptes par état, erreurs de tracker, erreurs de torrent, classes d'erreur, torrents sans catégorie, et les 15 premières catégories, trackers et tags. Prend quelques secondes sur une très grosse bibliothèque.
find_torrents engine, search, category, tag, tracker, state, error_class, sort (par défaut added_time), order (asc/desc, par défaut desc), offset, limit (par défaut 25, max 200) Une page de torrents, filtres combinés en ET. Réponse : total, filtered, returned, rows, et next_offset tant qu'il reste des pages. search correspond à tous les mots du nom, ou à un préfixe d'info hash d'au moins 6 caractères hexadécimaux. Chaque ligne est un ensemble compact de champs (nom, info hash, état, progression, taille, catégorie, tags, hôte du tracker, ratio, envoi, débits, pairs, seeds, date d'ajout, chemin de sauvegarde, l'étiquette de ligne agent, indicateur d'arrêt par l'utilisateur, et l'erreur de tracker avec sa classe).
torrent_detail info_hash (obligatoire) La ligne complète d'un torrent, le moteur qui le détient et sa liste de trackers en direct.
torrent_files info_hash (obligatoire), limit (par défaut 100, max 1000) Nombre de fichiers, taille totale, et les fichiers avec leur taille.
tracker_errors engine, error_class, samples (par défaut 3, max 20) Les torrents en erreur de tracker regroupés par classe (dead = non enregistré, auth = passkey refusée, throttled, unreachable, other), chacune avec ses principaux trackers et des exemples de messages.
trackers problems_only, include_hidden (tous deux false par défaut), limit (par défaut 50, max 500) Chaque hôte de tracker : nombre de torrents, statut de la dernière annonce, dernière erreur, passkey et réglages d'annonce. Les plus gros d'abord.
categories aucun Chaque catégorie avec son chemin de sauvegarde et son mode.
health aucun Le rapport d'anomalies de /api/health/anomalies : torrents dont les données manquent, chemins de sauvegarde fantômes, seeds sans leurs pièces, téléchargements à l'arrêt faute de sources, re-téléchargements, hashes seedés deux fois, fichiers qu'un autre torrent détient avec d'autres octets (issus d'une passe de fond toutes les 5 minutes, generated_at en donne l'heure ; scan vaut pending jusqu'à la première), plus des comptes en direct des trackers en échec, des annonces en retard, des moteurs retenus et des disques à court d'espace, par moteur. Instantané. Voir Supervision & journaux.
drain history (par défaut 10 ; 50 au plus reviennent, la route ne garde que les 50 derniers passages) État du drain race par volume et les passages de drain les plus récents.
jobs state (par ex. running, done, failed), limit (par défaut 20 ; 100 au plus reviennent) Les jobs de fond, les plus récemment mis à jour d'abord, avec leur progression. Seuls les 100 jobs créés le plus récemment sont examinés, puis filtrés par state.
logs level (ERROR, WARN, INFO, DEBUG ; niveau minimal, par défaut WARN), contains (insensible à la casse, dans le message), module (partie du chemin de module, insensible à la casse, par ex. announce ou store), limit (par défaut 50, max 500) Les lignes correspondantes les plus récentes du tampon de journal en mémoire (les 2000 dernières lignes), les plus anciennes d'abord, avec matched et returned. Il couvre des minutes, pas des jours.

Outils d'écriture (réversibles, actifs par défaut)

Outil Arguments Ce qu'il fait Hashes max
pause info_hashes Arrête les torrents (les données et la ligne restent). 1000
resume info_hashes Démarre les torrents arrêtés. 1000
reannounce info_hashes Annonce maintenant au lieu d'attendre le prochain intervalle. 100
recheck info_hashes Vérifie le hash des données en arrière-plan. Un torrent arrêté reste arrêté. Protégé comme Vérifier à nouveau (Recheck) dans le menu contextuel : quand un autre torrent nomme les mêmes fichiers avec d'autres octets, le torrent est retenu pendant que ces fichiers sont vérifiés d'abord, et reste arrêté en erreur s'ils ne se vérifient pas (Ajouter des torrents & données existantes). 50
set_category info_hashes, category ("" la retire) Change seulement l'étiquette. Les fichiers restent en place et le torrent reste dans son moteur. 100
set_tags info_hashes, tags (tableau ; [] vide la liste) Remplace les tags par exactement cette liste. 100
move_to_category info_hashes, category, allow_breaking_hardlinks (false par défaut) Définit la catégorie et déplace les données vers son chemin de sauvegarde, sous forme de job (voir jobs) ; quand le mode de la catégorie diffère, le job est une graduation vers l'autre moteur. Refusé (409 dans le résultat par torrent, avec sa reason) si un fichier a un hardlink ailleurs et que allow_breaking_hardlinks vaut false, si l'espace libre manque, si un autre torrent lit les mêmes fichiers, ou si la destination contient déjà d'autres fichiers. Voir Jobs, actions groupées & déplacement. 100
add_torrent category (obligatoire), exactement un parmi torrent_path / torrent_url / magnet, plus save_path, tags (tableau), paused, engine Ajoute un torrent. torrent_path est un fichier .torrent sur la machine Hydranos ; torrent_url est récupéré en http(s) (délai 30 s, 15 MiB max) par la propre sortie réseau du démon, comme ses autres requêtes (VPN & sortie réseau) : quand le kill switch ne lui laisse aucune sortie, l'ajout échoue avec la raison. Un magnet répond {"info_hash": …, "status": "resolving"} et apparaît dès que ses métadonnées arrivent. save_path remplace le chemin de la catégorie et doit être l'endroit où se trouvent ou se trouveront les données. N'utilise jamais le mode seed : les données existantes sont vérifiées par hash. Pas de sous-dossier : [daemon] create_torrent_folder n'est pas appliqué. Le placement suit Catégories & routage ; les refus du chemin d'ajout (disque race plein, fichiers qu'un autre torrent détient avec path_collision = "refuse", déjà ajouté) reviennent comme erreur de l'outil. 1

Chaque liste info_hashes est vérifiée avant toute action : chaque entrée doit faire 40 caractères hexadécimaux, les doublons sont retirés, et une liste qui dépasse la limite est refusée en bloc. Les outils par torrent répondent {"ok": n, "failed": n, "results": [...]} avec un {info_hash, ok, status, answer} par torrent ; pause/resume répondent une entrée par moteur plus une liste not_found.

Outils destructifs (masqués par défaut)

Outil Arguments Ce qu'il fait Hashes max
delete_torrents info_hashes, delete_files (false par défaut), engine Supprime les torrents. Sans engine, toutes les copies de cette instance disparaissent ; avec delete_files, leurs données sont aussi effacées du disque, ce qui est irréversible. 100
purge_race info_hashes Supprime la copie du moteur nommé race, avec ses fichiers (les fichiers qu'une autre copie ou un autre torrent lit encore sont conservés) ; une copie dans un autre moteur reste. Un hash absent de race → statut 404 (torrent not in race) dans son résultat. Seulement le moteur nommé race : pour un moteur supplémentaire de rôle race, utilisez delete_torrents avec engine. 100

Outils destructifs

delete_torrents et purge_race ne sont ni listés ni appelables tant que vous ne les activez pas :

[mcp]
allow_destructive = true

La section [mcp] ne figure pas dans le default.toml livré, et l'onglet Config ne peut modifier que des clés qui existent déjà : ajoutez-la donc à la main dans le fichier de configuration (voir Config : démon, auth & global) et redémarrez Hydranos (voir Exploiter Hydranos pour un arrêt propre). Une fois la section présente, elle apparaît sous Other dans Paramètres avancés (default.toml) (Advanced settings (default.toml)) ; l'interrupteur est relu à chaque requête, donc une modification enregistrée là s'applique immédiatement à /mcp.

Interrupteur désactivé, un client qui appelle malgré tout l'un de ces outils (par exemple depuis une liste d'outils en cache) reçoit un résultat isError : `delete_torrents` is disabled on this node; set `allow_destructive = true` under `[mcp]` in the configuration to enable it. Les deux outils portent destructiveHint: true, donc un client bien élevé vous demande confirmation avant chaque appel.

Limites

  • Des pages, pas toute la bibliothèque. find_torrents renvoie au plus 200 lignes par appel ; suivez next_offset. Les autres plafonds figurent dans les tableaux d'outils ci-dessus.
  • La catégorie doit exister pour add_torrent, set_category (sauf si vide) et move_to_category. Un nom inconnu est refusé avec la liste des noms valides. C'est plus strict que l'API REST et le shim qBittorrent : leurs routes d'étiquetage enregistrent n'importe quel nom, et leurs routes d'ajout acceptent un nom inconnu tant qu'un chemin de sauvegarde est envoyé (le torrent atterrit alors dans race). Créez d'abord les catégories dans l'onglet Catégories (Categories).
  • Jamais de mode seed, jamais de sous-dossier. add_torrent vérifie toujours par hash les données déjà sur disque, pour un magnet aussi, et n'applique pas create_subfolder / [daemon] create_torrent_folder. Pour ajouter par-dessus des données complètes sans vérification, ou avec un dossier à lui, utilisez l'API REST ou le shim (voir Ajouter des torrents & données existantes).
  • engine n'est pas vérifié pour un magnet. Avec torrent_path ou torrent_url, un engine inconnu est refusé avec la liste des moteurs ; avec magnet, un engine inconnu est ignoré et la catégorie décide où va le torrent.
  • Ce que MCP ne couvre pas en 4.4. Il n'existe aucun outil pour les flux et règles RSS, l'ordre de téléchargement (priorités de fichiers, séquentiel), les limites de débit ou de partage, la file, les réglages réseau ni les nœuds. Utilisez pour cela l'interface web ou l[[API REST|REST-API-FR]] (RSS et téléchargements automatiques, File d'attente, limites de partage et de débit).
  • Les lectures montrent la même liste fusionnée que l'interface web ; les écritures n'agissent que sur cette instance. overview, find_torrents et tracker_errors incluent les lignes des autres moteurs locaux de même rôle et, si vous avez déclaré des nœuds, leurs lignes aussi (le champ agent, un nom historique, contient l'étiquette de ligne local-<engine> ou <node>-<engine>). torrent_detail et toutes les écritures ne regardent que les moteurs de cette instance : pour un hash détenu uniquement par un nœud, torrent_detail répond no torrent <hash> on this node, recheck, set_category, set_tags et move_to_category répondent no such torrent on this node (statut 404), reannounce et delete_torrents rapportent le 404 de la route elle-même, et pause/resume le listent dans not_found. Pour agir sur les torrents d'un nœud, faites pointer un client vers le /mcp de ce nœud. Voir Nœuds & plusieurs machines.
  • Copies dans plusieurs moteurs locaux. reannounce, recheck, set_category et move_to_category agissent sur la copie du premier moteur qui la détient. set_tags change les tags de chaque copie. pause/resume écrivent l'indicateur d'arrêt sur la ligne de chaque copie mais n'arrêtent ou ne démarrent que la copie du premier moteur ; les autres copies continuent de tourner (ou restent arrêtées) jusqu'au prochain redémarrage, puis suivent l'indicateur. delete_torrents sans engine atteint toutes les copies.
  • Pas de contrôle de l'Origin. L'endpoint ne repose que sur la clé API. Gardez le port 8199 sur votre LAN ou derrière un VPN ou un reverse proxy, comme pour le reste de l'API.

Erreurs

Il existe deux sortes d'échecs, et les clients les affichent différemment.

Les erreurs d'outil sont des résultats normaux marqués isError: true avec un message texte que le modèle peut lire et exploiter, par exemple unknown category `tv`; this node has: movies, tv-hd, unknown engine `vpn2`; this node runs: race, hoard, info_hashes is empty, ou give one of torrent_path, torrent_url or magnet. Un appel réussi renvoie isError: false avec le JSON à la fois dans content[0].text et dans structuredContent.

Les erreurs de protocole sont des erreurs JSON-RPC :

Situation Statut HTTP Code JSON-RPC
Le corps n'est pas du JSON 400 -32700 parse error
Lot (tableau JSON) 400 -32600 batching is not supported
Méthode inconnue 200 -32601 method not found
Nom d'outil inconnu 200 -32602 unknown tool
Notification (sans id) 202, corps vide aucun
GET ou DELETE sur /mcp 405, Allow: POST aucun
Clé API absente ou erronée 401, WWW-Authenticate: Bearer aucun ({"error": "Invalid or missing API key"})

Voir aussi

Hydranos 4.4 · 🇬🇧

Start

Install

Use

Integrate

Network & machines

Operate

Reference


Hydranos 4.4 · 🇫🇷

Démarrer

Installer

Utiliser

Intégrer

Réseau & machines

Exploiter

Référence


Clone this wiki locally