BlogEngenharia
Nosso MCP App no ChatGPT para celular: o que aprendemos
Rodamos nosso painel de partitura no site móvel do ChatGPT em um Simulador de iPhone: o que os insets de área segura (safe area) dele contêm, o que acontece quando ele reconstrói um painel e como agora testamos as duas coisas sem um celular.
- Escrito por
- Haiyi Mei
- Publicado
- Tamanho
- 8 min de leitura
A resposta curta
No celular, o ChatGPT coloca a barra de título e a caixa de mensagem por cima de um MCP App em tela cheia e as informa como insets de área segura, cerca de 47 px e 127 px no nosso teste, e move o inferior enquanto o app está aberto. Ele também reconstruiu o nosso painel a partir do resultado original da ferramenta na conversa sempre que entrou ou saiu da tela cheia. Mantenha o inset livre sem somar uma folga sua, posicione de novo os elementos posicionados por script a cada mudança de contexto e confira ao carregar se um resultado está desatualizado. Testamos o site móvel do ChatGPT em um Simulador de iPhone, não o app nativo.
O que quebrou quando abrimos nosso MCP App no ChatGPT no celular?
Quatro coisas, todas ligadas à tela cheia. O painel do ScoreStarling mostra uma partitura na conversa (como conectá-lo); em tela cheia, você toca nas notas e pergunta sobre elas à conversa a partir de um cartão de seleção que se encaixa acima do player no celular. Em 7 de outubro de 2026, rodamos tudo isso no site móvel do ChatGPT, no Safari de um iPhone 17 do Simulador do iOS (402 × 874 pontos). O frame do painel é cross-origin, então o lemos a partir de capturas de tela.
| O que vimos | Causa | Correção |
|---|---|---|
| O player flutuava a cerca de um terço da altura da tela | Um valor fixo de 96 px somado a um inset inferior (cerca de 127 px) que já cobre a caixa de mensagem | O inset ou 96 px, o que for maior |
| Um texto mais longo ou a barra Thinking levantou o player, mas não o cartão fixado | O ChatGPT move o inset; o player acompanha via CSS, e o cartão é posicionado por script | Posicionar o cartão a cada mudança de contexto |
| Depois de uma edição, entrar na tela cheia ou sair dela mostrava a partitura antiga, somente leitura | O ChatGPT montou um painel novo a partir do resultado original da ferramenta | Ler a versão atual se o resultado estiver desatualizado |
| Depois de uma edição pela conversa, o cartão flutuava cerca de 40 px acima do player | O nosso aviso “Updated from the chat” [Atualizado pela conversa] moveu a área a partir da qual o cartão é medido | Posicionar o cartão quando essa área mudar de tamanho |
Por que um MCP App em tela cheia fica atrás da caixa de mensagem do ChatGPT no celular?
Porque o ChatGPT desenha a caixa de mensagem por cima do seu frame e informa quanto ela cobre pelo inset inferior da área segura. Ignore o inset e seus controles ficam debaixo da caixa; some uma folga sua por cima, como fizemos, e eles flutuam. A especificação do MCP Apps descreve safeAreaInsets apenas como “Safe area boundaries in pixels” [limites da área segura em pixels], e a documentação da OpenAI diz que o campo de mensagem (o “composer”) continua sobreposto em tela cheia, sem informar o tamanho dele (as duas conferidas em 7 de outubro de 2026). Nossos 47 px e 127 px são estimativas feitas a partir de capturas de tela.
Em 6 de outubro, uma conversa no celular mostrou nosso player sob a barra de título do ChatGPT, então descemos o cabeçalho para baixo do inset superior e levamos o player para a parte de baixo, onde o nosso CSS também reservava 96 px para uma caixa de mensagem, somados ao inset inferior. Um teste local com um inset de 34 px parecia certo; os 127 + 96 do ChatGPT, não. Agora o painel mantém o que for maior e também lê o window.openai.safeArea do 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)); }
O que muda enquanto um MCP App em tela cheia está aberto no celular?
Os insets. No nosso teste, a borda inferior se moveu quando o texto digitado cresceu para duas linhas e quando a barra Thinking tomou o lugar da caixa de mensagem. A especificação permite que um host envie ui/notifications/host-context-changed sempre que um campo de contexto muda, só com os campos alterados, para a view mesclar.
O nosso player se apoia numa variável CSS e acompanhou. O cartão de seleção é posicionado por script e ficou para trás, então agora toda mudança de contexto o posiciona de novo. Nosso próprio aviso causou um segundo deslocamento: “Updated from the chat” aparece acima da partitura por 20 segundos e empurra a área da partitura para baixo. O cartão, medido a partir do topo dessa área, escorregou por cima do player, e, se algo o posicionasse de novo nesse meio-tempo, ele flutuava acima do player quando o aviso sumia. Agora um ResizeObserver na área também posiciona o cartão, uma vez por frame de animação:
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'));
Por que um MCP App mostra uma versão antiga depois de sair da tela cheia?
Porque o ChatGPT no celular montou um painel novo cada vez que entrou ou saiu da tela cheia e entregou a ele o resultado original da ferramenta na conversa, feito antes de qualquer edição. A especificação permite que um host derrube uma view a qualquer momento; o resultado de uma ferramenta só registra o instante em que a ferramenta rodou.
O nosso era meio instantâneo (snapshot), meio ao vivo: imagens das páginas e notas da revisão a que pertencia, mais um campo de revisão atual lido quando o painel o busca. O painel reconstruído desenhou a revisão 0, viu que a partitura estava na revisão 3 e ficou somente leitura. A verificação de edições feitas pela conversa comparava a revisão do servidor com esse campo, que já era o atual, e por isso nunca alcançava a revisão. Agora um painel a quem o host entrega um resultado que a partitura já ultrapassou lê a revisão atual uma vez, a menos que o resultado traga uma mudança sugerida aguardando aprovação, que deve mesmo ser diferente.
Como testar o comportamento do ChatGPT no celular sem um celular?
Imite o host real numa réplica e prove que cada teste falha sem a correção. Usamos o sunpeak, que replica o ChatGPT e o Claude para testes com Playwright. O shell de ChatGPT móvel dele (versão 0.20.91) desenha uma barra de título e uma caixa de mensagem e informa a caixa como um inset de 92 px. Os três testes que escrevemos para esses bugs, numa tela de toque de 402 × 874, acrescentam o resto. Pelo frame de sandbox do shell, que é o pai do painel assim como o frame do ChatGPT, eles enviam novos insets de 127, 160, 70 e 127 px e, depois de uma edição, recarregam o painel e entregam a ele o resultado original da ferramenta. Outro teste edita a partitura fora do painel, como faz a conversa. O player deve terminar de 0 a 24 px acima do maior valor entre o inset e 96 px, e o cartão de 0 a 16 px acima do player.
- Rodar o host realO site móvel do ChatGPT em um Simulador
- Corrigir uma causaImplantar, atualizar as ferramentas do app, olhar de novo
- Imitar o hostEnviar as mensagens dele a partir do frame da réplica
- Desfazer a correçãoO novo teste precisa falhar sem ela
| Correção desfeita | O que falhou |
|---|---|
| O inset ou 96 px, nunca os dois | Teste da caixa de mensagem: “player close to the message box” |
| Cartão posicionado a cada mudança de contexto | Teste da caixa de mensagem: “card clear of the player” |
| Versão atual para um painel reconstruído | Teste de reconstrução: o botão Desfazer continuou desativado |
| Cartão posicionado quando a área muda de tamanho | Teste do aviso: “card docked on the player” |
Uma rodada desses três levou 59,9 segundos. Um quarto teste, acrescentado no mesmo dia, confere o cabeçalho de uma linha e o player do editor no celular, e as nossas regras para colaboradores agora exigem os testes de celular depois de qualquer mudança no layout em tela cheia, nos insets, no cartão ou no tratamento de resultados. A rodada de celular também flagrou o ChatGPT transformando um B4 selecionado em C4, uma sétima abaixo, com o pedido “Troque esta nota por Dó”; uma regra de oitava mais próxima na descrição da ferramenta levou um teste local com um modelo real de 2 de 3 rodadas aprovadas para 6 de 6.
O que não verificamos
Nossas verificações de celular rodaram no Simulador do iOS e no site móvel do ChatGPT: nenhum celular físico, nenhum app nativo. Ainda em aberto:
- os insets exatos que o ChatGPT envia, e quando; os nossos são estimativas que as réplicas reaproveitam;
- a barra de ferramentas expandida do Safari, que esconde pela metade a caixa de mensagem e a borda inferior do player;
- uma rolagem de página de cerca de 156 pontos que o Safari deixou depois que o teclado fechou, e que um painel cross-origin não consegue desfazer;
- uma faixa opaca de até cerca de 777 pontos quando a tela cheia abriu enquanto o ChatGPT ainda respondia;
- a janela de resposta do ChatGPT e o desmonte do próprio iframe, que as réplicas não imitam;
- o ChatGPT no computador, onde a tela cheia é um painel lateral com a caixa de mensagem fora dele; não lemos os insets dele.
Uma lista de verificação para MCP Apps em celulares
- Mantenha os dois insets livres; se você também mantém um valor de reserva para a caixa de mensagem, use o maior, nunca a soma.
- Mescle cada notificação
host-context-changede posicione de novo tudo o que é posicionado por script, uma vez por frame. - Observe os seus próprios contêineres para avisos que os movam.
- Espere uma reconstrução a partir de um resultado de ferramenta antigo; compare a versão dele com a do servidor ao carregar.
- Dê ao seu host de teste local os insets medidos no host real.
- Trate o URI do recurso de UI como uma chave de cache, como aconselha a documentação da OpenAI, e, depois de publicar um novo, atualize as ferramentas do app no ChatGPT (configurações do plugin, “Manage app” [Gerenciar app], “Refresh tools” [Atualizar ferramentas]; conferido em 7 de outubro de 2026).
- Transforme cada descoberta no host real em um teste de réplica que falhe sem a correção.
Fontes
- 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 (a ponte de componentes
window.openai), OpenAI - MCP Testing Framework, sunpeak
Perguntas e respostas
O ChatGPT inclui a caixa de mensagem em safeAreaInsets no celular?
No nosso teste, sim. No site móvel do ChatGPT (Simulador do iPhone 17, 7 de outubro de 2026), o inset inferior era de cerca de 127 px e cobria a caixa de mensagem, e o inset superior, de cerca de 47 px, cobria a barra de título. A especificação do MCP Apps não diz o que um inset contém, então mantenha livre o espaço informado e não some uma folga sua por cima.
O ChatGPT muda os insets enquanto um app em tela cheia está aberto?
Sim, no nosso teste: um texto de duas linhas e a barra “Thinking” [Pensando] do ChatGPT moveram a borda inferior. Aplique os novos insets sempre que ui/notifications/host-context-changed chegar, mesclando os campos que ela traz com o que você já tem, e posicione de novo tudo o que você posiciona por script.
Por que meu MCP App mostra dados antigos depois de passar para tela cheia no celular?
O ChatGPT no celular montou um painel novo a partir do resultado original da ferramenta na conversa toda vez que entrou ou saiu da tela cheia, então o nosso mostrou a partitura como era antes das edições seguintes. Quando a view carregar, compare a versão do resultado com a do servidor e leia o estado atual uma vez se o resultado estiver desatualizado.
Dá para testar o layout do ChatGPT no celular sem um celular?
Em parte. Reproduzimos o que o celular mostrou no shell de ChatGPT móvel do sunpeak, com o Playwright: insets que se movem, um painel reconstruído e uma edição feita pela conversa, e cada teste falha quando a correção é desfeita. Os valores que o ChatGPT realmente envia, a barra de ferramentas do Safari, o teclado, a janela de resposta do ChatGPT e o app nativo ainda exigem um celular de verdade.



