@@ -672,13 +672,15 @@ def generate_sync():
672672<head>
673673 <meta charset="UTF-8">
674674 <meta name="viewport" content="width=device-width, initial-scale=1.0">
675+ <meta name="color-scheme" content="light dark">
675676 <title>Say View</title>
676677 <script src="https://unpkg.com/@babel/standalone@7.26.10/babel.min.js"></script>
677678 <script type="importmap">
678679 {
679680 "imports": {
680681 "react": "https://esm.sh/react@19.2.0",
681682 "react-dom/client": "https://esm.sh/react-dom@19.2.0/client",
683+ "@modelcontextprotocol/ext-apps": "https://esm.sh/@modelcontextprotocol/ext-apps@0.4.1?deps=zod@3.25.1&external=react,react-dom",
682684 "@modelcontextprotocol/ext-apps/react": "https://esm.sh/@modelcontextprotocol/ext-apps@0.4.1/react?deps=zod@3.25.1&external=react,react-dom"
683685 }
684686 }
@@ -769,8 +771,14 @@ def generate_sync():
769771 .infoPopup a:hover { text-decoration: underline; }
770772 .infoPopup ul { margin: 0; padding-left: 16px; }
771773 .infoPopup li { margin: 4px 0; }
774+ /* Dark mode: host-provided theme via data-theme attribute */
775+ [data-theme="dark"] {
776+ --color-text-primary: #eee;
777+ --color-text-secondary: #666;
778+ }
779+ /* Fallback: system preference when running standalone without host */
772780 @media (prefers-color-scheme: dark) {
773- :root {
781+ :root:not([data-theme]) {
774782 --color-text-primary: #eee;
775783 --color-text-secondary: #666;
776784 }
@@ -783,6 +791,7 @@ def generate_sync():
783791 import React, { useState, useCallback, useEffect, useRef, StrictMode } from 'react';
784792 import { createRoot } from 'react-dom/client';
785793 import { useApp } from '@modelcontextprotocol/ext-apps/react';
794+ import { applyDocumentTheme, applyHostStyleVariables, applyHostFonts } from '@modelcontextprotocol/ext-apps';
786795
787796 function SayView() {
788797 const [hostContext, setHostContext] = useState(undefined);
@@ -1251,6 +1260,16 @@ def generate_sync():
12511260 if (params.displayMode) {
12521261 setDisplayMode(params.displayMode);
12531262 }
1263+ // Apply host theme and styles
1264+ if (params.theme) {
1265+ applyDocumentTheme(params.theme);
1266+ }
1267+ if (params.styles?.variables) {
1268+ applyHostStyleVariables(params.styles.variables);
1269+ }
1270+ if (params.styles?.css?.fonts) {
1271+ applyHostFonts(params.styles.css.fonts);
1272+ }
12541273 };
12551274 },
12561275 });
@@ -1265,6 +1284,16 @@ def generate_sync():
12651284 if (ctx?.displayMode) {
12661285 setDisplayMode(ctx.displayMode);
12671286 }
1287+ // Apply initial host theme and styles
1288+ if (ctx?.theme) {
1289+ applyDocumentTheme(ctx.theme);
1290+ }
1291+ if (ctx?.styles?.variables) {
1292+ applyHostStyleVariables(ctx.styles.variables);
1293+ }
1294+ if (ctx?.styles?.css?.fonts) {
1295+ applyHostFonts(ctx.styles.css.fonts);
1296+ }
12681297 }, [app]);
12691298
12701299 // Speak lock: coordinate with other TTS Views
0 commit comments