Accueil / Articles / Arrêter de renvoyer du JSON : Envoyer une interface utilisateur interactive avec des applications MCP

Arrêter de renvoyer du JSON : Envoyer une interface utilisateur interactive avec des applications MCP

Les applications MCP permettent aux serveurs de fournir des interfaces utilisateur en environnement isolé accompagnées d’outils, afin que les utilisateurs puissent approuver, configurer et gérer ces éléments sans quitter la conversation avec l’agent.

2858 mots

Pendant la majeure partie de ses débuts, le cycle d’interaction de MCP est resté limité : les agents invoquent des outils, ces derniers s’exécutent, les serveurs répondent par du texte ou des données structurées, et les modèles reformulent le résultat pour les utilisateurs.

De nombreuses questions restent dans ce cadre. Compter les déploiements réussis ne nécessite pas de complexité supplémentaire : il suffit d’appeler get_deployments(), de lire un objet compact comme {"total": 12, "healthy": 10, "degraded": 2}, et de répondre en une seule ligne.

La situation change lorsque les utilisateurs souhaitent interagir avec le résultat. Les tableaux de bord, les processus d’approbation, les tables filtrables, les formulaires de configuration, les graphiques, les panneaux de déploiement, les workflows en plusieurs étapes ainsi que les mécanismes impliquant un intervenant humain exigent tous plus qu’un simple envoi de JSON. Pendant longtemps, MCP n’a offert aucun standard inter-hôte pour cela. Aujourd’hui, il en existe un sous le nom de MCP Apps, qui élargit ce qu’un serveur MCP peut représenter.

Les serveurs MCP étaient principalement des interfaces machines

Le premier modèle mental était orienté agents. Les serveurs exposent des outils tels que search_projects(), create_ticket(), restart_service() et get_customer(). Les modèles les découvrent, les appellent, reçoivent des données, et les humains voient ce que le modèle choisit de montrer. Cela est puissant car les opérations se font via un seul protocole plutôt qu’une intégration personnalisée pour chaque agent. La limite est que ces fonctionnalités ont été conçues pour des machines, ce qui place l’humain à un écart par rapport au résultat brut.

Cela convient tant que l’interaction est intrinsèquement visuelle. « Montrez-moi tous les services en production » peut retourner un bloc JSON contenant des informations sur les statuts, la CPU et la mémoire, mais un tableau de bord compact avec des barres de progression, des badges ainsi que des commandes pour les journaux, la redémarrage et l’échelle est bien plus utile. MCP Apps vise à combler cette lacune.

Qu’est-ce que sont exactement les MCP Apps ?

MCP Apps étend le Model Context Protocol afin que les serveurs puissent fournir des interfaces utilisateur interactives en complément de leurs outils — pas des captures d’écran, ni du Markdown présenté comme interface utilisateur, mais de véritables applications HTML/JavaScript affichées à l’intérieur d’un hôte MCP. La documentation décrit les outils qui annoncent des ressources ui://, les hôtes qui affichent ces ressources à l’intérieur d’iframes isolés, ainsi que le fait que le même hôte injecte les contenus des outils dans l’affichage tout en permettant à cet affichage d’appeler à nouveau les outils uniquement via cet hôte.

MCP App = MCP Tool + UI Resource + Host/View protocol

Un outil continue d’appeler des API, de consulter des bases de données, d’exécuter de la logique métier et de retourner des données structurées. Il peut en outre disposer d’une interface utilisateur pour présenter ces résultats. Cette interface est une ressource MCP telle que ui://services/dashboard et peut contenir un frontend complet — HTML, CSS, JavaScript, React, graphiques, formulaires, boutons. Ainsi, une seule opération offre à la fois des capacités destinées aux machines et une interface pour les utilisateurs, standardisée entre tous les hôtes.

D’où viennent les applications MCP ?

Cette extension est nouvelle. Les développeurs qui ont mis en place des serveurs MCP jusqu’en 2025 n’ont pas manqué de fonctionnalité secrète ; la norme officielle n’existait pas encore à l’époque.

Fin novembre 2025 a vu l’apparition de SEP-1865, la proposition d’Apps élaborée en collaboration avec les contributeurs et mainteneurs de MCP-UI provenant des principaux laboratoires de modèles. Des expériences parallèles (MCP-UI, Apps SDK) existaient déjà ; ce qui manquait était un moyen interopérable permettant à un serveur de fournir des outils, des données et une interface utilisateur que tout hôte compatible pouvait afficher. L’article du blog MCP de novembre 2025 consacré à la proposition d’Apps relate l’annonce de SEP-1865.

Au cours de la fin janvier 2026, le même groupe a qualifié Apps de première extension officielle prête pour la production, dotée d’une spécification plus précise, d’un SDK ainsi que d’hôtes de déploiement. ChatGPT, Claude, Goose et Visual Studio Code ont été mentionnés comme premiers clients. L’article du blog MCP de janvier 2026 déclare Apps être la première extension officielle.

La version candidate de juillet 2026 a amélioré les extensions de manière générale : identifiants stables, négociation des fonctionnalités, dépôts séparés, versionnement indépendant, ainsi qu’une piste « Extensions » qui liste les applications. Elle a également souligné que les appels déclenchés par des boutons passent toujours par le chemin JSON-RPC de l’hôte, ce qui maintient Agent → Outil et Humain → Bouton → Outil sous un même plan de contrôle. L’article sur la version candidate de juillet 2026 publié sur le blog MCP traite de cette piste « Extensions ».

En septembre 2026, un article d’AWS Bedrock AgentCore a présenté un modèle d’hébergement concret sans limiter les applications à AWS uniquement : hôte → passerelle → environnement de exécution → serveur MCP (outils + ressources UI) → Lambda/DynamoDB. La démonstration utilisait ChatGPT et indiquait que Claude ainsi que d’autres hôtes d’applications fonctionnaient de la même manière. Consultez l’article du blog AWS Machine Learning sur les applications MCP interactives avec Bedrock AgentCore pour suivre ce processus pas à pas.

Qui prend réellement en charge les applications MCP ?

Soutenir MCP ne revient pas au même que soutenir les applications MCP. Un client peut gérer des outils et des ressources ordinaires sans avoir à implémenter l’extension Apps. L’annonce de janvier 2026 a mentionné ChatGPT, Claude, Goose et VS Code ; les documents actuels décrivent le rendu en ligne dans Claude, ChatGPT et d’autres clients conformes, tout en indiquant que le support par l’hôte varie. Concevez en fonction de cette réalité : ne supposez pas que tous les clients comprennent les applications Apps. L’équation utile est Le serveur prend en charge les applications MCP + L’hôte prend en charge les applications MCP = Interface utilisateur interactive ; un serveur prudent doit recourir à du texte ou à du contenu structuré lorsque l’hôte ne peut pas afficher l’application.

La seule question qui compte vraiment

Si la ressource d’interface utilisateur est du HTML statique, comment les données de l’outil parviennent-elles jusqu’à elle ? La consommation en CPU peut être de 21 % maintenant et de 87 % dix secondes plus tard ; régénérer tout l’interface utilisateur à chaque appel de l’outil serait absurde. La solution réside dans la séparation : l’interface utilisateur et les données sont des éléments distincts. Considérez l’outil comme le producteur de données, la ressource comme l’enveloppe de présentation, et l’hôte comme le lien entre les deux. L’outil renvoie des données dynamiques ; la ressource renvoie une application capable de rendre cette forme ; l’hôte les relie en temps de exécution.

Comment fonctionnent réellement les applications MCP

Prenons l’exemple de get_servers(), qui renvoie des objets serveur contenant l’id, le nom, l’état, la consommation en CPU et en mémoire, dont les métadonnées pointent vers ui://servers/dashboard. Le cycle de vie est le suivant :

Le modèle appelle get_servers(). Le serveur exécute sa logique — base de données, API cloud, Kubernetes, service interne — et renvoie des données structurées. L’hôte perçoit les métadonnées UI pour ui://servers/dashboard et envoie une requête resources/read. Le serveur renvoie le bundle frontend (React, Vue ou JavaScript pur). Les lignes de serveur actuelles ne sont pas intégrées dans cet HTML ; l’interface utilisateur ne connaît que le contrat attendu (servers[].id, servers[].status, etc.).

L’hôte affiche l’application dans un iframe isolé afin que le code UI d’un serveur MCP ne puisse pas accéder librement au DOM, à la session ou aux identifiants de l’hôte. Ensuite, l’hôte transmet le résultat de l’outil dans la vue en cours d’exécution, généralement via JSON-RPC au moyen de postMessage entre l’hôte et la vue isolée.

L’interface utilisateur reçoit les données comme le ferait n’importe quelle application single-page et les affiche en conséquence. Un serveur génère une carte ; cinquante serveurs génèrent cinquante cartes. L’application reste inchangée ; seules les données changent.

Par rapport à une application web classique — où React appelle GET /api/servers — les MCP Apps font en sorte que l’agent déclenche tools/call, que l’outil renvoie du JSON, et que l’hôte injecte ce JSON dans une application React située à l’intérieur d’un iframe. L’interface utilisateur n’a pas toujours besoin de récupérer les données elle-même ; l’hôte peut lui transmettre directement les résultats.

Mais les MCP Apps ne se limitent pas à des résultats d’outils plus esthétiques

Une caractéristique plus profonde est que l’application peut également appeler des outils. Les boutons, les formulaires et les graphiques ne sont pas décoratifs ; ils peuvent invoquer les mêmes outils MCP que ceux utilisés par l’agent, via l’hôte.

MCP App → call tool → Host → tools/call → MCP Server → restart_server()

Par exemple, un bouton de redémarrage à l’intérieur du tableau de bord peut appeler restart_server via l’hôte, plutôt que d’inventer un canal secondaire :

async function restartServer(serverId) {
  return app.callServerTool({
    name: "restart_server",
    arguments: { server_id: serverId }
  });
}

L’hôte reste le gardien des permissions, de la journalisation et des politiques.

Une capacité, deux interfaces

Ainsi, la même opération backend peut présenter deux aspects : un outil que le modèle utilise lors de la conversation, et une application que l’humain manipule visuellement. Aucun ne remplace l’autre. Les agents restent performants pour le raisonnement ouvert ; les applications se distinguent lorsque la structure, la densité ou des actions répétées sont importantes.

Un exemple en production : approbation humaine au sein d’un flux de travail d’agent

Imaginez un agent qui rédige une histoire d’utilisateur qui doit être approuvée avant d’être enregistrée. Sans applications, le modèle colle le brouillon dans la conversation et espère que l’être humain tape « approuver » ou « rejeter avec des raisons ». Avec des applications, un outil tel que present_user_story_for_approval peut renvoyer le brouillon ainsi qu’une ressource UI affichant les options Accepter / Demander des modifications / Rejeter. En cliquant sur Rejeter, un champ de raison s’ouvre ; en soumettant, on peut appeler un outil qui enregistre la décision et met à jour éventuellement le contexte du modèle afin que la prochaine étape sache déjà pourquoi la version 1 a échoué.

Ce schéma repose sur l’intervention humaine avec une véritable interface de contrôle, et non sur un rituel fragile basé sur le langage naturel.

Tous les boutons n’ont pas besoin d’être des outils visibles par le modèle

Certaines outils devraient être réservés aux agents uniquement, d’autres uniquement aux applications, et d’autres encore partagés. La pagination au sein d’un tableau de bord ne devrait pouvoir être appelée que depuis l’interface, afin d’éviter que le modèle ne soit submergé de fonctionnalités liées au changement de page. Le serveur peut définir différents niveaux de visibilité, créant ainsi une véritable frontière d’accès plutôt qu’une simple convention de nommage.

La communication peut également s’effectuer du côté de l’application vers le contexte du modèle (lorsque l’hôte le permet) : une raison de rejet saisie dans l’interface peut mettre à jour ce contexte, permettant au modèle suivant d’améliorer le brouillon sans que l’utilisateur ait à réécrire sa critique dans la chat.

MCP Apps n’est pas une primitive de base nouvelle

Malgré son nom, Apps n’est pas un quatrième élément parmi les outils/ressources/promptes. Il s’agit d’une extension qui standardise la relation entre un outil et une ressource d’interface, ainsi que le protocole d’hôte/interfaced. Si les outils et les ressources sont déjà connus, Apps constitue une couche interactive autour d’eux — et non un protocole distinct ajouté ultérieurement.

Quelles sont les modifications si vous possédez l’application de chat

Les équipes qui développent leur propre plateforme d’agent deviennent l’hôte MCP. Cet hôte doit détecter les métadonnées de l’interface utilisateur, lire les ressources, mettre l’application en environnement isolé, transmettre les entrées/sorties des outils à l’affichage, proxyer les appels d’outils autorisés vers le serveur, négocier les capacités et appliquer les permissions. Il s’agit d’une véritable surface architecturale.

Il y a trois acteurs : le serveur MCP, l’hôte MCP et l’affichage de l’application MCP. Le SDK officiel sépare les développeurs d’affichages, ceux des hôtes et ceux des serveurs. Les packages d’aide se trouvent sous @modelcontextprotocol/ext-apps en TypeScript, ce qui n’oblige pas à intégrer la logique métier dans Node. Le MCP au niveau des connexions utilise toujours les métadonnées des outils, les ressources, le contenu structuré et les requêtes MCP ; par conséquent, un serveur Python/FastMCP fonctionne s’il expose ce que les hôtes compatibles avec Apps attendent. L’affichage repose sur des technologies web ; les backends existants peuvent rester en place.

La sécurité ne peut pas être une considération ultérieure

Les interfaces utilisateur exécutables augmentent les risques. Les iframes isolés et les appels gérés par l’hôte aident, mais chaque application doit être traitée comme une interface utilisateur non fiable — surtout lorsqu’elle peut déclencher des fonctions telles que restart_service(), delete_resource(), approve_payment() ou deploy_to_production(). Les dialogues de confirmation sont utiles mais insuffisants. L’authentification, l’autorisation, la validation, les politiques de sécurité, les journaux d’audit, l’idempotence, les vérifications de version et les limites de fréquence doivent rester du ressort du backend. L’interface utilisateur n’est pas la frontière de confiance.

Où les applications MCP ont réellement du sens

Ne mettez pas chaque outil dans une application. Pour renvoyer un code 42 ou une chaîne de version, il n’est pas nécessaire d’utiliser React. Les applications s’avèrent utiles lorsque l’interaction est structurée :

Panneaux de contrôle opérationnels — services, déploiements, infrastructure, journaux, métriques, tâches, files d’attente : examiner puis agir.

Flux de travail d’approbation — approuver/refuser, accepter/ Demander des modifications, déployer/annuler, publier/conserver en brouillon. C’est souvent la solution la plus adaptée aux entreprises.

RAG et recherche de connaissances d’entreprise — filtres, cases à cocher et la fonction « Comparer les éléments sélectionnés » surpassent vingt résultats en texte brut, tandis que l’agent gère toujours le raisonnement.

Gouvernance des agents — le langage naturel permet de déterminer qui peut accéder à Salesforce en production ; une vue du registre est plus pratique pour examiner et approuver les modifications de permissions.

Formulaires et configuration — décrire « CPU 2, mémoire 4GB, région us-east-1, réplicas 3 » est moins efficace qu’un formulaire que l’agent peut afficher lorsque c’est nécessaire.

Ne créez pas une application par outil

Évitez la prolifération de tool_1 → app_1. Préférez les applications de domaine. Une application de « Gestion des déploiements » peut regrouper en une seule famille les opérations de récupération, d’enregistrement des logs, de redémarrage, d’échelle et de réversion. Un outil d’entrée permet de découvrir l’application ; par la suite, l’interface peut appeler directement les opérations associées. L’UI reste cohérente et l’interface MCP reste plus propre.

Le changement architectural majeur

Le changement intéressant n’est pas l’iframe lui-même. Les opérations conçues pour les agents peuvent désormais exposer une couche utilisateur normalisée :

OPERATION → Machine Interface (MCP Tool) + Human Interface (MCP App)

Si les capacités sont emballées sous forme de plugins d’agent, un paquet Salesforce peut livrer en même temps des instructions, des outils (search_accounts, create_opportunity, update_lead), des permissions, des évaluations et des applications (navigateur d’comptes, formulaire d’opportunité, tableau de bord de pipeline). La capacité devient ainsi une interface d’interaction complète pour les agents et les utilisateurs humains.

L’agent n’a pas besoin de connaître l’existence de React ou d’iframes. Il appelle get_services(...) ou present_user_story_for_approval(...) ; les métadonnées indiquent à l’hôte qu’une interface existe. L’interface utilisateur reste dans la couche UI, le raisonnement avec l’agent se fait côté backend.

Comment j’introduirais cela dans un système existant

Sur une plateforme qui dispose déjà d’un chat personnalisé, d’agents et d’un serveur FastMCP, il convient d’éviter une refonte. Commencez par une fonctionnalité uniquement en lecture comme get_agents(), accompagnée de la vue minimale (ui://agents/list) affichant les noms, les statuts et le nombre d’outils — sans boutons. Prouvez le fonctionnement : l’agent appelle l’outil, l’hôte détecte l’interface utilisateur, lit les ressources, affiche l’iframe, et le résultat de l’outil parvient à la vue.

Ensuite, ajoutez la fonction de mise à jour, puis une véritable opération comme la désactivation de l’agent, suivie de mécanismes d’autorisation et d’enregistrement des audits, ainsi que des applications plus avancées. L’adoption reste progressive sans avoir à réécrire la logique de fonctionnement de l’agent.

Les équipes qui évaluent cette adoption doivent également prévoir des ressources pour la négociation des capacités du hôte. Un serveur conscient des applications qui ajoute toujours des métadonnées d’interface peut continuer à fonctionner correctement sur des clients plus anciens, à condition que le hôte ignore simplement les champs inconnus et que le contenu structuré de l’outil reste complet. Inversement, un hôte prétendant prendre en charge les applications doit mettre en œuvre des mécanismes de sandboxing, de lecture des ressources et de proxysage des appels d’outils avant d’activer ce paramètre pour les utilisateurs finaux ; des hôtes partiellement implémentés génèrent des iframes défectueux qui érodent la confiance plus rapidement que du JSON pur ne l’aurait jamais fait.

L’observabilité doit faire partie du même plan de déploiement. Enregistrez quels outils contiennent des ressources UI, quels hôtes les ont rendues, quelles appels d’outils initiés par des boutons ont réussi et lesquels sont passés en mode texte. Ces métriques vous indiquent si les applications chargent réellement du contenu interactif ou si les utilisateurs préfèrent encore taper dans le chat. Sans cette telemétrie, il est facile de déployer des tableaux de bord que personne ne clique.

Finalement, assurez-vous que les contrats de schéma soient versionnés. L’application et l’outil doivent s’accorder sur les noms et les types des champs. Si servers[].cpu est divisé en objets imbriqués sans mise à jour du contrat UI, des widgets vides seront affichés tandis que l’agent continuera de recevoir un JSON correct. Considérez le chargement attendu par l’application comme une API publique appartenant à la même équipe que celle qui gère l’outil.

Lors de l’évaluation du succès après le lancement, il convient de distinguer les cas où « L’application est affichée » de ceux où « L’application est utilisée ». Un iframe qui s’affiche une seule fois et ne reçoit jamais de clic n’a qu’une valeur curiosité ; en revanche, une application qui provoque des redémarrages, des approbations ou des modifications de configuration a une réelle importance pour le produit. Associez les analyses de produits aux journaux d’audit MCP afin de pouvoir indiquer quelles actions humaines proviennent des applications par rapport au chat, et si ces actions ont réduit le temps de résolution des tickets déjà gérés par les agents.

Dernière pensée

MCP a répondu à la question de savoir comment les agents communiquent avec des systèmes externes via un seul protocole. Les applications MCP permettent de savoir comment les humains peuvent utiliser ces mêmes fonctionnalités sans quitter la conversation en cours.

Hier, le parcours suivait l’agent, les outils, JSON, puis la prose. Aujourd’hui, une seule capacité peut se diviser : les modèles continuent d’appeler des outils au cours de la conversation tandis que les utilisateurs manipulent une application visuelle, et ces deux branches aboutissent aux mêmes services de domaine. Le raisonnement reste géré par l’agent, l’exécution par les outils, et lorsque le travail nécessite une structure, le protocole peut afficher des tableaux de bord, des formulaires, des validations, des graphiques, des panneaux de configuration et des points de contrôle humains directement dans la conversation — sans abandonner la couche MCP sur laquelle les agents dépendent déjà.

C’est pourquoi MCP Apps va au-delà de simples réponses plus esthétiques : les serveurs évoluent en passant d’extrémités destinées aux machines à des couches d’interaction portables pour les agents comme pour les humains.

Précisez explicitement les solutions de secours pour les documents dans le README de votre serveur : quels outils déclarent les ressources UI, quels hôtes sont connus pour les afficher, et à quoi ressemble le texte ou la version structurée de secours lorsque les applications ne sont pas disponibles. Cette documentation permet d’éviter des tickets de support du type « MCP ne fonctionne pas », alors que le véritable problème est un hôte qui n’a pas l’extension activée.

Lectures complémentaires

La documentation principale concernant l’extension Apps est publiée sur apps.extensions.modelcontextprotocol.io (sections d’aperçu et API). Les comptes-rendus chronologiques se trouvent sur blog.modelcontextprotocol.io pour la proposition de 2025, la déclaration de mise en production en 2026, ainsi que pour le track des extensions en version candidate. Le blog de Machine Learning d’AWS a par la suite présenté un modèle d’hébergement Bedrock AgentCore qui reste indépendant du type d’hôte.

Si vous gérez plusieurs serveurs MCP aujourd’hui, résistez à l’envie d’inventer un mini-framework privé pour chaque équipe. Préférez des outils hébergés en commun pour gérer le cycle de vie des iframe, des types TypeScript partagés pour les données utilisées par les applications, ainsi qu’une courte liste de contrôle pour l’évaluation du design : cette application a-t-elle besoin d’une interface utilisateur ? Existe-t-il déjà une application qui pourrait l’intégrer ? Quelle solution de secours en cas où l’hébergeur ne peut pas afficher les applications ? Qui est responsable de l’autorisation des appels déclenchés par des boutons ? Ces quatre questions permettent de freiner la prolifération prématurée des applications.

La formation est également importante. Les agents qui voient soudainement moins d’outils, car certaines opérations ont été déplacées derrière une visibilité réservée aux applications, se comporteront différemment. Mettez à jour les messages du système et les ensembles d’évaluation lorsque vous divisez les niveaux d’accès, et conservez un test de référence qui ouvre une application, clique sur une action sûre, et vérifie que la ligne d’audit backend apparaît. Sans ce test, les dérives restent cachées dans l’iframe jusqu’à ce qu’un client signale un bouton inactif.

Avec ces éléments en place, les applications MCP cessent de sembler être une nouveauté et deviennent des fonctionnalités ordinaires au sein des plateformes d’agents. Cela permet de boucler le cycle d’adoption grâce à des solutions de secours claires et une utilisation mesurable.