Skip to main content
Glama
Poulouloup

Hasan Orchestrator

by Poulouloup

Hasan Orchestrator

Orchestrateur MCP multi-devices en Python/FastAPI faisant le lien entre Hermes (assistant vocal local) et plusieurs appareils (mobile, desktop, laptop) via une API REST avec polling.

Hermes (localhost) → MCP localhost:8643
                          ↓
                    Orchestrateur FastAPI (localhost:8080)
                          ↓ HTTPS + Bearer token
              ┌───────────┼───────────┐
           "phone"     "desk"      "laptop"
         (polling)   (polling)   (polling)

Les devices initient toujours la connexion (register, heartbeat, long polling). L'orchestrateur ne contacte jamais directement un device.


1. Installation

cd ~/hasan-orchestrator
./install.sh

Le script :

  1. Crée un environnement virtuel Python (venv/)

  2. Installe les dépendances (requirements.txt)

  3. Crée ~/.hasan-orchestrator/ pour la base SQLite (registry.db)

  4. Génère ORCHESTRATOR_ADMIN_KEY dans .env si absent

  5. Installe et active le service systemd utilisateur hasan-orchestrator.service

Pour une installation manuelle :

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# éditer .env et définir ORCHESTRATOR_ADMIN_KEY (openssl rand -hex 32)
python main.py

L'API REST écoute par défaut sur http://127.0.0.1:8080.


Related MCP server: Brain Bridge

2. Configuration Hermes

Ajouter dans ~/.hermes/config.yaml :

Option A — MCP en stdio (recommandé)

mcp:
  servers:
    - name: hasan-orchestrator
      type: stdio
      command: /chemin/vers/hasan-orchestrator/venv/bin/python
      args: ["/chemin/vers/hasan-orchestrator/mcp_server.py"]
      description: "Contrôle multi-devices (phone, desk, laptop)"

Le serveur MCP en stdio doit être lancé alors que l'orchestrateur FastAPI tourne déjà (il s'appuie sur l'API interne /internal/* pour créer les commandes et lire les résultats).

Option B — MCP exposé via HTTP

mcp:
  servers:
    - name: hasan-orchestrator
      url: "http://localhost:8643/mcp"
      auth:
        type: bearer
        token: "${ORCHESTRATOR_ADMIN_KEY}"

3. Connecter un nouveau device

Chaque device (agent mobile/desktop/laptop) doit :

  1. Calculer un device_hash unique et immuable — un SHA256 généré une seule fois (par exemple à partir d'un identifiant matériel + sel aléatoire) et conservé localement.

  2. S'enregistrer :

curl -X POST http://localhost:8080/register \
  -H "Content-Type: application/json" \
  -d '{
    "device_name": "phone",
    "device_hash": "a3f2c8...",
    "device_type": "mobile_agent",
    "version": "1.0.0",
    "capabilities": {
      "send_sms":     {"enabled": true,  "auth_required": false},
      "make_call":    {"enabled": true,  "auth_required": true},
      "screenshot":   {"enabled": true,  "auth_required": false},
      "get_battery":  {"enabled": true,  "auth_required": false}
    }
  }'

Réponse :

{
  "status": "registered",
  "session_token": "tok_...",
  "heartbeat_interval": 30,
  "polling_interval": 30,
  "server_time": "..."
}
  1. Conserver session_token et l'utiliser dans le header Authorization: Bearer tok_... pour tous les appels suivants.

  2. Envoyer un heartbeat toutes les heartbeat_interval secondes :

curl -X POST http://localhost:8080/heartbeat \
  -H "Authorization: Bearer tok_..." \
  -H "Content-Type: application/json" \
  -d '{
    "device_hash": "a3f2c8...",
    "capabilities_version": "<hash renvoyé/calculé>",
    "network": {"ip": "192.168.1.42", "transport": "https", "nat": true, "carrier": "WiFi"}
  }'

Si capabilities_refresh_needed: true est retourné, refaire un /register complet (les capabilities ont été modifiées côté orchestrateur).

  1. Boucler sur GET /commands (long polling, jusqu'à 55s) pour recevoir les commandes à exécuter, puis poster le résultat sur /results.

Un device sans heartbeat depuis 2 × heartbeat_interval est marqué offline.


4. Tools MCP disponibles

L'orchestrateur n'a aucune connaissance hardcodée des capabilities. Les 3 tools ci-dessous sont les seuls exposés à Hermes :

Tool

Description

device_list()

Liste les devices online et leurs capabilities activées

device_info(device_name)

Détails complets d'un device (registry, capabilities, statut)

exec_action(action, params, device_name?)

Exécute n'importe quelle action sur un device

Principe : le device déclare ses propres capabilities à l'enregistrement. L'orchestrateur les stocke et les route dynamiquement via exec_action.

Si device_name n'est pas précisé, l'orchestrateur choisit automatiquement l'unique device online disposant de la capability demandée. S'il y en a plusieurs, il demande de préciser.

Exemples d'appels exec_action

  • exec_action("send_sms", {"numero": "0612345678", "message": "hello"}, "phone")

  • exec_action("record_audio", {"duration": 10}, "phone")

  • exec_action("open_file", {"path": "/home/user/doc.pdf"}, "desk")

  • exec_action("get_battery", {}, "phone")

  • exec_action("set_volume", {"level": 50}, "desk")


5. Exemples de commandes vocales pour Hermes

  • "Liste mes appareils"

  • "Prends un screenshot du desk"

  • "Envoie un SMS au 06 12 34 56 78 depuis le phone : je serai en retard"

  • "Quel est le niveau de batterie du phone ?"

  • "Lance Spotify sur le laptop"

  • "Mets le volume à 50 sur le desk"

  • "Ouvre le fichier rapport.pdf sur le laptop"

  • "Active la capability run_terminal sur desk"

  • "Désactive get_location sur phone"


6. Gestion des capabilities depuis l'orchestrateur (admin)

Modifier (merge) les capabilities d'un device :

curl -X PATCH http://localhost:8080/api/devices/phone/capabilities \
  -H "Authorization: Bearer ${ORCHESTRATOR_ADMIN_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"run_terminal": {"enabled": true, "auth_required": true}}'

Ajouter/modifier une seule capability :

curl -X POST http://localhost:8080/api/devices/desk/capabilities/run_terminal \
  -H "Authorization: Bearer ${ORCHESTRATOR_ADMIN_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true, "auth_required": true}'

Supprimer une capability :

curl -X DELETE http://localhost:8080/api/devices/phone/capabilities/get_location \
  -H "Authorization: Bearer ${ORCHESTRATOR_ADMIN_KEY}"

Au prochain heartbeat du device concerné, capabilities_refresh_needed: true sera retourné et le device devra refaire un /register complet.


7. Endpoints admin (Hermes)

Endpoint

Description

GET /api/devices

Liste tous les devices et leur statut

GET /api/devices/{device_name}

Détails d'un device

GET /api/commands/{command_id}

Statut d'une commande

PATCH /api/devices/{device_name}/capabilities

Merge de capabilities

POST /api/devices/{device_name}/capabilities/{capability_name}

Ajoute/modifie une capability

DELETE /api/devices/{device_name}/capabilities/{capability_name}

Supprime une capability

Tous nécessitent Authorization: Bearer ${ORCHESTRATOR_ADMIN_KEY}.


8. Ajouter un nouveau type d'appareil

  1. Choisir un device_type parmi mobile_agent, desktop_agent, laptop_agent (ou étendre l'enum DeviceType dans models.py pour un nouveau type, ex. tablet_agent).

  2. Implémenter côté agent : /register, /heartbeat, boucle GET /commands

    • POST /results (+ /confirm si des capabilities auth_required).

  3. Définir les capabilities pertinentes pour ce type d'appareil. Aucune modification de l'orchestrateur n'est nécessaire — les actions inconnues sont routées automatiquement via exec_action.

  4. Enregistrer le device : il apparaîtra automatiquement dans device_list() et sera routable par nom ou par capability.


9. Logs

journalctl --user -u hasan-orchestrator -f

Niveau de log configurable via LOG_LEVEL dans .env (DEBUG, INFO, ERROR).


10. Architecture des fichiers

hasan-orchestrator/
  main.py           # FastAPI : endpoints REST devices + admin
  registry.py       # Gestion SQLite des devices (registry persistant)
  command_queue.py  # File de commandes en mémoire avec TTL
  mcp_server.py     # Serveur MCP (stdio) exposé à Hermes
  auth.py           # Validation des Bearer tokens (admin + sessions device)
  models.py         # Schémas Pydantic
  config.py         # Configuration (.env)
  install.sh        # Installation + service systemd
  requirements.txt
  .env.example

Related MCP Connectors

Related MCP Servers