@modelcontextprotocol/ext-apps 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/LICENSE +196 -1
  2. package/README.md +274 -25
  3. package/dist/docs/patterns.d.ts +9 -0
  4. package/dist/src/app-bridge.d.ts +253 -247
  5. package/dist/src/app-bridge.examples.d.ts +9 -0
  6. package/dist/src/app-bridge.js +17 -17
  7. package/dist/src/app-with-deps.js +9 -9
  8. package/dist/src/app.d.ts +246 -209
  9. package/dist/src/app.examples.d.ts +9 -0
  10. package/dist/src/app.js +10 -10
  11. package/dist/src/generated/schema.d.ts +45 -33
  12. package/dist/src/generated/schema.test.d.ts +1 -0
  13. package/dist/src/message-transport.d.ts +30 -32
  14. package/dist/src/message-transport.examples.d.ts +9 -0
  15. package/dist/src/react/index.d.ts +8 -10
  16. package/dist/src/react/index.examples.d.ts +6 -0
  17. package/dist/src/react/index.js +8 -8
  18. package/dist/src/react/react-with-deps.js +8 -8
  19. package/dist/src/react/useApp.d.ts +58 -44
  20. package/dist/src/react/useApp.examples.d.ts +6 -0
  21. package/dist/src/react/useAutoResize.d.ts +14 -11
  22. package/dist/src/react/useAutoResize.examples.d.ts +6 -0
  23. package/dist/src/react/useDocumentTheme.d.ts +14 -16
  24. package/dist/src/react/useDocumentTheme.examples.d.ts +6 -0
  25. package/dist/src/react/useHostStyles.d.ts +45 -53
  26. package/dist/src/react/useHostStyles.examples.d.ts +6 -0
  27. package/dist/src/server/index.d.ts +215 -41
  28. package/dist/src/server/index.examples.d.ts +9 -0
  29. package/dist/src/server/index.js +10 -10
  30. package/dist/src/spec.types.d.ts +56 -40
  31. package/dist/src/styles.d.ts +75 -32
  32. package/dist/src/styles.examples.d.ts +9 -0
  33. package/dist/src/types.d.ts +8 -7
  34. package/package.json +26 -7
@@ -2,49 +2,50 @@ import { Implementation } from "@modelcontextprotocol/sdk/types.js";
2
2
  import { App, McpUiAppCapabilities } from "../app";
3
3
  export * from "../app";
4
4
  /**
5
- * Options for configuring the useApp hook.
5
+ * Options for configuring the {@link useApp `useApp`} hook.
6
6
  *
7
- * Note: This interface does NOT expose App options like `autoResize`.
8
- * The hook creates the App with default options (autoResize: true). If you need
9
- * custom App options, create the App manually instead of using this hook.
7
+ * Note: This interface does NOT expose {@link App `App`} options like `autoResize`.
8
+ * The hook creates the `App` with default options (`autoResize: true`). If you
9
+ * need custom `App` options, create the `App` manually instead of using this hook.
10
10
  *
11
- * @see {@link useApp} for the hook that uses these options
12
- * @see {@link useAutoResize} for manual auto-resize control with custom App options
11
+ * @see {@link useApp `useApp`} for the hook that uses these options
12
+ * @see {@link useAutoResize `useAutoResize`} for manual auto-resize control with custom `App` options
13
13
  */
14
14
  export interface UseAppOptions {
15
15
  /** App identification (name and version) */
16
16
  appInfo: Implementation;
17
- /** Features and capabilities this app provides */
17
+ /**
18
+ * Declares what features this app supports.
19
+ */
18
20
  capabilities: McpUiAppCapabilities;
19
21
  /**
20
- * Called after App is created but before connection.
22
+ * Called after {@link App `App`} is created but before connection.
21
23
  *
22
24
  * Use this to register request/notification handlers that need to be in place
23
25
  * before the initialization handshake completes.
24
26
  *
25
- * @param app - The newly created App instance
27
+ * @param app - The newly created `App` instance
26
28
  *
27
- * @example Register a notification handler
28
- * ```typescript
29
- * import { McpUiToolInputNotificationSchema } from '@modelcontextprotocol/ext-apps/react';
30
- *
31
- * onAppCreated: (app) => {
32
- * app.setNotificationHandler(
33
- * McpUiToolInputNotificationSchema,
34
- * (notification) => {
35
- * console.log("Tool input:", notification.params.arguments);
36
- * }
37
- * );
38
- * }
29
+ * @example Register an event handler
30
+ * ```tsx source="./useApp.examples.tsx#useApp_registerHandler"
31
+ * useApp({
32
+ * appInfo: { name: "MyApp", version: "1.0.0" },
33
+ * capabilities: {},
34
+ * onAppCreated: (app) => {
35
+ * app.ontoolresult = (result) => {
36
+ * console.log("Tool result:", result);
37
+ * };
38
+ * },
39
+ * });
39
40
  * ```
40
41
  */
41
42
  onAppCreated?: (app: App) => void;
42
43
  }
43
44
  /**
44
- * State returned by the useApp hook.
45
+ * State returned by the {@link useApp `useApp`} hook.
45
46
  */
46
47
  export interface AppState {
47
- /** The connected App instance, null during initialization */
48
+ /** The connected {@link App `App`} instance, null during initialization */
48
49
  app: App | null;
49
50
  /** Whether initialization completed successfully */
50
51
  isConnected: boolean;
@@ -54,48 +55,61 @@ export interface AppState {
54
55
  /**
55
56
  * React hook to create and connect an MCP App.
56
57
  *
57
- * This hook manages the complete lifecycle of an {@link App}: creation, connection,
58
- * and cleanup. It automatically creates a {@link PostMessageTransport} to window.parent
59
- * and handles initialization.
58
+ * This hook manages {@link App `App`} creation and connection. It automatically
59
+ * creates a {@link PostMessageTransport `PostMessageTransport`} to window.parent and handles
60
+ * initialization.
61
+ *
62
+ * This hook is part of the optional React integration. The core SDK (`App`,
63
+ * `PostMessageTransport`) is framework-agnostic and can be used with any UI
64
+ * framework or vanilla JavaScript.
60
65
  *
61
66
  * **Important**: The hook intentionally does NOT re-run when options change
62
67
  * to avoid reconnection loops. Options are only used during the initial mount.
63
- *
64
- * **Note**: This is part of the optional React integration. The core SDK
65
- * (App, PostMessageTransport) is framework-agnostic and can be
66
- * used with any UI framework or vanilla JavaScript.
68
+ * Furthermore, the `App` instance is NOT closed on unmount. This avoids cleanup
69
+ * issues during React Strict Mode's double-mount cycle. If you need to
70
+ * explicitly close the `App`, call {@link App.close `App.close`} manually.
67
71
  *
68
72
  * @param options - Configuration for the app
69
73
  * @returns Current connection state and app instance. If connection fails during
70
74
  * initialization, the `error` field will contain the error (typically connection
71
75
  * timeouts, initialization handshake failures, or transport errors).
72
76
  *
73
- * @example Basic usage
74
- * ```typescript
75
- * import { useApp, McpUiToolInputNotificationSchema } from '@modelcontextprotocol/ext-apps/react';
76
- *
77
+ * @example Basic usage of useApp hook with common event handlers
78
+ * ```tsx source="./useApp.examples.tsx#useApp_basicUsage"
77
79
  * function MyApp() {
80
+ * const [hostContext, setHostContext] = useState<
81
+ * McpUiHostContext | undefined
82
+ * >(undefined);
83
+ *
78
84
  * const { app, isConnected, error } = useApp({
79
85
  * appInfo: { name: "MyApp", version: "1.0.0" },
80
86
  * capabilities: {},
81
87
  * onAppCreated: (app) => {
82
- * // Register handlers before connection
83
- * app.setNotificationHandler(
84
- * McpUiToolInputNotificationSchema,
85
- * (notification) => {
86
- * console.log("Tool input:", notification.params.arguments);
87
- * }
88
- * );
88
+ * app.ontoolinput = (input) => {
89
+ * console.log("Tool input:", input);
90
+ * };
91
+ * app.ontoolresult = (result) => {
92
+ * console.log("Tool result:", result);
93
+ * };
94
+ * app.ontoolcancelled = (params) => {
95
+ * console.log("Tool cancelled:", params.reason);
96
+ * };
97
+ * app.onerror = (error) => {
98
+ * console.log("Error:", error);
99
+ * };
100
+ * app.onhostcontextchanged = (params) => {
101
+ * setHostContext((prev) => ({ ...prev, ...params }));
102
+ * };
89
103
  * },
90
104
  * });
91
105
  *
92
106
  * if (error) return <div>Error: {error.message}</div>;
93
107
  * if (!isConnected) return <div>Connecting...</div>;
94
- * return <div>Connected!</div>;
108
+ * return <div>Theme: {hostContext?.theme}</div>;
95
109
  * }
96
110
  * ```
97
111
  *
98
- * @see {@link App.connect} for the underlying connection method
99
- * @see {@link useAutoResize} for manual auto-resize control when using custom App options
112
+ * @see {@link App.connect `App.connect`} for the underlying connection method
113
+ * @see {@link useAutoResize `useAutoResize`} for manual auto-resize control when using custom App options
100
114
  */
101
115
  export declare function useApp({ appInfo, capabilities, onAppCreated, }: UseAppOptions): AppState;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Type-checked examples for the useApp hook.
3
+ *
4
+ * @module
5
+ */
6
+ export {};
@@ -3,21 +3,23 @@ import { App } from "../app";
3
3
  /**
4
4
  * React hook that automatically reports UI size changes to the host.
5
5
  *
6
- * Uses ResizeObserver to watch `document.body` and `document.documentElement` for
6
+ * Uses `ResizeObserver` to watch `document.body` and `document.documentElement` for
7
7
  * size changes and sends `ui/notifications/size-changed` notifications.
8
8
  *
9
- * **Note**: This hook is rarely needed since the {@link useApp} hook automatically enables
9
+ * The hook automatically cleans up the `ResizeObserver` when the component unmounts.
10
+ *
11
+ * **Note**: This hook is rarely needed since the {@link useApp `useApp`} hook automatically enables
10
12
  * auto-resize by default. This hook is provided for advanced cases where you
11
- * create the {@link App} manually with `autoResize: false` and want to add auto-resize
13
+ * create the {@link App `App`} manually with `autoResize: false` and want to add auto-resize
12
14
  * behavior later.
13
15
  *
14
- * @param app - The connected App instance, or null during initialization
16
+ * @param app - The connected {@link App `App`} instance, or null during initialization
15
17
  * @param elementRef - Currently unused. The hook always observes `document.body`
16
18
  * and `document.documentElement` regardless of this value. Passing a ref will
17
19
  * cause unnecessary effect re-runs; omit this parameter.
18
20
  *
19
21
  * @example Manual App creation with custom auto-resize control
20
- * ```tsx
22
+ * ```tsx source="./useAutoResize.examples.tsx#useAutoResize_manualApp"
21
23
  * function MyComponent() {
22
24
  * // For custom App options, create App manually instead of using useApp
23
25
  * const [app, setApp] = useState<App | null>(null);
@@ -27,11 +29,12 @@ import { App } from "../app";
27
29
  * const myApp = new App(
28
30
  * { name: "MyApp", version: "1.0.0" },
29
31
  * {}, // capabilities
30
- * { autoResize: false } // Disable default auto-resize
32
+ * { autoResize: false }, // Disable default auto-resize
31
33
  * );
32
34
  *
33
- * const transport = new PostMessageTransport(window.parent);
34
- * myApp.connect(transport)
35
+ * const transport = new PostMessageTransport(window.parent, window.parent);
36
+ * myApp
37
+ * .connect(transport)
35
38
  * .then(() => setApp(myApp))
36
39
  * .catch((err) => setError(err));
37
40
  * }, []);
@@ -44,8 +47,8 @@ import { App } from "../app";
44
47
  * }
45
48
  * ```
46
49
  *
47
- * @see {@link App.setupSizeChangedNotifications} for the underlying implementation
48
- * @see {@link useApp} which enables auto-resize by default
49
- * @see {@link App} constructor for configuring `autoResize` option
50
+ * @see {@link App.setupSizeChangedNotifications `App.setupSizeChangedNotifications`} for the underlying implementation
51
+ * @see {@link useApp `useApp`} which enables auto-resize by default
52
+ * @see {@link App `App`} constructor for configuring `autoResize` option
50
53
  */
51
54
  export declare function useAutoResize(app: App | null, elementRef?: RefObject<HTMLElement | null>): void;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Type-checked examples for the useAutoResize hook.
3
+ *
4
+ * @module
5
+ */
6
+ export {};
@@ -2,45 +2,43 @@ import { McpUiTheme } from "../types";
2
2
  /**
3
3
  * React hook that provides the current document theme reactively.
4
4
  *
5
- * Uses a MutationObserver to watch for changes to the `data-theme` attribute
5
+ * Uses a `MutationObserver` to watch for changes to the `data-theme` attribute
6
6
  * or `class` on `document.documentElement`. When the theme changes (e.g., from
7
7
  * host context updates), the hook automatically re-renders your component with
8
8
  * the new theme value.
9
9
  *
10
+ * The `MutationObserver` is automatically disconnected when the component unmounts.
11
+ *
10
12
  * @returns The current theme ("light" or "dark")
11
13
  *
12
14
  * @example Conditionally render based on theme
13
- * ```tsx
14
- * import { useDocumentTheme } from '@modelcontextprotocol/ext-apps/react';
15
- *
15
+ * ```tsx source="./useDocumentTheme.examples.tsx#useDocumentTheme_conditionalRender"
16
16
  * function MyApp() {
17
17
  * const theme = useDocumentTheme();
18
18
  *
19
- * return (
20
- * <div>
21
- * {theme === 'dark' ? <DarkIcon /> : <LightIcon />}
22
- * </div>
23
- * );
19
+ * return <div>{theme === "dark" ? <DarkIcon /> : <LightIcon />}</div>;
24
20
  * }
25
21
  * ```
26
22
  *
27
23
  * @example Use with theme-aware styling
28
- * ```tsx
24
+ * ```tsx source="./useDocumentTheme.examples.tsx#useDocumentTheme_themedButton"
29
25
  * function ThemedButton() {
30
26
  * const theme = useDocumentTheme();
31
27
  *
32
28
  * return (
33
- * <button style={{
34
- * background: theme === 'dark' ? '#333' : '#fff',
35
- * color: theme === 'dark' ? '#fff' : '#333',
36
- * }}>
29
+ * <button
30
+ * style={{
31
+ * background: theme === "dark" ? "#333" : "#fff",
32
+ * color: theme === "dark" ? "#fff" : "#333",
33
+ * }}
34
+ * >
37
35
  * Click me
38
36
  * </button>
39
37
  * );
40
38
  * }
41
39
  * ```
42
40
  *
43
- * @see {@link getDocumentTheme} for the underlying function
44
- * @see {@link applyDocumentTheme} to set the theme
41
+ * @see {@link getDocumentTheme `getDocumentTheme`} for the underlying function
42
+ * @see {@link applyDocumentTheme `applyDocumentTheme`} to set the theme
45
43
  */
46
44
  export declare function useDocumentTheme(): McpUiTheme;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Type-checked examples for the useDocumentTheme hook.
3
+ *
4
+ * @module
5
+ */
6
+ export {};
@@ -14,45 +14,33 @@ import { McpUiHostContext } from "../types";
14
14
  * this hook ensures they work correctly by setting the `color-scheme` property
15
15
  * based on the host's theme preference.
16
16
  *
17
- * @param app - The connected App instance, or null during initialization
17
+ * @param app - The connected {@link App `App`} instance, or null during initialization
18
18
  * @param initialContext - Initial host context from the connection (optional).
19
19
  * If provided, styles and theme will be applied immediately on mount.
20
20
  *
21
- * @example Basic usage with useApp
22
- * ```tsx
23
- * import { useApp } from '@modelcontextprotocol/ext-apps/react';
24
- * import { useHostStyleVariables } from '@modelcontextprotocol/ext-apps/react';
25
- *
21
+ * @example
22
+ * ```tsx source="./useHostStyles.examples.tsx#useHostStyleVariables_basicUsage"
26
23
  * function MyApp() {
27
- * const { app, isConnected } = useApp({
24
+ * const { app } = useApp({
28
25
  * appInfo: { name: "MyApp", version: "1.0.0" },
29
26
  * capabilities: {},
30
27
  * });
31
28
  *
32
- * // Automatically apply host style variables and theme
33
- * useHostStyleVariables(app);
29
+ * // Apply host styles - pass initial context to apply styles from connect() immediately
30
+ * useHostStyleVariables(app, app?.getHostContext());
34
31
  *
35
32
  * return (
36
- * <div style={{ background: 'var(--color-background-primary)' }}>
33
+ * <div style={{ background: "var(--color-background-primary)" }}>
37
34
  * Hello!
38
35
  * </div>
39
36
  * );
40
37
  * }
41
38
  * ```
42
39
  *
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
- * useHostStyleVariables(app, hostContext);
50
- * ```
51
- *
52
- * @see {@link applyHostStyleVariables} for the underlying styles function
53
- * @see {@link applyDocumentTheme} for the underlying theme function
54
- * @see {@link useHostFonts} for applying host fonts
55
- * @see {@link McpUiStyles} for available CSS variables
40
+ * @see {@link applyHostStyleVariables `applyHostStyleVariables`} for the underlying styles function
41
+ * @see {@link applyDocumentTheme `applyDocumentTheme`} for the underlying theme function
42
+ * @see {@link useHostFonts `useHostFonts`} for applying host fonts
43
+ * @see {@link McpUiStyles `McpUiStyles`} for available CSS variables
56
44
  */
57
45
  export declare function useHostStyleVariables(app: App | null, initialContext?: McpUiHostContext | null): void;
58
46
  /**
@@ -67,55 +55,59 @@ export declare function useHostStyleVariables(app: App | null, initialContext?:
67
55
  * The hook also applies fonts from the initial host context when
68
56
  * the app first connects.
69
57
  *
70
- * @param app - The connected App instance, or null during initialization
58
+ * @param app - The connected {@link App `App`} instance, or null during initialization
71
59
  * @param initialContext - Initial host context from the connection (optional).
72
60
  * If provided, fonts will be applied immediately on mount.
73
61
  *
74
62
  * @example Basic usage with useApp
75
- * ```tsx
76
- * import { useApp } from '@modelcontextprotocol/ext-apps/react';
77
- * import { useHostFonts } from '@modelcontextprotocol/ext-apps/react';
78
- *
63
+ * ```tsx source="./useHostStyles.examples.tsx#useHostFonts_basicUsage"
79
64
  * function MyApp() {
80
- * const { app, isConnected } = useApp({
65
+ * const { app } = useApp({
81
66
  * appInfo: { name: "MyApp", version: "1.0.0" },
82
67
  * capabilities: {},
83
68
  * });
84
69
  *
85
- * // Automatically apply host fonts
86
- * useHostFonts(app);
70
+ * // Apply host fonts - pass initial context to apply fonts from connect() immediately
71
+ * useHostFonts(app, app?.getHostContext());
87
72
  *
88
- * return (
89
- * <div style={{ fontFamily: 'var(--font-sans)' }}>
90
- * Hello!
91
- * </div>
92
- * );
73
+ * return <div style={{ fontFamily: "var(--font-sans)" }}>Hello!</div>;
93
74
  * }
94
75
  * ```
95
76
  *
96
- * @example With initial context
97
- * ```tsx
98
- * const [hostContext, setHostContext] = useState<McpUiHostContext | null>(null);
99
- *
100
- * // ... get initial context from app.connect() result
101
- *
102
- * useHostFonts(app, hostContext);
103
- * ```
104
- *
105
- * @see {@link applyHostFonts} for the underlying fonts function
106
- * @see {@link useHostStyleVariables} for applying style variables and theme
77
+ * @see {@link applyHostFonts `applyHostFonts`} for the underlying fonts function
78
+ * @see {@link useHostStyleVariables `useHostStyleVariables`} for applying style variables and theme
107
79
  */
108
80
  export declare function useHostFonts(app: App | null, initialContext?: McpUiHostContext | null): void;
109
81
  /**
110
- * React hook that applies host styles, fonts, and theme.
82
+ * Applies all host styling (CSS variables, theme, and fonts) to match the host application.
111
83
  *
112
- * This is a convenience hook that combines {@link useHostStyleVariables} and
113
- * {@link useHostFonts}. Use the individual hooks if you need more control.
84
+ * This is a convenience hook that combines {@link useHostStyleVariables `useHostStyleVariables`} and
85
+ * {@link useHostFonts `useHostFonts`}. Use the individual hooks if you need more control.
114
86
  *
115
- * @param app - The connected App instance, or null during initialization
87
+ * @param app - The connected {@link App `App`} instance, or null during initialization
116
88
  * @param initialContext - Initial host context from the connection (optional).
89
+ * Pass `app?.getHostContext()` to apply styles immediately on mount.
90
+ *
91
+ * @example
92
+ * ```tsx source="./useHostStyles.examples.tsx#useHostStyles_basicUsage"
93
+ * function MyApp() {
94
+ * const { app } = useApp({
95
+ * appInfo: { name: "MyApp", version: "1.0.0" },
96
+ * capabilities: {},
97
+ * });
98
+ *
99
+ * // Apply all host styles - pass initial context to apply styles from connect() immediately
100
+ * useHostStyles(app, app?.getHostContext());
101
+ *
102
+ * return (
103
+ * <div style={{ background: "var(--color-background-primary)" }}>
104
+ * Hello!
105
+ * </div>
106
+ * );
107
+ * }
108
+ * ```
117
109
  *
118
- * @see {@link useHostStyleVariables} for style variables and theme only
119
- * @see {@link useHostFonts} for fonts only
110
+ * @see {@link useHostStyleVariables `useHostStyleVariables`} for style variables and theme only
111
+ * @see {@link useHostFonts `useHostFonts`} for fonts only
120
112
  */
121
113
  export declare function useHostStyles(app: App | null, initialContext?: McpUiHostContext | null): void;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Type-checked examples for the useHostStyles hooks.
3
+ *
4
+ * @module
5
+ */
6
+ export {};