Files
nas-runbooks/common/nyora-notes-mcp-gateway-deploiement-20260826.md
T

4.9 KiB

Déploiement Passerelle MCP NyoraNotes (Multi-Agent, Séparation Stricte par Scope)

Date : 26 août 2026
Auteur : Gemini AntiGravity (sur brief Claude v2)
Tags : nyora-notes-mcp, mcp, streamable-http, scoping, dsh, tailscale, runbook
Statut : Validé et testé en direct de bout en bout sur NAS DS920+ et VPS Contabo


1. Contexte & Problématique

NyoraNotes est une application FastAPI purement REST, sans endpoint MCP natif (/mcp renvoyait 404). Les tentatives directes de connexion MCP depuis DSH étaient vouées à l'échec. De plus, la séparation d'accès entre agents nécessitait un contrôle strict par sous-dossier de vault (vault/dsh/), sans altérer le fonctionnement des 5 instances Hermes en production.


2. Architecture & Topologie

  • Service : nyora-notes-mcp (conteneur Python 3.11 / FastAPI / Starlette / MCP SDK 1.29.1).
  • Emplacement : /volume1/docker/nyora-notes-mcp sur le NAS DS920+.
  • Port : 3098 (mappé 0.0.0.0:3098 -> 8000/tcp).
  • Réseau : n8n (communique directement avec http://nyora-notes:8787 par nom de conteneur).
  • Transport MCP : streamable-http sur /mcp/ (compatible spec MCP 2025-03-26 et dsh-mcp-client).
  • Backend Auth : La passerelle utilise un credential backend unique (NYORA_BACKEND_TOKEN) pour relayer les requêtes vers NyoraNotes.
  • Scoping par agent : La couche applicative de la passerelle valide chaque requête MCP selon le token de l'agent appelant :
    • mcp-dsh-89f4b32a10e74c5d98bc7211e405a8f2agent_id: dsh, préfixe autorisé : dsh/.

3. Logique de Routage & Contrôle d'Accès

Double niveau de protection :

  1. Contrôle d'accès par file_path (Gatekeeper Passerelle) : Si le client fournit un argument file_path, la passerelle vérifie qu'il débute strictement par l'un des allowed_prefixes de l'agent (ex: dsh/). Tout chemin interdit (hermes-tt/..., infra/...) ou tentative de traversée (../...) est immédiatement rejeté avec 403 Forbidden sans être transmis au backend.
  2. Routage de stockage par injection automatique de tag (Backend NyoraNotes) : L'API REST NyoraNotes place les fichiers dans le dossier correspondant au premier tag de la note (tags[0]), ou dans inbox/ si aucun tag n'est fourni. Pour garantir que chaque note créée atterrisse physiquement dans le dossier de vault alloué, le handler notes_create de la passerelle injecte systématiquement le tag de scope (dsh) en tête de liste (tags), que le client ait fourni des tags ou non.

4. Outils MCP Exposés

Outil Description Contrôle de Sécurité / Scoping
notes_create Crée une note Markdown Contrôle de file_path + injection automatique du tag de scope en tête
notes_get Récupère une note par son UUID Vérifie que le file_path appartient au scope de l'agent (sinon 403)
notes_list Liste les notes paginées Filtre les résultats pour ne retourner que les notes du scope de l'agent
notes_search Recherche FTS plein texte Filtre les résultats pour exclure tout document hors scope de l'agent

5. Matrice de Validation & Preuves Brutes

Test Commande / Méthode Résultat constaté Statut
Healthcheck GET http://192.168.100.33:3098/health HTTP 200 OK, service nyora-notes-mcp Validé
MCP Initialize POST /mcp/ avec token DSH HTTP 200 OK, serverInfo: nyora-notes-mcp Validé
Création SANS TAG (Injection auto) notes_create sans tags HTTP 201 Created, note placée dans dsh/test-fix-injection-tag-dsh-automatique.md Validé
Test Scoping (Violation hermes-tt) notes_create sur hermes-tt/... 403 Forbidden ("hors du scope autorise") Validé
Test Scoping (Path traversal) notes_create sur ../hermes-tt/... 403 Forbidden ("hors du scope autorise") Validé
Auth Invalide POST /mcp/ avec token erroné HTTP 401 Unauthorized Validé
Exécution Native DSH dsh --profile headless (sans curl) Appel natif notes_create + notes_list + notes_get Validé
Preuve Physique NAS (disque direct) cat /volume1/docker/nyora-notes/vault/dsh/test-fix-injection-tag-dsh-automatique.md Présent sur disque NAS Synology (282 octets) Validé

6. Procédure pour Ajouter un Nouvel Agent

Pour ajouter un futur agent MCP sans toucher à NyoraNotes :

  1. Ouvrir /volume1/docker/nyora-notes-mcp/app/config.py.
  2. Ajouter une entrée dans AGENT_SCOPES :
    "mcp-nouvel-agent-secret-key": AgentScope(
        agent_id="nouvel-agent",
        allowed_prefixes=["nouvel-agent/"],
        description="Nouvel agent scopé à son dossier"
    )
    
  3. Redémarrer le conteneur : cd /volume1/docker/nyora-notes-mcp && docker compose restart nyora-notes-mcp.