NeuraApps - Widgets UI Interactifs
NeuraApps - Widgets UI Interactifs
NeuraApps rend des widgets interactifs directement dans la conversation NeuraChat (carte client, formulaire, graphique, visualiseur…) au lieu d'une réponse en Markdown. Le module suit la spécification officielle Anthropic MCP ext-apps v1.7.1.
Contrairement à un dock, l'utilisateur n'active rien manuellement : c'est l'orchestration (canvas NeuraHub) qui décide d'afficher un widget selon l'intention détectée, dans les limites d'une liste blanche définie par l'admin.
1. Concept : Blueprint / Skill / App
NEURASCOPE distingue ce que fait l'IA (action) de comment le résultat s'affiche (présentation) :
| Primitive | Rôle | Activation |
|---|---|---|
| NeuraMCP Blueprint | Action : appelle une source de données (Odoo, HubSpot, API…) | Autonome (le LLM appelle l'outil) |
| NeuraSkill | Runtime contrôlé (prompt/tools/actions) | Dock utilisateur (1 skill actif) |
| NeuraApps | Présentation : rend un widget UI à partir du résultat | Orchestration + liste blanche admin (pas de dock) |
✅ Un App ne remplace pas un Blueprint : le Blueprint fournit les données, l'App fournit l'affichage. Un App ne détient jamais de credentials.
graph LR
Q[Question user] --> Orch[Orchestration NeuraHub]
Orch --> BP[Blueprint MCP<br/>données]
BP --> Node[NeuraAppsNode<br/>liste blanche]
Node -->|App autorisé| Widget[Widget dans NeuraChat]
Node -->|sinon| MD[Réponse Markdown]
style Widget fill:#8b5cf6,stroke:#7c3aed,color:#fff
2. Tutoriel : câbler un NeuraAppsNode dans le canvas NeuraHub
Un widget ne s'affiche que si un NeuraAppsNode est câblé dans le canvas du projet.
- Ouvrez le canvas d'orchestration : NeuraHub → Orchestration.
- Ajoutez un nœud NeuraAppsNode en aval du NeuraChatNode (branche
handle_output). - Ouvrez le panneau de configuration du nœud (NeuraAppsConfigPanel).
- Cochez la liste blanche des Apps autorisés pour ce projet (
enabled_apps). - Enregistrez le canvas.
⚠️ Sans NeuraAppsNode câblé, aucun widget ne s'affiche — le pipeline retombe sur la réponse Markdown classique.
(Capture : canvas NeuraHub avec un NeuraAppsNode branché sur le NeuraChatNode — voir /docs.)
3. Tutoriel : forker un App depuis le marketplace
Le marketplace NeuraApps est distinct de ceux de NeuraMCP (Blueprints) et NeuraSkill.
- NeuraApps → Marketplace.
- Repérez le widget voulu (catégories : cartes métier, formulaires, visualisation, éditeurs, spécialisés, exemples Anthropic officiels).
- Cliquez Forker : une copie privée au tenant est créée.
- Le fork ne copie jamais de credentials — uniquement le bundle, le CSP et les schémas d'entrée/sortie.
- Ajoutez l'App forké à la liste blanche d'un NeuraAppsNode (voir §2) pour le rendre actif.
4. Tutoriel : créer un App custom (bundle + ui_resource_uri)
- NeuraApps → Créer.
- Renseignez : nom,
ui_resource_uri(ex.ui://mon-widget), et le bundle :- bundle interne servi depuis
public/widgets/{slug}/index.html(recommandé), OU source = externalavecexternal_registry_url(soumis à la whitelist de domaines, voir §5).
- bundle interne servi depuis
- Déclarez les contrats :
input_schema,output_schema,events_schema(typage fort des événements postMessage). - Définissez le CSP propre (
bundle_csp) : il est fusionné avec le CSP par défaut au moment du serve. - Respectez les règles de conception :
- bundle < 50 Ko gzippé recommandé ;
- modes clair et sombre obligatoires ;
- aucun credential dans le bundle.
Le widget s'exécute dans une iframe sandbox (allow-scripts allow-forms, jamais allow-same-origin) et dialogue avec NeuraChat via postMessage (SDK transport.js : onData / sendEvent / notifyResize / ready).
5. Sécurité : CSP, signature JWT, isolation tenant
La sécurité NeuraApps repose sur plusieurs couches vérifiées à chaque rendu :
URL de bundle signée (JWT dédié)
- Chaque URL de bundle est signée avec un secret dédié (
APP_NEURAAPPS_SIGNING_SECRET, distinct du JWT d'authentification général). - TTL court (5 min) ; claims
tenant_id+app_id+conversation_id. - Au serve, le token est revalidé et l'App rechargée avec
accessibleBy(tenant): toute tentative cross-tenant renvoie 404 (jamais 403, pour ne pas révéler l'existence).
CSP par App
- Le CSP propre à l'App (
bundle_csp) est appliqué dans les en-têtes de la réponse qui sert le bundle, avecX-Frame-Options,X-Content-Type-Options: nosniffetReferrer-Policy.
Isolation & anti-SSRF
- Les bundles
source = externalne sont récupérés que si le domaine est whitelisté pour le tenant (TenantAllowedDomain) ou globalement — contrôle anti-SSRF (IP privées et services de métadonnées cloud bloqués).
Rate limit & audit
- Le serve des bundles est limité à 100 requêtes/min par tenant.
- Chaque rendu (
rendered_at), première interaction (interacted_at) et événements reçus (events_received) sont journalisés dansneura_apps_usageset consultables dans/admin/security(bloc « Audit Widgets NeuraApps »). Rétention des événements : 90 jours.
Références
- Spécification officielle : @modelcontextprotocol/ext-apps v1.7.1 (Apache 2.0, Anthropic).
- Config :
config/neuraapps.php. - Tables :
neura_apps,neura_apps_categories,neura_apps_node_config,neura_apps_usages.