
MCP Apps 主題系統詳解明暗模式自適應 CSS 變量完全參考【免費下載鏈接】ext-appsOfficial repo for spec SDK of MCP Apps protocol - standard for UIs embedded AI chatbots, served by MCP servers項目地址: https://gitcode.com/GitHub_Trending/ex/ext-apps如果你正在開發運行在 AI 聊天機器人里的MCP Apps界面主題系統是你繞不開的一課用戶切換到深色模式時你的應用必須立刻跟著變暗且無需重新加載頁面。MCP Apps 協議通過一套明暗模式自適應 CSS 變量如--color-background-primary、light-dark()函數和data-theme屬性讓宿主應用Host把自己的配色、字體、字號下發給嵌入的 App實現無縫的明暗模式切換。為什么 MCP Apps 需要一套主題系統MCP App 通常以沙箱 iframe的形式嵌入到宿主應用如 Claude 等 AI 客戶端的對話流中。你的 App 不是獨立網站而是住在別人家里——所以配色不能自己說了算宿主的品牌色、明暗偏好必須由 App 跟隨明暗模式要實時切換用戶在聊天窗口一鍵切深色你的 UI 毫秒級響應字體字號要對齊宿主有自己的字體體系App 復用后視覺才統一。MCP Apps 協議的解法是宿主把主題令牌Theme Tokens打包成一個 CSS 變量對象通過 Host Context 傳給 AppApp 把這些變量寫到根元素上CSS 里用var()引用即可。主題數據流從宿主到你的 App整個機制的核心類型定義在 src/spec.types.ts 中export type McpUiTheme light | dark;主題相關的三類數據都攜帶在McpUiHostContext宿主上下文里見 src/spec.types.ts字段類型作用themelight \| dark宿主當前的明暗偏好styles.variablesMcpUiStyles一組 CSS 變量顏色、字體、圓角、陰影styles.css.fontsstringfont-face/import字體 CSS數據流可以概括為一條鏈路宿主偏好變化時比如用戶切換深色模式SDK 會觸發hostcontextchanged事件你的 App 重新應用一遍即可——無刷新、毫秒級。快速上手3 個函數搞定明暗模式自適應SDK 在 src/styles.ts 中提供了 3 個開箱即用的函數覆蓋了 90% 的主題需求一鍵設置當前明暗主題applyDocumentTheme(dark)會同時做兩件事src/styles.ts給html設置data-themedark屬性 → 你的 CSS 可以用[data-themedark]選擇器設置color-scheme屬性 →light-dark()函數和原生控件滾動條、下拉框自動適配。getDocumentTheme()則負責讀取當前主題且兼容 Tailwind 的classdark約定src/styles.ts。一鍵注入宿主 CSS 變量applyHostStyleVariables(ctx.styles.variables)把宿主下發的每個變量逐個寫到根元素上src/styles.ts。之后你的樣式表就能這樣寫body { background-color: var(--color-background-primary); color: var(--color-text-primary); } .card { border: 1px solid var(--color-border-primary); border-radius: var(--border-radius-md); box-shadow: var(--shadow-sm); }一鍵加載宿主字體applyHostFonts(css)把宿主提供的字體 CSS 注入為style標簽且保證只注入一次src/styles.ts。完整的連接后應用 變化時重新應用寫法可直接參考官方模式文檔 docs/patterns.mdfunction applyHostContext(ctx: McpUiHostContext) { if (ctx.theme) applyDocumentTheme(ctx.theme); if (ctx.styles?.variables) applyHostStyleVariables(ctx.styles.styles?.variables ?? ctx.styles.variables); if (ctx.styles?.css?.fonts) applyHostFonts(ctx.styles.css.fonts); } app.onhostcontextchanged applyHostContext; app.connect().then(() { const ctx app.getHostContext(); if (ctx) applyHostContext(ctx); });CSS 變量完整清單顏色、字體、圓角、陰影協議為宿主可下發的變量定義了完整清單McpUiStyleVariableKeysrc/spec.types.ts所有變量均為可選——宿主可以只下發子集。分類速查如下顏色類共 5 組語義色分組變量前綴典型成員用途背景色--color-background-*primary / secondary / tertiary / inverse / ghost / info / danger / success / warning / disabled頁面、卡片、狀態提示背景文本色--color-text-*同上正文、輔助文字、狀態文字邊框色--color-border-*同上分割線、卡片描邊聚焦環--color-ring-*primary / inverse / info / danger…輸入框 focus 光圈狀態語義info / danger / success / warning各分組內均含提示、報錯、成功、警告字體與排版類變量示例值說明--font-sans/--font-monosystem-ui, sans-serif正文字體 / 等寬字體族--font-weight-normal ~ bold400 / 500 / 600 / 700四級字重--font-text-{xs,sm,md,lg}-size0.75rem ~ 1.125rem正文四檔字號--font-heading-{xs ~ 3xl}-size0.75rem ~ 2.25rem標題七檔字號--font-*-line-height1.1 ~ 1.5對應字號的行高尺寸與效果類變量說明--border-radius-{xs,sm,md,lg,xl,full}2px → 9999px 六級圓角--border-width-regular常規邊框寬度1px--shadow-{hairline,sm,md,lg}從發絲線陰影到大投影官方示例中的完整取值可參考 examples/basic-host/src/host-styles.ts。明暗模式自適應的三種寫法由淺入深寫法一data-theme屬性選擇器最直白的方式自己為每個顏色寫兩套[data-themelight] { --bg-color: #ffffff; } [data-themedark] { --bg-color: #1a1a1a; } body { background: var(--bg-color); }適合變量少、需要精確控制每個色值的場景。寫法二light-dark()函數推薦現代瀏覽器的 CSS 函數一份變量同時聲明亮色和暗色值瀏覽器根據color-scheme自動選邊。SDK 的applyDocumentTheme正是為此服務——它同時設置了color-scheme讓light-dark()立即生效。官方宿主示例就是這樣定義全部配色的examples/basic-host/src/host-styles.ts--color-background-primary: light-dark(#ffffff, #1a1a1a); /* 亮色值, 暗色值 */ --color-text-primary: light-dark(#1f2937, #f3f4f6); --color-ring-danger: light-dark(#dc2626, #ef4444);這是 MCP Apps 推薦的聲明式方案宿主只需一份變量表就能同時覆蓋明暗兩套 UI。寫法三JS 監聽主題變化做條件渲染當某些邏輯而不只是 CSS依賴主題時用 React HookuseDocumentTheme()即可響應式拿到light | dark它內部用MutationObserver監聽根元素的data-theme屬性變化主題一變組件自動重渲染src/react/useDocumentTheme.ts。function ThemedButton() { const theme useDocumentTheme(); return button style{{ background: theme dark ? #333 : #fff }}點擊我/button; }React 項目一個 Hook 全自動應用主題如果你用 React 寫 MCP Appsrc/react/useHostStyles.ts 提供了三檔 HookHook職責useHostStyleVariables應用styles.variablestheme含color-scheme保證light-dark()生效useHostFonts應用styles.css.fonts字體 CSSuseHostStyles上面兩者的合體通常只需這一個function MyApp() { const { app } useApp({ appInfo: { name: MyApp, version: 1.0.0 }, capabilities: {}, }); // 一個 Hook變量 主題 字體全部自動應用 useHostStyles(app, app?.getHostContext()); return ( div style{{ background: var(--color-background-primary) }} 跟隨宿主主題明暗秒切換 /div ); }兩個細節幫你避坑傳第二個參數app?.getHostContext()連接完成時的初始主題/變量會在掛載瞬間就應用避免白屏閃爍一幀亮色再變暗Hook 同時監聽hostcontextchanged事件宿主后續切主題時自動重新應用卸載時自動解綁。配套示例src/react/useHostStyles.examples.tsx、src/react/useDocumentTheme.examples.tsx。宿主視角如何為 App 提供主題如果你是寫宿主應用Host而非 App主題管理同樣有現成參考——官方 basic-host 示例的 examples/basic-host/src/theme.ts 實現了一個迷你主題管理器初始化用window.matchMedia((prefers-color-scheme: dark))讀取系統明暗偏好作為初始值應用document.documentElement.setAttribute(data-theme, theme)colorScheme theme響應系統切換監聽prefers-color-scheme的change事件自動跟隨操作系統通知 App主題變化后經 Host Context 下發觸發 App 側的hostcontextchanged。再搭配一份light-dark()變量表examples/basic-host/src/host-styles.ts宿主與 App 就完成了雙向適配。最佳實踐清單?優先使用宿主下發的變量var(--color-*)而不是硬編碼色值宿主沒下發的變量再寫默認值兜底var(--font-sans, system-ui, sans-serif)?聲明式雙主題用light-dark()它比手寫兩套[data-theme]選擇器更省一半代碼?記得設置color-schemeSDK 已幫你做否則原生滾動條、表單控件在暗色下會是刺眼的白色?React 項目直接用useHostStyles(app, app?.getHostContext())別手動管理addEventListener/removeEventListener??所有變量都是可選的Recordkey, string | undefined寫 CSS 時給var()提供 fallback?? 主題只可能是light | dark二值協議未定義第三態不要依賴跟隨系統這種中間值。總結MCP Apps 的主題系統 McpUiTheme二值主題 語義化 CSS 變量表 light-dark()自適應宿主通過McpUiHostContext下發theme與styles.variablesApp 用 src/styles.ts 三個函數React 用useHostStyles把它們落到根元素你的 CSS 全部引用var(--color-xxx)明暗切換自動完成、零刷新。想繼續深入建議按順序閱讀協議規范 specification/2026-01-26/apps.mdx、模式手冊 docs/patterns.md、可運行示例 examples/basic-server-react/ 與 examples/basic-host/。【免費下載鏈接】ext-appsOfficial repo for spec SDK of MCP Apps protocol - standard for UIs embedded AI chatbots, served by MCP servers項目地址: https://gitcode.com/GitHub_Trending/ex/ext-apps創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考