BlogIngénierie
Notre MCP App dans ChatGPT sur mobile : ce que nous avons appris
Nous avons fait tourner notre panneau de partition dans le site mobile de ChatGPT, sur un simulateur d’iPhone : ce que contiennent ses marges de zone de sécurité (safe-area insets), ce qui se passe quand il reconstruit un panneau, et comment nous testons désormais les deux sans téléphone.
- Écrit par
- Haiyi Mei
- Publié
- Longueur
- 8 min de lecture
La réponse courte
Sur téléphone, ChatGPT superpose sa barre de titre et sa zone de saisie à une MCP App en plein écran et les signale comme des marges de zone de sécurité, d’environ 47 px et 127 px dans notre essai ; il déplace celle du bas pendant que l’application est ouverte. Il a aussi reconstruit notre panneau à partir du résultat d’outil d’origine de la conversation chaque fois qu’il passait en plein écran ou en sortait. Laissez la marge libre sans ajouter de réserve de votre cru, replacez les éléments positionnés par script à chaque changement de contexte, et vérifiez au chargement si un résultat est périmé. Nous avons testé le site mobile de ChatGPT dans un simulateur d’iPhone, pas l’application native.
Qu’est-ce qui a cassé quand nous avons ouvert notre MCP App dans ChatGPT sur téléphone ?
Quatre choses, toutes liées au plein écran. Le panneau de ScoreStarling affiche une partition dans la conversation (comment le connecter) ; en plein écran, vous touchez des notes et interrogez la conversation à leur sujet depuis une carte de sélection qui se fixe au-dessus du lecteur sur téléphone. Le 7 octobre 2026, nous l’avons essayé sur le site mobile de ChatGPT, dans Safari sur l’iPhone 17 du simulateur iOS (402 × 874 points). Le cadre du panneau est cross-origin ; nous l’avons donc lu sur des captures d’écran.
| Ce que nous avons vu | Cause | Correctif |
|---|---|---|
| Le lecteur flottait environ au tiers de la hauteur de l’écran | Un espace fixe de 96 px ajouté à une marge du bas (environ 127 px) qui couvre déjà la zone de saisie | La marge ou 96 px, selon la plus grande |
| Un texte plus long ou la barre Thinking relevait le lecteur, pas la carte fixée | ChatGPT déplace la marge ; le lecteur suit via le CSS, la carte est placée par script | Placer la carte à chaque changement de contexte |
| Après une modification, l’entrée ou la sortie du plein écran affichait l’ancienne partition, en lecture seule | ChatGPT construisait un nouveau panneau à partir du résultat d’outil d’origine | Lire la version actuelle si un résultat est en retard |
| Après une modification faite dans la conversation, la carte flottait environ 40 px au-dessus du lecteur | Notre bandeau « Updated from the chat » [mis à jour depuis la conversation] a déplacé la zone à partir de laquelle la carte est mesurée | Placer la carte quand cette zone change de taille |
Pourquoi une MCP App en plein écran se cache-t-elle derrière la zone de saisie de ChatGPT sur téléphone ?
Parce que ChatGPT dessine sa zone de saisie par-dessus votre cadre et vous indique la place qu’elle prend par la marge de zone de sécurité du bas. Ignorez la marge et vos commandes passent sous la zone ; ajoutez par-dessus votre propre réserve, comme nous l’avons fait, et elles flottent. La spécification MCP Apps ne décrit safeAreaInsets que par « Safe area boundaries in pixels » [limites de la zone de sécurité, en pixels], et la documentation d’OpenAI dit que la zone de saisie (le « composer ») reste superposée en plein écran sans en donner la taille (les deux vérifiées le 7 octobre 2026). Nos 47 px et 127 px sont des estimations tirées de captures d’écran.
Le 6 octobre, une conversation sur téléphone montrait notre lecteur sous la barre de titre de ChatGPT : nous avons donc placé l’en-tête sous la marge du haut et le lecteur en bas, où notre CSS réservait en plus 96 px pour une zone de saisie, au-dessus de la marge du bas. Un test local avec une marge de 34 px avait l’air correct ; le 127 + 96 de ChatGPT, non. Désormais le panneau garde la plus grande des deux valeurs, et lit aussi le window.openai.safeArea de ChatGPT :
// panel.js, simplified: the host's inset or 96 px, never both
const bottom = Math.max(context.safeAreaInsets?.bottom || 0, window.openai?.safeArea?.insets?.bottom || 0);
root.style.setProperty('--safe-bottom', `${bottom}px`);
root.style.setProperty('--composer-space', fullscreen ? `${Math.max(0, 96 - bottom)}px` : '0px');
/* panel.css */
.stage > .player { bottom: calc(10px + var(--safe-bottom) + var(--composer-space)); }
Que change-t-il pendant qu’une MCP App est ouverte en plein écran sur téléphone ?
Les marges. Dans notre essai, le bord inférieur a bougé quand un texte en cours de saisie est passé à deux lignes et quand la barre Thinking a remplacé la zone de saisie. La spécification permet à un hôte d’envoyer ui/notifications/host-context-changed chaque fois qu’un champ du contexte change, avec seulement les champs modifiés, que la vue doit fusionner.
Notre lecteur repose sur une variable CSS et a suivi. La carte de sélection, placée par script, est restée sur place : désormais, chaque changement de contexte la replace. Notre propre bandeau a provoqué une seconde dérive : « Updated from the chat » s’affiche au-dessus de la partition pendant 20 secondes et repousse la zone de la partition vers le bas. La carte, mesurée depuis le haut de cette zone, a glissé sur le lecteur, et si quelque chose la replaçait entre-temps, elle flottait au-dessus du lecteur une fois le bandeau disparu. Un ResizeObserver sur la zone replace désormais aussi la carte, une fois par image d’animation :
this.context = {...this.context, ...params}; // host.js, simplified: merge the partial update
function hostContext(next) { applyContext(next); editor.queuePlace(); }
new ResizeObserver(() => { updateClip(); editor.queuePlace(); }).observe($('stage'));
Pourquoi une MCP App affiche-t-elle une ancienne version après la sortie du plein écran ?
Parce que, sur téléphone, ChatGPT construisait un nouveau panneau chaque fois qu’il passait en plein écran ou en sortait, et lui donnait le résultat d’outil d’origine de la conversation, produit avant toute modification. La spécification permet à un hôte de détruire une vue à n’importe quel moment ; un résultat d’outil ne fait que garder la trace de l’instant où son outil s’est exécuté.
Notre panneau était un mélange d’instantané et de données en direct : les images des pages et les notes de sa propre révision, plus un champ de révision actuelle lu quand le panneau le récupère. Le panneau reconstruit a dessiné la révision 0, a vu que la partition en était à la révision 3 et est passé en lecture seule. Sa vérification des modifications faites dans la conversation comparait la révision du serveur à ce champ déjà à jour, si bien que le panneau ne se remettait jamais à jour. Désormais, un panneau à qui l’hôte remet un résultat que la partition a dépassé lit une fois la révision actuelle, sauf si le résultat contient une modification suggérée en attente d’approbation, qui est censée différer.
Comment tester le comportement de ChatGPT sur téléphone sans téléphone ?
Imitez le vrai hôte dans une réplique, et prouvez que chaque test échoue sans son correctif. Nous utilisons sunpeak, qui reproduit ChatGPT et Claude pour les tests Playwright. Sa coque ChatGPT mobile (version 0.20.91) dessine une barre de titre et une zone de saisie, et signale la zone comme une marge de 92 px. Les trois tests que nous avons écrits pour ces bugs, sur un écran tactile de 402 × 874, ajoutent le reste. Par le cadre sandbox de la coque, qui est le parent du panneau comme l’est le cadre de ChatGPT, ils envoient de nouvelles marges de 127, 160, 70 et 127 px, et après une modification ils rechargent le panneau et lui remettent le résultat d’outil d’origine. Un autre test modifie la partition en dehors du panneau, comme le fait la conversation. Le lecteur doit finir de 0 à 24 px au-dessus de la plus grande des deux valeurs, la marge ou 96 px, et la carte de 0 à 16 px au-dessus du lecteur.
- Exécuter le vrai hôteLe site mobile de ChatGPT dans un simulateur
- Corriger une causeDéployer, actualiser les outils de l’application, regarder à nouveau
- Imiter l’hôteEnvoyer ses messages depuis le cadre de la réplique
- Annuler le correctifLe nouveau test doit échouer sans lui
| Correctif annulé | Ce qui a échoué |
|---|---|
| La marge ou 96 px, jamais les deux | Test de la zone de saisie : « lecteur proche de la zone de saisie » |
| Carte placée à chaque changement de contexte | Test de la zone de saisie : « carte dégagée du lecteur » |
| Version actuelle pour un panneau reconstruit | Test de reconstruction : l’annulation restait désactivée |
| Carte placée quand la zone change de taille | Test du bandeau : « carte fixée sur le lecteur » |
Une exécution de ces trois tests a pris 59,9 secondes. Un quatrième, ajouté le même jour, vérifie l’en-tête sur une seule ligne de l’éditeur sur téléphone et le lecteur ; nos règles pour les contributeurs exigent désormais les tests sur téléphone après toute modification de la mise en page plein écran, des marges, de la carte ou du traitement des résultats. L’exécution sur téléphone a aussi révélé que ChatGPT transformait un B4 sélectionné en C4, une septième plus bas, pour « Changez cette note en do » ; une règle de l’octave la plus proche dans la description de l’outil a fait passer un test local avec un vrai modèle de 2 exécutions réussies sur 3 à 6 sur 6.
Ce que nous n’avons pas vérifié
Nos vérifications sur téléphone ont eu lieu dans le simulateur iOS et sur le site mobile de ChatGPT : pas de téléphone physique, pas d’application native. Restent ouverts :
- les marges exactes que ChatGPT envoie, et quand ; les nôtres sont des estimations que les répliques réutilisent ;
- la barre d’outils développée de Safari, qui cache à moitié la zone de saisie et le bord inférieur du lecteur ;
- un défilement de page d’environ 156 points que Safari a laissé après la fermeture du clavier, et qu’un panneau cross-origin ne peut pas annuler ;
- une bande opaque pouvant atteindre environ 777 points quand le plein écran s’est ouvert alors que ChatGPT répondait encore ;
- la feuille de réponse de ChatGPT et la destruction de son propre iframe, que les répliques n’imitent pas ;
- ChatGPT sur ordinateur, où le plein écran est un panneau latéral dont la zone de saisie est à l’extérieur ; nous n’avons pas lu ses marges.
Une liste de contrôle pour les MCP Apps sur téléphone
- Laissez libres les deux marges ; si vous gardez aussi une valeur de repli pour une zone de saisie, prenez la plus grande, jamais la somme.
- Fusionnez chaque notification
host-context-changedet replacez tout ce qui est positionné par script, une fois par image. - Observez vos propres conteneurs pour repérer les bandeaux qui les déplacent.
- Attendez-vous à une reconstruction à partir d’un ancien résultat d’outil ; comparez sa version à celle du serveur au chargement.
- Donnez à votre hôte de test local les marges mesurées sur le vrai.
- Traitez l’URI de la ressource d’interface comme une clé de cache, comme le conseille la documentation d’OpenAI, et après en avoir publié une nouvelle, actualisez les outils de l’application dans ChatGPT (réglages du plug-in, puis « Manage app » [Gérer l’application] et « Refresh tools » [Actualiser les outils] ; vérifié le 7 octobre 2026).
- Transformez chaque constat fait sur le vrai hôte en test de réplique qui échoue sans son correctif.
Sources
- SEP-1865 : MCP Apps : Interactive User Interfaces for MCP (stable, 2026-01-26), Model Context Protocol
- Add UI to your MCP server, OpenAI
- UI guidelines, OpenAI
- Reference (le pont de composants
window.openai), OpenAI - MCP Testing Framework, sunpeak
Questions et réponses
Sur téléphone, ChatGPT compte-t-il sa zone de saisie dans safeAreaInsets ?
Dans notre essai, oui. Sur le site mobile de ChatGPT (simulateur iPhone 17, 7 octobre 2026), la marge du bas faisait environ 127 px et couvrait la zone de saisie, et la marge du haut, environ 47 px, couvrait la barre de titre. La spécification MCP Apps ne dit pas ce que contient une marge : laissez donc libre l’espace indiqué et n’y ajoutez pas de réserve de votre cru.
ChatGPT modifie-t-il les marges pendant qu’une application est ouverte en plein écran ?
Oui, dans notre essai : un texte de deux lignes en cours de saisie et la barre « Thinking » [réflexion] de ChatGPT ont tous deux déplacé le bord inférieur. Appliquez les nouvelles marges chaque fois que ui/notifications/host-context-changed arrive, en fusionnant les champs qu’elle contient avec ce que vous avez déjà, et replacez tout ce que vous positionnez par script.
Pourquoi ma MCP App affiche-t-elle d’anciennes données après le passage en plein écran sur téléphone ?
Sur téléphone, ChatGPT construisait un nouveau panneau à partir du résultat d’outil d’origine de la conversation chaque fois qu’il passait en plein écran ou en sortait : le nôtre affichait donc la partition telle qu’elle était avant les modifications ultérieures. Au chargement de la vue, comparez la version du résultat à celle du serveur et lisez une fois l’état actuel si le résultat est en retard.
Peut-on tester la mise en page de ChatGPT sur téléphone sans téléphone ?
En partie. Nous rejouons ce que le téléphone affichait dans la coque ChatGPT mobile de sunpeak, avec Playwright : marges qui bougent, panneau reconstruit et modification venue de la conversation ; chaque test échoue quand son correctif est annulé. Les valeurs que ChatGPT envoie réellement, la barre d’outils de Safari, le clavier, la feuille de réponse de ChatGPT et l’application native exigent encore un vrai téléphone.



