Skip to main content
MCP Apps SDK
import { App } from "@modelcontextprotocol/ext-apps";

Overview

onhostcontextchanged is a notification handler called whenever the host environment changes — for example, when the user toggles between light and dark themes, resizes the viewport, switches locale, or changes the display mode. Before your callback is invoked, the updated fields are automatically merged into the internal context store. This means getHostContext() already returns the latest values by the time your handler runs. The params object contains only the fields that changed, not the full context.

Signature

app.onhostcontextchanged = (params: McpUiHostContext) => void;

Parameters

params
McpUiHostContext
Partial context update containing only the fields that changed. See Core Types for the full McpUiHostContext structure. Common fields include:
theme
"light" | "dark"
The host’s current color scheme.
displayMode
string
The current display mode (e.g., "default", "fullscreen").
availableDisplayModes
string[]
Display modes the host currently supports. Use this to show or hide UI controls like a fullscreen button.
locale
string
The host’s locale (e.g., "en-US", "ja-JP").
Register handlers before calling connect() to avoid missing notifications during the initialization handshake.

Usage

Respond to theme changes

app.onhostcontextchanged = (ctx) => {
  if (ctx.theme) {
    document.body.classList.toggle("dark", ctx.theme === "dark");
  }
};

await app.connect();

Adapt to display mode and available modes

const container = document.querySelector<HTMLDivElement>("#app-container")!;
const fullscreenBtn = document.querySelector<HTMLButtonElement>("#fullscreen-btn")!;

app.onhostcontextchanged = (ctx) => {
  if (ctx.displayMode) {
    container.classList.toggle("fullscreen", ctx.displayMode === "fullscreen");
  }
  if (ctx.availableDisplayModes) {
    fullscreenBtn.style.display =
      ctx.availableDisplayModes.includes("fullscreen") ? "block" : "none";
  }
};

await app.connect();

Combine with getHostContext for full state

Since the internal context is updated before your handler runs, you can read the complete context when you need fields beyond what changed:
app.onhostcontextchanged = (ctx) => {
  if (ctx.theme || ctx.displayMode) {
    const full = app.getHostContext();
    applyLayout(full?.theme, full?.displayMode);
  }
};