Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions specification/draft/apps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ interface HostContext {
};
/** Current color theme preference */
theme?: "light" | "dark";
/** CSS variables for theming. See Theming section for standardized variable names. */
styles?: Record<string, string>;
/** How the UI is currently displayed */
displayMode?: "inline" | "fullscreen" | "pip";
/** Display modes the host supports */
Expand Down Expand Up @@ -435,8 +437,6 @@ interface HostContext {
}
```

All fields are optional. Hosts SHOULD provide relevant context. Guest UIs SHOULD handle missing fields gracefully.

Example:

```json
Expand All @@ -450,13 +450,66 @@ Example:
"hostInfo": { "name": "claude-desktop", "version": "1.0.0" },
"hostContext": {
"theme": "dark",
"styles": {
"--color-background-primary": "light-dark(#ffffff, #171717)",
"--color-text-primary": "light-dark(#171717, #fafafa)",
"--font-family-sans": "system-ui, sans-serif",
...
},
"displayMode": "inline",
"viewport": { "width": 400, "height": 300 }
}
}
}
```

### Theming

Hosts can optionally pass CSS custom properties via `HostContext.styles` for visual cohesion with the host environment.

#### Current Standardized Variables

| Category | Variables |
|----------|-----------|
| Background | `--color-background-primary`, `--color-background-secondary`, `--color-background-tertiary`, `--color-background-inverted` |
| Text | `--color-text-primary`, `--color-text-secondary`, `--color-text-tertiary`, `--color-text-inverted` |
| Icons | `--color-icon-primary`, `--color-icon-secondary`, `--color-icon-tertiary`, `--color-icon-inverted` |
| Borders | `--color-border-primary`, `--color-border-secondary` |
| Accents | `--color-accent-info`, `--color-accent-danger`, `--color-accent-success`, `--color-accent-warning` |
| Font Family | `--font-family-sans` |
| Font Sizes | `--font-size-heading`, `--font-size-body`, `--font-size-caption` |
| Font Weights | `--font-weight-regular`, `--font-weight-emphasized` |
| Line Heights | `--font-leading-regular`, `--font-leading-tight` |
| Composite Styles | `--font-style-heading`, `--font-style-body`, `--font-style-body-emphasized`, `--font-style-caption`, `--font-style-caption-emphasized` |
| Border Radius | `--border-radius-small`, `--border-radius-medium`, `--border-radius-large`, `--border-radius-full` |
| Border Width | `--border-width-regular` |

#### Host Behavior

- Hosts can provide any subset of standardized variables, or not pass `styles` at all. However, passing all of the standardized properties is recommended for cohesiveness
- Hosts can use the CSS `light-dark()` function for theme-aware values

#### App Behavior

- Apps should set default fallback values for CSS variables, to account for hosts who don't pass some or all style variables. This ensures graceful degradation when hosts omit `styles` or specific variables:
```
:root {
--colorTextPrimary: #171717;
}
```
- Apps can use the `applyHostStyles` utility (or `useHostStyles` if they prefer a React hook) to easily populate the host-provided CSS variables into their style sheet
- Apps can use the `applyDocumentTheme` utility (or `useDocumentTheme` if they prefer a React hook) to easily respond to Host Context `theme` changes in a way that is compatible with the host's light/dark color variables

Example usage of standardized CSS variables:

```css
.container {
background: var(--color-background-primary);
color: var(--color-text-primary);
font: var(--font-style-body);
}
```

### MCP Apps Specific Messages

MCP Apps introduces additional JSON-RPC methods for UI-specific functionality:
Expand Down Expand Up @@ -1046,6 +1099,24 @@ This proposal synthesizes feedback from the UI CWG and MCP-UI community, host im
- **Include external URLs in MVP:** This is one of the easiest content types for servers to adopt, as it's possible to embed regular apps. However, it was deferred due to concerns around model visibility, inability to screenshot content, and review process.
- **Support multiple content types:** Deferred to maintain a lean MVP.

#### 4. Host Theming via CSS Variables

**Decision:** Provide a standardized set of CSS custom properties for visual cohesion.

**Rationale:**

- CSS variables are universal, framework-agnostic, and require no runtime
- Apps apply styles via `var(--name)` with fallbacks for graceful degradation
- Limited variable set (colors, typography, borders) ensures hosts can realistically provide all values
- Spacing intentionally excluded—layouts break when spacing varies from original design
- No UI component library—no single library works across all host environments

**Alternatives considered:**

- **Full design system:** Rejected as too prescriptive; hosts have different aesthetics
- **Inline styles in tool results:** Rejected; separating theming from data enables caching and updates
- **CSS-in-JS injection:** Rejected; framework-specific and security concerns with injected code

### Backward Compatibility

The proposal builds on the existing core protocol. There are no incompatibilities.
Expand Down
5 changes: 5 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";

export { PostMessageTransport } from "./message-transport";
export * from "./types";
export {
applyHostStyles,
getDocumentTheme,
applyDocumentTheme,
} from "./styles";

/**
* Metadata key for associating a resource URI with a tool call.
Expand Down
Loading
Loading