Skip to content

fix(apps): declare color-scheme to allow transparent MCP App iframes#7479

Merged
aharvard merged 2 commits intomainfrom
fix/iframe-color-scheme-transparency
Feb 24, 2026
Merged

fix(apps): declare color-scheme to allow transparent MCP App iframes#7479
aharvard merged 2 commits intomainfrom
fix/iframe-color-scheme-transparency

Conversation

@aharvard
Copy link
Copy Markdown
Collaborator

@aharvard aharvard commented Feb 24, 2026

Summary

Fixes #7439

MCP App iframes that declare color-scheme: light dark and rely on transparency get an opaque backdrop (white in light mode, black in dark mode) because Goose never declared color-scheme on its own document or the sandbox proxy iframe.

Root Cause

Goose toggles dark mode via a .dark CSS class but never sets the color-scheme CSS property. When a guest app iframe declares color-scheme: light dark, the browser detects a cross-scheme mismatch between the parent document and the iframe, and per the CSS Color Adjustment spec paints an opaque canvas behind the iframe.

The iframe stack is: Goose document → sandbox proxy iframe → guest app iframe. Each boundary is a potential cross-scheme mismatch point.

Changes

Three changes, one at each layer of the iframe stack:

  1. mcp_app_proxy.html — Add <meta name="color-scheme" content="light dark"> to the sandbox proxy. This is the key fix — the proxy is a transparent relay document with no visible content, so declaring both schemes tells the browser not to paint an opaque backdrop.

  2. ThemeContext.tsx — Set document.documentElement.style.colorScheme to match the resolved theme at runtime, preventing cross-scheme mismatch at the Goose↔proxy boundary.

  3. index.html — Same colorScheme assignment in the early inline theme script so it's correct before React mounts.

modes before/after
macOS appearance: light

goose theme: system
light-system
macOS appearance: light

goose theme: light
light-light
macOS appearance: light

goose theme: dark
light-dark
macOS appearance: dark

goose theme: system
dark-system
macOS appearance: dark

goose theme: light
dark-light
macOS appearance: dark

goose theme: dark
dark-dark

Why colorScheme = theme instead of color-scheme: light dark

Setting color-scheme: light dark globally on the Goose document would tell the browser to auto-apply dark UA styles (scrollbars, form controls, default backgrounds) based on OS preference — potentially conflicting with Goose's own theme token system. By setting exactly light or dark to match the resolved theme, we stay in full control.

Testing

  • Cargo builds clean
  • TypeScript compiles clean
  • All 340 UI tests pass
  • Tested with a transparency inspector MCP App that verifies iframe transparency, color-scheme alignment, and host theme matching in both light and dark mode

Goose toggles dark mode via a CSS class but never declared color-scheme
on the document. When an MCP App iframe declares color-scheme: light dark,
the browser detects a cross-scheme mismatch and paints an opaque backdrop
behind the iframe (white in light mode, black in dark mode), making it
impossible for apps to be transparent.

Three changes at each layer of the iframe stack:

1. Sandbox proxy HTML — add <meta name="color-scheme" content="light dark">
   so the transparent relay document doesn't trigger an opaque backdrop
   regardless of the parent's or child's color scheme.

2. ThemeContext.tsx — set document.documentElement.style.colorScheme to
   match the resolved theme at runtime, preventing cross-scheme mismatch
   between Goose and the proxy iframe.

3. index.html — same colorScheme assignment in the early inline theme
   script so it's correct before React mounts.

Fixes #7439
Copilot AI review requested due to automatic review settings February 24, 2026 16:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes iframe transparency issues for MCP Apps by declaring color-scheme CSS property across all layers of the iframe stack (Goose document → sandbox proxy iframe → guest app iframe). When MCP Apps declare color-scheme: light dark and rely on transparency, they were getting an opaque backdrop due to cross-scheme mismatch between parent and child documents. The fix ensures proper color-scheme alignment at all iframe boundaries.

Changes:

  • Added color-scheme meta tag to mcp_app_proxy.html sandbox proxy to declare support for both light and dark schemes
  • Updated ThemeContext.tsx to set document.documentElement.style.colorScheme dynamically based on resolved theme
  • Updated index.html early theme initialization script to set colorScheme before React mounts

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
crates/goose-server/src/routes/templates/mcp_app_proxy.html Added color-scheme: light dark meta tag to sandbox proxy document
ui/desktop/src/contexts/ThemeContext.tsx Set colorScheme style property in applyThemeToDocument function
ui/desktop/index.html Set colorScheme in early inline theme initialization script for dark mode paths

Address Copilot review feedback — the no-localStorage and catch
fallback paths only set colorScheme when dark, leaving it undefined
in light mode which can still cause opaque iframe backdrops.
@aharvard aharvard requested a review from zanesq February 24, 2026 17:28
Copy link
Copy Markdown
Contributor

@zanesq zanesq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙏

@aharvard aharvard added this pull request to the merge queue Feb 24, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Feb 24, 2026
@aharvard aharvard added this pull request to the merge queue Feb 24, 2026
Merged via the queue into main with commit 5e59b4d Feb 24, 2026
21 checks passed
@aharvard aharvard deleted the fix/iframe-color-scheme-transparency branch February 24, 2026 18:56
zanesq added a commit that referenced this pull request Feb 25, 2026
…m-cache

* 'main' of github.com:block/goose:
  chore(release): release version 1.25.0 (minor) (#7263)
  Docs: Community all-stars and page update (#7483)
  fix: searchbar zindex modal overlay (#7502)
  blog: Order Lunch Without Leaving Your AI Agent (#7505)
  feat: gateway to chat to goose - telegram etc (#7199)
  Option to add changeable defaults in goose-releases (#7373)
  Fix out of order messages (#7472)
  fix: ensure latest session always displays in sidebar (#7489)
  docs: rename TLDR to Quick Install in MCP tutorials (#7493)
  docs: update Neighborhood extension page with video embed and layout improvements (#7473)
  feat: let AskAI Discord bot see channels in the server (#7480)
  Apps token limit (#7474)
  fix(apps): declare color-scheme to allow transparent MCP App iframes (#7479)
u35tpus pushed a commit to u35tpus/goose that referenced this pull request Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Goose prevents MCP Apps iframe from being transparent in dark mode

3 participants