From def96b392aa7ed0cac5ec3c5d8300180e5aa3fcb Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Sun, 25 Jan 2026 13:38:22 -0600 Subject: [PATCH] Fix `onhostcontextchanged` handler invocation in examples `App.onhostcontextchanged` is a setter-only property with no getter. TypeScript doesn't prevent reading from setter-only properties, so `app.onhostcontextchanged?.(ctx)` compiles but silently returns `undefined` at runtime. Extract the handler into a named `handleHostContextChanged()` function and call it directly after `connect()`, matching the pattern used in `basic-server-vanillajs` and other examples. Co-Authored-By: Claude Opus 4.5 --- examples/sheet-music-server/src/mcp-app.ts | 20 +++++++++++--------- examples/transcript-server/src/mcp-app.ts | 8 +++++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/examples/sheet-music-server/src/mcp-app.ts b/examples/sheet-music-server/src/mcp-app.ts index 04fd16e..48b44ca 100644 --- a/examples/sheet-music-server/src/mcp-app.ts +++ b/examples/sheet-music-server/src/mcp-app.ts @@ -1,7 +1,7 @@ /** * @file Sheet Music App - renders ABC notation with abcjs and provides audio playback */ -import { App } from "@modelcontextprotocol/ext-apps"; +import { App, type McpUiHostContext } from "@modelcontextprotocol/ext-apps"; import ABCJS from "abcjs"; import "abcjs/abcjs-audio.css"; import "./global.css"; @@ -109,18 +109,20 @@ app.ontoolinput = (params) => { app.onerror = console.error; -app.onhostcontextchanged = (params) => { - if (params.safeAreaInsets) { - mainEl.style.paddingTop = `${params.safeAreaInsets.top}px`; - mainEl.style.paddingRight = `${params.safeAreaInsets.right}px`; - mainEl.style.paddingBottom = `${params.safeAreaInsets.bottom}px`; - mainEl.style.paddingLeft = `${params.safeAreaInsets.left}px`; +function handleHostContextChanged(ctx: McpUiHostContext) { + if (ctx.safeAreaInsets) { + mainEl.style.paddingTop = `${ctx.safeAreaInsets.top}px`; + mainEl.style.paddingRight = `${ctx.safeAreaInsets.right}px`; + mainEl.style.paddingBottom = `${ctx.safeAreaInsets.bottom}px`; + mainEl.style.paddingLeft = `${ctx.safeAreaInsets.left}px`; } -}; +} + +app.onhostcontextchanged = handleHostContextChanged; app.connect().then(() => { const ctx = app.getHostContext(); if (ctx) { - app.onhostcontextchanged(ctx); + handleHostContextChanged(ctx); } }); diff --git a/examples/transcript-server/src/mcp-app.ts b/examples/transcript-server/src/mcp-app.ts index 61adc7b..7e3787e 100644 --- a/examples/transcript-server/src/mcp-app.ts +++ b/examples/transcript-server/src/mcp-app.ts @@ -68,7 +68,7 @@ app.onteardown = async () => { app.onerror = log.error; -app.onhostcontextchanged = (ctx: McpUiHostContext) => { +function handleHostContextChanged(ctx: McpUiHostContext) { if (ctx.safeAreaInsets) { mainEl.style.paddingTop = `${ctx.safeAreaInsets.top}px`; mainEl.style.paddingRight = `${ctx.safeAreaInsets.right}px`; @@ -78,7 +78,9 @@ app.onhostcontextchanged = (ctx: McpUiHostContext) => { if (ctx.theme) { applyDocumentTheme(ctx.theme); } -}; +} + +app.onhostcontextchanged = handleHostContextChanged; // ============================================================================ // Audio Capture @@ -546,6 +548,6 @@ app.connect().then(() => { log.info("Connected to host"); const ctx = app.getHostContext(); if (ctx) { - app.onhostcontextchanged?.(ctx); + handleHostContextChanged(ctx); } });