mcp-ui : livrer du HTML dans MCP, et ce que le standard MCP Apps change pour vos hôtes
UI over MCP. Create next-gen UI experiences with the protocol and SDK!
En bref
- De quoi s’agit-il ?
- Le SDK mcp-ui implémente la spécification MCP Apps pour transporter et rendre des interfaces web à côté des résultats d'outils. Voici comment fonctionne le mécanisme, ce qu'il coûte, et à quel moment il n'est pas le bon outil.
- À qui s’adresse-t-il ?
- Adoptez mcp-ui si vous construisez un hôte MCP qui doit afficher du HTML fourni par un serveur, ou un serveur qui veut exposer des widgets interactifs : le paquet @mcp-ui/client est présenté dans le README comme le SDK recommandé pour les hôtes MCP Apps, et les quatre implémentations serveur (TypeScript, Ruby, Python) couvrent les piles courantes.
- Puis-je l’utiliser commercialement ?
- Oui. Apache-2.0 est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
- Est-il encore maintenu ?
- Oui. Les derniers commits datent d’il y a 70 jours.
- En quel langage est-il écrit ?
- Principalement TypeScript, d’après les statistiques de langage de GitHub.
Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.
ANALYSE OPEN SOURCE APPROFONDIE
Le problème : un résultat d'outil MCP est du texte, pas une interface
Un serveur MCP renvoie du contenu typé, principalement du texte, et l'hôte l'affiche comme tel. Dès qu'un outil produit quelque chose de structuré (un tableau, un formulaire, un sélecteur), il faut soit sérialiser la donnée et laisser l'hôte la rendre avec son propre code, soit accepter une sortie plate. mcp-ui répond à ce manque en transportant du HTML dans le protocole lui-même : le serveur déclare une ressource UI, l'hôte la récupère et la rend dans un iframe. Le public visé est double. D'un côté les auteurs de serveurs qui veulent attacher un widget à un outil sans imposer un composant React à chaque client. De l'autre les auteurs d'hôtes, qui doivent afficher des interfaces venues de serveurs qu'ils ne contrôlent pas. Le README situe le projet dans une généalogie précise : mcp-ui a exploré le concept d'UI interactive sur MCP, et ces motifs ont alimenté la spécification MCP Apps, laquelle a standardisé la livraison d'UI sur le protocole. Autrement dit, le SDK se présente aujourd'hui comme une implémentation d'un standard, pas comme une extension propriétaire.
Le lien _meta.ui.resourceUri, ou comment un outil trouve son interface
Le mécanisme central tient dans une clé de métadonnées. Côté serveur, on crée d'abord une ressource avec createUIResource, qui prend un uri de schéma ui:// (par exemple ui://my-server/widget), un content de type rawHtml avec une chaîne htmlString, et un encoding valant text. On enregistre ensuite un gestionnaire de ressource avec registerAppResource, puis on déclare l'outil via registerAppTool en plaçant dans son _meta la valeur ui.resourceUri pointant vers l'URI de la ressource. C'est ce champ que l'hôte inspecte : d'après le README, les hôtes détectent _meta.ui.resourceUri, récupèrent l'UI via resources/read et la rendent avec AppRenderer. Le format sur le fil est l'objet UIResource, avec un type valant resource et un sous-objet contenant uri, mimeType, et soit text soit blob. Le mimeType standard est text/html;profile=mcp-app. La variante blob transporte le HTML encodé en base64, ce qui laisse le choix entre lisibilité et robustesse du transport. Ce découplage entre l'outil et sa ressource a une conséquence pratique : l'interface peut être mise en cache ou servie séparément du résultat, et un même widget peut être référencé par plusieurs outils.
AppRenderer contre UIResourceRenderer : deux époques dans le même paquet
Le paquet client expose deux composants, et le choix entre eux dépend de vos hôtes. AppRenderer correspond au chemin MCP Apps : il accepte une prop client optionnelle pour la récupération automatique de la ressource, un toolName, un toolInput et un toolResult, une prop sandbox contenant l'URL d'un proxy, plus onOpenLink et onMessage pour traiter les demandes émises par l'interface. UIResourceRenderer vise les hôtes historiques qui embarquent la ressource directement dans la réponse de l'outil : il prend une prop resource et un callback onUIAction qui reçoit les actions de type tool, prompt, link, notify et intent. Le même composant existe en Web Component sous la balise ui-resource-renderer, avec un attribut resource contenant du JSON. Cette dualité est un aveu de transition : le README qualifie lui-même UIResourceRenderer de legacy. Si vous démarrez un hôte aujourd'hui, partir sur UIResourceRenderer vous engage dans un chemin dont la documentation annonce déjà la sortie. Le rendu HTML, dans les deux cas, passe par un composant interne HTMLResourceRenderer qui place le contenu dans un iframe, ce qui est adapté à du HTML autonome.
Mise en route : les commandes et les clés visibles dans le dépôt
L'installation se fait par les gestionnaires de paquets habituels, et le README affiche des badges de version pour chacun des canaux : @mcp-ui/server et @mcp-ui/client sur npm, mcp_ui_server sur RubyGems, mcp-ui-server sur PyPI. Le côté serveur TypeScript s'écrit avec registerAppTool et registerAppResource importés de @modelcontextprotocol/ext-apps/server, createUIResource venant de @mcp-ui/server. Le côté client s'importe depuis @mcp-ui/client. Deux détails de configuration méritent attention avant d'écrire du code. Le premier est la prop sandbox d'AppRenderer : elle attend un objet avec une url de proxy, et le README ne détaille pas ce que ce proxy doit implémenter. Le second est le mimeType : pour du HTML au standard MCP Apps, la valeur attendue est text/html;profile=mcp-app, alors que l'exemple de Web Component du README utilise simplement text/html. Cette divergence entre deux exemples du même document est le genre de détail qui coûte une heure de débogage si on la découvre en production.
Le sandbox et les actions UI : la partie que la documentation laisse en creux
Le README consacre une section à la sécurité et une autre aux actions UI, mais le texte fourni n'en détaille pas le contenu. On peut seulement affirmer ce qui apparaît dans les exemples. Les interfaces communiquent avec l'agent en émettant des événements que l'hôte intercepte, via onUIAction pour le chemin legacy et onMessage pour AppRenderer. Le README illustre le cas d'un bouton dans du HTML qui déclenche un appel d'outil. Le point non résolu est le périmètre réel du bac à sable : AppRenderer reçoit une URL de proxy, ce qui suggère que le HTML est servi depuis une origine distincte plutôt qu'injecté directement, mais le document ne précise ni les en-têtes, ni la politique de sandbox de l'iframe, ni les garanties offertes. Pour un composant qui exécute du HTML fourni par un tiers, c'est la question la plus importante du projet, et elle reste à trancher en lisant le code et la page Security du dépôt plutôt qu'en se fiant au README. À noter aussi que le HTMLResourceRenderer est décrit comme adapté au HTML autonome, ce qui exclut de fait les interfaces qui ont besoin de ressources externes.
Ce que mcp-ui ne fera pas pour vous
Le projet ne fournit aucun moteur de rendu pour autre chose que du HTML. Le README liste un seul type de ressource pris en charge, text/html;profile=mcp-app, et ne mentionne ni React distant, ni composants natifs, ni format déclaratif. Si vos interfaces doivent s'intégrer à la mise en page de l'hôte, hériter de son thème ou de ses composants, l'iframe est un mur : vous obtenez une boîte isolée, pas une extension de l'application. Deuxième limite, la dépendance à un hôte compatible. Un widget mcp-ui n'a aucune existence hors d'un client qui sait lire _meta.ui.resourceUri ou traiter une ressource embarquée. Si votre interface doit aussi fonctionner dans un navigateur seul ou dans une application non MCP, ce SDK n'est pas le bon véhicule. Troisième point, la coexistence de deux modèles dans la même version majeure du paquet client, avec un modèle explicitement étiqueté legacy, signifie que les exemples trouvés en ligne ne s'appliquent pas tous à votre configuration. Il faut savoir lequel des deux composants vous utilisez avant de copier un extrait de code.
Face à quoi on compare : Apps SDK et la spécification MCP Apps
Le README cite Apps SDK comme l'autre effort qui a influencé la spécification MCP Apps, laquelle a ensuite standardisé la livraison d'UI sur le protocole. La différence tient à la position dans la chaîne. Apps SDK est un chemin propriétaire lié à un hôte particulier. mcp-ui se présente comme une implémentation du standard, avec quatre paquets serveur dans trois langages et un paquet client, ce qui laisse la possibilité d'écrire un serveur en Ruby ou en Python et de le rendre avec le même client. L'alternative la plus directe n'est cependant pas un autre SDK mais l'absence de SDK : faire rendre les résultats par l'hôte lui-même, en définissant un format de données que le client interprète. Cette approche garde le contrôle du style et de l'accessibilité, au prix d'un contrat à maintenir entre chaque serveur et chaque hôte, et de l'impossibilité d'envoyer une interface arbitraire. mcp-ui échange ce contrôle contre l'universalité du HTML. Le choix se joue là, pas sur les fonctionnalités.
Maintenance, licence et coût de mise à jour
Le dépôt n'est pas archivé, la branche par défaut est main, et les publications récentes visibles concernent le paquet client, dont client/v7.1.1 daté du 9 mai 2026. Le numéro majeur 7 indique que des ruptures ont déjà eu lieu, et la présence simultanée d'AppRenderer et de UIResourceRenderer dans cette version montre comment le projet gère les transitions : en gardant l'ancien chemin plutôt qu'en le supprimant. Pour un intégrateur, cela veut dire que les mises à jour du client demandent de vérifier à chaque fois lequel des deux composants est concerné. Le serveur, lui, est plus stable par nature puisque son rôle se limite à produire une ressource. La licence est Apache-2.0, une licence permissive qui autorise l'usage commercial et la modification, avec les obligations habituelles de conservation des mentions et de l'avis de licence, et une clause de brevets. Le README ne signale aucune restriction supplémentaire. Ce paragraphe n'est pas un avis juridique : pour un produit distribué, faites relire les obligations de notice par qui de droit.
Conclusion éditoriale
Adoptez mcp-ui si vous construisez un hôte MCP qui doit afficher du HTML fourni par un serveur, ou un serveur qui veut exposer des widgets interactifs : le paquet @mcp-ui/client est présenté dans le README comme le SDK recommandé pour les hôtes MCP Apps, et les quatre implémentations serveur (TypeScript, Ruby, Python) couvrent les piles courantes. Ne l'adoptez pas si vos interfaces doivent tourner hors d'un hôte MCP, ou si vous ne pouvez pas fournir une URL de proxy pour le sandbox : AppRenderer attend une prop sandbox avec cette URL, et sans elle le composant ne dispose pas de la configuration annoncée. Avant d'intégrer, vérifiez trois choses dans votre copie du dépôt : la version publiée de @mcp-ui/client face au tag client/v7.1.1, le contenu réel de la page Security pour les garanties de sandbox, et si vos hôtes cibles parlent MCP Apps ou l'ancien format MCP-UI, car cela détermine si vous montez AppRenderer ou UIResourceRenderer.
Notes de la communauté