Skip to content

Commit aa89688

Browse files
committed
Add utility for using styles
1 parent 9e97bf3 commit aa89688

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed

src/app.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
4747

4848
export { PostMessageTransport } from "./message-transport";
4949
export * from "./types";
50+
export { applyHostStyles } from "./styles";
5051

5152
/**
5253
* Metadata key for associating a resource URI with a tool call.

src/react/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* ## Main Exports
1010
*
1111
* - {@link useApp} - React hook to create and connect an MCP App
12+
* - {@link useHostStyles} - React hook to apply host styles as CSS variables
1213
* - {@link useAutoResize} - React hook for manual auto-resize control (rarely needed)
1314
*
1415
* @module @modelcontextprotocol/ext-apps/react
@@ -32,3 +33,4 @@
3233
*/
3334
export * from "./useApp";
3435
export * from "./useAutoResize";
36+
export * from "./useHostStyles";

src/react/useHostStyles.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { useEffect, useRef } from "react";
2+
import { App } from "../app";
3+
import { applyHostStyles } from "../styles";
4+
import { McpUiHostContext } from "../types";
5+
6+
/**
7+
* React hook that applies host styles as CSS custom properties.
8+
*
9+
* This hook listens to host context changes and automatically applies the
10+
* `styles` CSS variables to `document.documentElement`. This allows your
11+
* app to use the host's theming values via CSS variables like
12+
* `var(--color-background-primary)`.
13+
*
14+
* The hook also applies styles from the initial host context when the app
15+
* first connects.
16+
*
17+
* @param app - The connected App instance, or null during initialization
18+
* @param initialContext - Initial host context from the connection (optional).
19+
* If provided, styles will be applied immediately on mount.
20+
*
21+
* @example Basic usage with useApp
22+
* ```tsx
23+
* import { useApp } from '@modelcontextprotocol/ext-apps/react';
24+
* import { useHostStyles } from '@modelcontextprotocol/ext-apps/react';
25+
*
26+
* function MyApp() {
27+
* const { app, isConnected } = useApp({
28+
* appInfo: { name: "MyApp", version: "1.0.0" },
29+
* capabilities: {},
30+
* });
31+
*
32+
* // Automatically apply host styles as CSS variables
33+
* useHostStyles(app);
34+
*
35+
* return (
36+
* <div style={{ background: 'var(--color-background-primary)' }}>
37+
* Hello!
38+
* </div>
39+
* );
40+
* }
41+
* ```
42+
*
43+
* @example With initial context
44+
* ```tsx
45+
* const [hostContext, setHostContext] = useState<McpUiHostContext | null>(null);
46+
*
47+
* // ... get initial context from app.connect() result
48+
*
49+
* useHostStyles(app, hostContext);
50+
* ```
51+
*
52+
* @see {@link applyHostStyles} for the underlying function
53+
* @see {@link McpUiStyles} for available CSS variables
54+
*/
55+
export function useHostStyles(
56+
app: App | null,
57+
initialContext?: McpUiHostContext | null,
58+
): void {
59+
const initialStylesApplied = useRef(false);
60+
61+
// Apply initial styles once on mount
62+
useEffect(() => {
63+
if (initialStylesApplied.current) {
64+
return;
65+
}
66+
if (initialContext?.styles) {
67+
applyHostStyles(initialContext.styles);
68+
initialStylesApplied.current = true;
69+
}
70+
}, [initialContext]);
71+
72+
// Listen for host context changes and apply updated styles
73+
useEffect(() => {
74+
if (!app) {
75+
return;
76+
}
77+
78+
app.onhostcontextchanged = (params) => {
79+
if (params.styles) {
80+
applyHostStyles(params.styles);
81+
}
82+
};
83+
}, [app]);
84+
}

src/styles.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { McpUiStyles } from "./types";
2+
3+
/**
4+
* Apply host styles as CSS custom properties on an element.
5+
*
6+
* This function takes the `styles` object from `McpUiHostContext` and sets
7+
* each CSS variable on the specified root element (defaults to `document.documentElement`).
8+
* This allows apps to use the host's theming values via CSS variables like
9+
* `var(--color-background-primary)`.
10+
*
11+
* @param styles - The styles object from `McpUiHostContext.styles`
12+
* @param root - The element to apply styles to (defaults to `document.documentElement`)
13+
*
14+
* @example Apply styles from host context
15+
* ```typescript
16+
* import { applyHostStyles } from '@modelcontextprotocol/ext-apps';
17+
*
18+
* app.onhostcontextchanged = (params) => {
19+
* if (params.styles) {
20+
* applyHostStyles(params.styles);
21+
* }
22+
* };
23+
* ```
24+
*
25+
* @example Apply to a specific element
26+
* ```typescript
27+
* const container = document.getElementById('app-root');
28+
* applyHostStyles(hostContext.styles, container);
29+
* ```
30+
*
31+
* @see {@link McpUiStyles} for the available CSS variables
32+
* @see {@link McpUiHostContext} for the full host context structure
33+
*/
34+
export function applyHostStyles(
35+
styles: McpUiStyles,
36+
root: HTMLElement = document.documentElement,
37+
): void {
38+
for (const [key, value] of Object.entries(styles)) {
39+
root.style.setProperty(key, value);
40+
}
41+
}

0 commit comments

Comments
 (0)