Skip to content

autoResize: true default causes layout bugs — need height management guidance #502

Description

@psylch

Problem

autoResize: true is the default in the Apps SDK, and it is the #1 source of layout bugs for MCP App developers. We hit this issue four separate times during development of our Mermaid MCP App, each with a different root cause:

#Root CauseSymptom
1height: 100vh + autoResize: trueInfinite growth feedback loop: height reported → host adjusts → taller → report again → ∞
2autoResize: true overriding explicit fixed heightSet height: 500px in CSS, but autoResize kept reporting content height instead
3Fullscreen exit with stale hostHeightAfter exiting fullscreen, height stayed at ~900px (the fullscreen value)
4useApp() hook ignores autoResize: falseuseApp() internally creates App with autoResize: true always — the option is not exposed in UseAppOptions (removed in v1.0.1). Even @ts-expect-error workarounds don't work at runtime.

Issue #4 is particularly painful

The recommended useApp() hook cannot be used by any App that needs height control. Developers must drop down to manual new App() construction:

// Cannot use useApp() — it forces autoResize: trueconstapp=newApp({name: "my-app",version: "0.1.0"},{},{autoResize: false}// only available via manual construction);

Proposals

1. Change autoResize default to false

Most MCP Apps with non-trivial UI (diagrams, editors, canvases) need to control their own height. autoResize: true is only appropriate for simple content-driven displays. Making it opt-in would prevent the most common class of layout bugs.

2. Expose autoResize in useApp() hook

// Currently impossible — useApp() doesn't accept autoResize optionconstapp=useApp({autoResize: false});

3. Document the three height strategies

The SDK should document these patterns explicitly:

StrategyWhen to useImplementation
Fixed height (recommended default)Most AppsautoResize: false + height: 500px + manual sendSizeChanged()
Content-driven with capSimple display AppsautoResize: true + CSS max-height
Full viewportFullscreen onlyrequestDisplayMode("fullscreen") + height: 100vh

With explicit warning: 100vh + autoResize: true = infinite growth loop.

4. Improve fullscreen ↔ inline transitions

When displayMode changes from fullscreen to inline, the host should re-send containerDimensions with inline-mode values. Currently the App must remember its pre-fullscreen height and manually reset — which is error-prone.

An onDisplayModeChanged callback that includes the new dimensions would solve this cleanly:

app.ondisplaymodechanged=({ mode, containerDimensions })=>{// mode: "inline" | "fullscreen"// containerDimensions: the dimensions for the new mode};

Recommended pattern (for docs)

constDEFAULT_HEIGHT=500;// Do NOT use useApp() — it forces autoResize: trueconstapp=newApp({name: "my-app",version: "0.1.0"},{},{autoResize: false});// Register handlers BEFORE connectapp.ontoolinput=(params)=>{/* ... */};app.onhostcontextchanged=(ctx)=>{constdims=ctx.containerDimensions;if(dims?.height)hostHeight=dims.height;elseif(dims?.maxHeight)hostHeight=Math.min(DEFAULT_HEIGHT,dims.maxHeight);elsehostHeight=DEFAULT_HEIGHT;};awaitapp.connect(transport);// Report initial size (host doesn't know without autoResize)app.sendSizeChanged({width: document.documentElement.scrollWidth,height: DEFAULT_HEIGHT,});

Context

From building 3 production MCP Apps (Mermaid, PlantUML, Music). Height management consumed more debugging time than any other single issue. Every MCP App developer will hit some variant of these bugs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions