Les panneaux ui:// livrés par #33 et #34 ne s'affichent que dans un client externe qui a négocié l'extension. Le dashboard intégré, sur /app/chat, montre le JSON de l'outil à la place.
Les deux moitiés
Le dashboard est à la fois client MCP et hôte, donc il faut les deux.
Client (src/beaconmcp/dashboard/chat.py) : annoncer io.modelcontextprotocol/ui avec text/html;profile=mcp-app dans les capacités passées à l'initialize de la ClientSession, puis lire la ressource via resources/read quand un résultat d'outil porte _meta.ui.resourceUri.
Hôte (src/beaconmcp/dashboard/static/chat.js) : rendre le document dans une iframe sandboxée et implémenter le côté hôte du protocole postMessage — répondre à ui/initialize, pousser ui/notifications/tool-result, relayer les tools/call vers la session, et router ui/update-model-context et ui/message vers la boucle Gemini.
Le SDK expose un module AppBridge qui fait ce travail côté hôte, mais il est en TypeScript et le dashboard sert du JS sans étape de build. À évaluer : le porter, l'inliner, ou implémenter le protocole à la main comme on l'a fait côté app.
Prérequis
Bloqué par la migration mcp 2.0. Le champ extensions de ClientCapabilities, par lequel un client se déclare compatible, n'existe pas en 1.x :
mcp 1.29 ClientCapabilities : elicitation, experimental, roots, sampling, tasks
extensions présent ? False
Il apparaît dans mcp_types 2.0.0, attaché à la révision de spec 2026-07-28. Côté serveur la migration n'était pas nécessaire, les panneaux tournent en 1.x parce que le format de fil suffit. Côté client elle l'est.
À trancher au passage
La garde _NEEDS_CONFIRMATION de #24 s'applique aux appels décidés par le modèle. Un tools/call émis depuis une iframe vient d'un clic humain, donc la modale est probablement redondante — mais c'est une décision explicite à prendre, et elle touche directement le travail de sécurité de #24.
Les panneaux
ui://livrés par #33 et #34 ne s'affichent que dans un client externe qui a négocié l'extension. Le dashboard intégré, sur/app/chat, montre le JSON de l'outil à la place.Les deux moitiés
Le dashboard est à la fois client MCP et hôte, donc il faut les deux.
Client (
src/beaconmcp/dashboard/chat.py) : annoncerio.modelcontextprotocol/uiavectext/html;profile=mcp-appdans les capacités passées à l'initializede laClientSession, puis lire la ressource viaresources/readquand un résultat d'outil porte_meta.ui.resourceUri.Hôte (
src/beaconmcp/dashboard/static/chat.js) : rendre le document dans une iframe sandboxée et implémenter le côté hôte du protocole postMessage — répondre àui/initialize, pousserui/notifications/tool-result, relayer lestools/callvers la session, et routerui/update-model-contextetui/messagevers la boucle Gemini.Le SDK expose un module
AppBridgequi fait ce travail côté hôte, mais il est en TypeScript et le dashboard sert du JS sans étape de build. À évaluer : le porter, l'inliner, ou implémenter le protocole à la main comme on l'a fait côté app.Prérequis
Bloqué par la migration mcp 2.0. Le champ
extensionsdeClientCapabilities, par lequel un client se déclare compatible, n'existe pas en 1.x :Il apparaît dans
mcp_types2.0.0, attaché à la révision de spec 2026-07-28. Côté serveur la migration n'était pas nécessaire, les panneaux tournent en 1.x parce que le format de fil suffit. Côté client elle l'est.À trancher au passage
La garde
_NEEDS_CONFIRMATIONde #24 s'applique aux appels décidés par le modèle. Untools/callémis depuis une iframe vient d'un clic humain, donc la modale est probablement redondante — mais c'est une décision explicite à prendre, et elle touche directement le travail de sécurité de #24.