modelcontextprotocol / modelcontextprotocol/ext-apps

Chat composer is displaced upward after interacting with a fullscreen MCP App and sending a message

Open
#776 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
2.9k
Forks
387
Avg merge
3h 21m
Merged PRs (30d)
6

Description

Summary

In Claude Desktop, clicking a control inside a fullscreen MCP App leaves the
conversation in a state where every subsequent message moves the chat composer up away
from the bottom of the window. The displacement accumulates and can carry the composer
out of the viewport.

The behavior is host-side, and it reproduces with the debug-server example in this
repository, copied without modification. Filed here because the
getting-started page
points to this repository for MCP Apps issues.

Three measured properties:

  • Until the app is clicked, messages do not displace the composer at all, at any scroll
    depth.
  • After the app is clicked, each message adds displacement equal to about half the
    scroll height that message adds.
  • The click itself displaces nothing, and returning focus to the composer does not undo
    the state.

Leaving fullscreen, or switching to another conversation, restores the composer.

Environment

  • Claude Desktop 1.52386.6.0 (Microsoft Store package) on Windows 11
  • Reproduced with examples/debug-server, copied without modification and packaged as a
    local .mcpb desktop extension

Steps to reproduce

  1. Package examples/debug-server as a .mcpb and install it in Claude Desktop.
  2. In a new conversation, call its tool and put the app in fullscreen display mode.
  3. Send two or three messages without clicking anything inside the app. The composer
    stays at the bottom of the window.
  4. Click any control inside the app. The composer does not move yet.
  5. Send another message. The composer moves up.
  6. Send further messages. The composer moves up again each time.

Measurements

Taken in the Claude Desktop DevTools console (Help > Troubleshooting > Enable Developer
Mode, then Ctrl+Shift+I), with the unmodified debug-server app fullscreen:

(() => {
  const c = document.querySelector('[data-chat-input-container]');
  const s = c?.closest('[data-autoscroll-container]');
  return {
    composerGap: Math.round(innerHeight - c.getBoundingClientRect().bottom),
    scrollTop: Math.round(s?.scrollTop ?? -1),
    scrollHeight: Math.round(s?.scrollHeight ?? -1),
    clientHeight: Math.round(s?.clientHeight ?? -1),
  };
})()

composerGap is the distance from the bottom of the window to the bottom of the
composer. When the composer is correctly placed, it is 0.

Sample composerGap scrollTop scrollHeight clientHeight
Messages sent, app untouched 0 837 2735 1522
Messages sent, app untouched 0 2580 4103 1522
Messages sent, app untouched 0 2984 4507 1522
After clicking in the app, then sending 941 4278 5912 1522

The first three samples show that scroll depth alone does not displace the composer:
scrollTop more than triples while composerGap stays at 0. The fourth sample differs
from them by one action, a click inside the app's iframe.

The accumulation, sampled every 500ms

Once the app has been clicked, a timer logging composerGap, scrollTop and
document.activeElement through two further sends gives this sequence, condensed to the
points where a value changes:

Event composerGap scrollTop activeElement
Start of recording, app already clicked once 1193 4666 DIV[chat-input]
Click inside the app, held for about 10s 1193 4666 IFRAME
Focus returns to the composer 1193 4666 DIV[chat-input]
Send a message 1380 5041 DIV[chat-input]
Send a message 1569 5418 DIV[chat-input]

Two things follow from that sequence.

The displacement advances only when a message is sent, not when the app is clicked.
composerGap is unchanged across the whole period when activeElement is the app's
iframe, and both increases happen while focus is on the composer.

Each increase is close to half the scroll height the message adds. The first send adds
375 to scrollTop and 187 to composerGap, and the second adds 377 and 189.

Additional observations from a second app

A separate MCP App, which presents many controls and so is clicked on constantly, shows
the displacement throughout a fullscreen session. In that app composerGap grew to
3828 in a long conversation, and in a new conversation it tracked the scroller's
scrollTop closely, measuring 281 against a scrollTop of 273.

In every sample from both apps the composer reports position: sticky, so the
displacement is not the sticky positioning being dropped. The app container reports
position: fixed, and dismissing the app changed scrollHeight by 61px, so the app's
frame is not contributing to the conversation scroller's content height.

Impact

A fullscreen MCP App becomes hard to use alongside the conversation, because any use of
the app displaces the composer and every subsequent message displaces it further. An app
with controls cannot avoid the trigger.

Leaving and re-entering fullscreen restores the composer temporarily until the next message is sent, as does switching
conversations.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the behavior with the unmodified examples/debug-server packaged as a .mcpb in Claude Desktop, then use the described DevTools measurements to compare composerGap and scroll state before and after an iframe click. Done means identifying a repository-side path to address the host-side displacement, or confirming that no fix can be made here.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
desktop, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.