@nowline/mcp 0.8.3 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/ui/entry.ts CHANGED
@@ -25,7 +25,7 @@
25
25
  declare const __MCP_VERSION__: string;
26
26
 
27
27
  import { App } from '@modelcontextprotocol/ext-apps';
28
- import { mountLivePreview } from '@nowline/preview';
28
+ import { type LivePreviewHandle, mountLivePreview } from '@nowline/preview';
29
29
  import type { NowOverride, ThemeOverride } from '@nowline/preview-shell';
30
30
  import {
31
31
  type PreviewPayload,
@@ -59,8 +59,13 @@ function toThemeOverride(theme: string | undefined): ThemeOverride {
59
59
 
60
60
  let mounted = false;
61
61
  let mountedSource: string | undefined;
62
+ let live: LivePreviewHandle | undefined;
62
63
 
63
- function mountFromPayload(payload: PreviewPayload): void {
64
+ function hostTheme(app: App): 'light' | 'dark' | undefined {
65
+ return app.getHostContext()?.theme;
66
+ }
67
+
68
+ function mountFromPayload(payload: PreviewPayload, app: App): void {
64
69
  const root = document.getElementById('nl-preview-root');
65
70
  if (!root || typeof payload.source !== 'string') {
66
71
  return;
@@ -72,11 +77,14 @@ function mountFromPayload(payload: PreviewPayload): void {
72
77
  // re-invocation on the same iframe) tears down the prior mount first.
73
78
  if (mounted) {
74
79
  if (payload.source === mountedSource) return;
80
+ live?.dispose();
81
+ live = undefined;
75
82
  (root as HTMLElement).replaceChildren();
76
83
  }
77
84
 
78
- mountLivePreview(root as HTMLElement, {
85
+ live = mountLivePreview(root as HTMLElement, {
79
86
  source: payload.source,
87
+ mode: hostTheme(app) ?? 'system',
80
88
  initialView: {
81
89
  theme: toThemeOverride(payload.theme),
82
90
  now: (payload.now ?? 'today') as NowOverride,
@@ -187,7 +195,7 @@ async function bootstrap(): Promise<void> {
187
195
  // before the server finishes rendering. Mirrors the official ext-apps examples.
188
196
  app.ontoolinput = ({ arguments: args }) => {
189
197
  const payload = parsePreviewFromArguments(args as Record<string, unknown> | undefined);
190
- if (payload) mountFromPayload(payload);
198
+ if (payload) mountFromPayload(payload, app);
191
199
  };
192
200
 
193
201
  // Authoritative path: the server-resolved lean preview payload. Reconciles the
@@ -195,11 +203,14 @@ async function bootstrap(): Promise<void> {
195
203
  app.ontoolresult = ({ content, isError }) => {
196
204
  if (isError) return;
197
205
  const payload = parsePreviewFromContent(content);
198
- if (payload) mountFromPayload(payload);
206
+ if (payload) mountFromPayload(payload, app);
199
207
  };
200
208
 
201
- // Re-report when the host changes our width / available height.
202
- app.onhostcontextchanged = () => reportHeight(app);
209
+ // Re-report when the host changes our width / available height / theme.
210
+ app.onhostcontextchanged = () => {
211
+ live?.handle.setMode(hostTheme(app) ?? 'system');
212
+ reportHeight(app);
213
+ };
203
214
 
204
215
  await app.connect();
205
216
  watchSize(app);
@@ -207,7 +218,7 @@ async function bootstrap(): Promise<void> {
207
218
 
208
219
  if (!mounted) {
209
220
  const fallback = readPayload();
210
- if (fallback) mountFromPayload(fallback);
221
+ if (fallback) mountFromPayload(fallback, app);
211
222
  }
212
223
  }
213
224