@mcp-web/app 0.1.0

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.
@@ -0,0 +1,116 @@
1
+ /**
2
+ * React hook to receive props from the MCP host via the ext-apps protocol.
3
+ *
4
+ * This hook connects to the host (e.g., Claude Desktop) using the
5
+ * `@modelcontextprotocol/ext-apps` JSON-RPC protocol. It listens for
6
+ * `tool-result` notifications, which contain the props returned by the
7
+ * tool handler as JSON in `content[0].text`.
8
+ *
9
+ * Must be called within an `MCPAppProvider` (set up automatically
10
+ * by `renderMCPApp`).
11
+ *
12
+ * @template T - The type of props expected from the handler
13
+ * @returns The props object, or null if not yet received
14
+ *
15
+ * @example Basic Usage
16
+ * ```tsx
17
+ * import { useMCPAppProps } from '@mcp-web/app';
18
+ *
19
+ * interface MyAppProps {
20
+ * title: string;
21
+ * data: number[];
22
+ * }
23
+ *
24
+ * function MyApp() {
25
+ * const props = useMCPAppProps<MyAppProps>();
26
+ *
27
+ * if (!props) {
28
+ * return <div>Waiting for data...</div>;
29
+ * }
30
+ *
31
+ * return (
32
+ * <div>
33
+ * <h1>{props.title}</h1>
34
+ * <ul>
35
+ * {props.data.map((item, i) => (
36
+ * <li key={i}>{item}</li>
37
+ * ))}
38
+ * </ul>
39
+ * </div>
40
+ * );
41
+ * }
42
+ * ```
43
+ *
44
+ * @example With Default Props for Development
45
+ * ```tsx
46
+ * function MyApp() {
47
+ * const props = useMCPAppProps<MyAppProps>() ?? {
48
+ * title: 'Development Preview',
49
+ * data: [1, 2, 3],
50
+ * };
51
+ *
52
+ * return <div>{props.title}</div>;
53
+ * }
54
+ * ```
55
+ */
56
+ export declare function useMCPAppProps<T>(): T | null;
57
+ /**
58
+ * Get the ext-apps `App` instance for advanced use cases.
59
+ *
60
+ * This hook provides access to the underlying `App` class from
61
+ * `@modelcontextprotocol/ext-apps`, enabling bidirectional communication
62
+ * with the host (e.g., calling server tools, sending messages).
63
+ *
64
+ * Must be called within an `MCPAppProvider` (set up automatically
65
+ * by `renderMCPApp`).
66
+ *
67
+ * @returns The App state including app instance, connection status, and errors
68
+ *
69
+ * @example Calling a server tool from the app
70
+ * ```tsx
71
+ * import { useMCPApp } from '@mcp-web/app';
72
+ *
73
+ * function MyApp() {
74
+ * const { app, isConnected } = useMCPApp();
75
+ *
76
+ * const handleClick = async () => {
77
+ * if (app) {
78
+ * const result = await app.callServerTool({
79
+ * name: 'update_data',
80
+ * arguments: { key: 'value' },
81
+ * });
82
+ * console.log('Server tool result:', result);
83
+ * }
84
+ * };
85
+ *
86
+ * return <button onClick={handleClick}>Update</button>;
87
+ * }
88
+ * ```
89
+ */
90
+ export declare function useMCPApp(): {
91
+ app: import("@modelcontextprotocol/ext-apps").App | null;
92
+ isConnected: boolean;
93
+ error: Error | null;
94
+ };
95
+ /**
96
+ * Get current MCP App props synchronously.
97
+ *
98
+ * @deprecated Use `useMCPAppProps` hook instead. This function is maintained
99
+ * for backward compatibility but does not work with the ext-apps protocol.
100
+ *
101
+ * @template T - The type of props expected
102
+ * @returns null (ext-apps protocol is async-only)
103
+ */
104
+ export declare function getMCPAppProps<T>(): T | null;
105
+ /**
106
+ * Subscribe to MCP App props changes.
107
+ *
108
+ * @deprecated Use `useMCPAppProps` hook instead. This function is maintained
109
+ * for backward compatibility but does not work with the ext-apps protocol.
110
+ *
111
+ * @template T - The type of props expected
112
+ * @param _listener - Function called when props are received or updated
113
+ * @returns No-op unsubscribe function
114
+ */
115
+ export declare function subscribeMCPAppProps<T>(_listener: (props: T) => void): () => void;
116
+ //# sourceMappingURL=use-mcp-app-props.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mcp-app-props.d.ts","sourceRoot":"","sources":["../src/use-mcp-app-props.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAgB,cAAc,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,CAwC5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,SAAS;;;;EAGxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,CAE5C;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAC5B,MAAM,IAAI,CAEZ"}
@@ -0,0 +1,158 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useMCPAppContext } from './mcp-app-context.js';
3
+ /**
4
+ * React hook to receive props from the MCP host via the ext-apps protocol.
5
+ *
6
+ * This hook connects to the host (e.g., Claude Desktop) using the
7
+ * `@modelcontextprotocol/ext-apps` JSON-RPC protocol. It listens for
8
+ * `tool-result` notifications, which contain the props returned by the
9
+ * tool handler as JSON in `content[0].text`.
10
+ *
11
+ * Must be called within an `MCPAppProvider` (set up automatically
12
+ * by `renderMCPApp`).
13
+ *
14
+ * @template T - The type of props expected from the handler
15
+ * @returns The props object, or null if not yet received
16
+ *
17
+ * @example Basic Usage
18
+ * ```tsx
19
+ * import { useMCPAppProps } from '@mcp-web/app';
20
+ *
21
+ * interface MyAppProps {
22
+ * title: string;
23
+ * data: number[];
24
+ * }
25
+ *
26
+ * function MyApp() {
27
+ * const props = useMCPAppProps<MyAppProps>();
28
+ *
29
+ * if (!props) {
30
+ * return <div>Waiting for data...</div>;
31
+ * }
32
+ *
33
+ * return (
34
+ * <div>
35
+ * <h1>{props.title}</h1>
36
+ * <ul>
37
+ * {props.data.map((item, i) => (
38
+ * <li key={i}>{item}</li>
39
+ * ))}
40
+ * </ul>
41
+ * </div>
42
+ * );
43
+ * }
44
+ * ```
45
+ *
46
+ * @example With Default Props for Development
47
+ * ```tsx
48
+ * function MyApp() {
49
+ * const props = useMCPAppProps<MyAppProps>() ?? {
50
+ * title: 'Development Preview',
51
+ * data: [1, 2, 3],
52
+ * };
53
+ *
54
+ * return <div>{props.title}</div>;
55
+ * }
56
+ * ```
57
+ */
58
+ export function useMCPAppProps() {
59
+ const [props, setProps] = useState(null);
60
+ const { app } = useMCPAppContext();
61
+ useEffect(() => {
62
+ if (!app)
63
+ return;
64
+ // Listen for tool result - this is where our props come from.
65
+ // The tool handler returns props which the bridge wraps into
66
+ // CallToolResult.content[0].text as JSON.
67
+ app.ontoolresult = async (result) => {
68
+ if (result?.content) {
69
+ for (const block of result.content) {
70
+ if (block.type === 'text' && typeof block.text === 'string') {
71
+ try {
72
+ const parsed = JSON.parse(block.text);
73
+ setProps(parsed);
74
+ }
75
+ catch {
76
+ // If JSON parsing fails, treat the text as-is
77
+ setProps(block.text);
78
+ }
79
+ return;
80
+ }
81
+ }
82
+ }
83
+ };
84
+ // Also listen for tool input - useful for apps that need
85
+ // the raw tool call arguments
86
+ app.ontoolinput = async (input) => {
87
+ // If we have arguments and no result yet, use them as initial props.
88
+ // This enables apps to render immediately with the tool input
89
+ // before the full result arrives.
90
+ if (input?.arguments) {
91
+ setProps((prev) => prev ?? input.arguments);
92
+ }
93
+ };
94
+ }, [app]);
95
+ return props;
96
+ }
97
+ /**
98
+ * Get the ext-apps `App` instance for advanced use cases.
99
+ *
100
+ * This hook provides access to the underlying `App` class from
101
+ * `@modelcontextprotocol/ext-apps`, enabling bidirectional communication
102
+ * with the host (e.g., calling server tools, sending messages).
103
+ *
104
+ * Must be called within an `MCPAppProvider` (set up automatically
105
+ * by `renderMCPApp`).
106
+ *
107
+ * @returns The App state including app instance, connection status, and errors
108
+ *
109
+ * @example Calling a server tool from the app
110
+ * ```tsx
111
+ * import { useMCPApp } from '@mcp-web/app';
112
+ *
113
+ * function MyApp() {
114
+ * const { app, isConnected } = useMCPApp();
115
+ *
116
+ * const handleClick = async () => {
117
+ * if (app) {
118
+ * const result = await app.callServerTool({
119
+ * name: 'update_data',
120
+ * arguments: { key: 'value' },
121
+ * });
122
+ * console.log('Server tool result:', result);
123
+ * }
124
+ * };
125
+ *
126
+ * return <button onClick={handleClick}>Update</button>;
127
+ * }
128
+ * ```
129
+ */
130
+ export function useMCPApp() {
131
+ const { app, isConnected, error } = useMCPAppContext();
132
+ return { app, isConnected, error };
133
+ }
134
+ /**
135
+ * Get current MCP App props synchronously.
136
+ *
137
+ * @deprecated Use `useMCPAppProps` hook instead. This function is maintained
138
+ * for backward compatibility but does not work with the ext-apps protocol.
139
+ *
140
+ * @template T - The type of props expected
141
+ * @returns null (ext-apps protocol is async-only)
142
+ */
143
+ export function getMCPAppProps() {
144
+ return null;
145
+ }
146
+ /**
147
+ * Subscribe to MCP App props changes.
148
+ *
149
+ * @deprecated Use `useMCPAppProps` hook instead. This function is maintained
150
+ * for backward compatibility but does not work with the ext-apps protocol.
151
+ *
152
+ * @template T - The type of props expected
153
+ * @param _listener - Function called when props are received or updated
154
+ * @returns No-op unsubscribe function
155
+ */
156
+ export function subscribeMCPAppProps(_listener) {
157
+ return () => { };
158
+ }
@@ -0,0 +1,123 @@
1
+ import type { UserConfig, UserConfigExport } from 'vite';
2
+ /**
3
+ * MCP-specific options for building MCP Apps.
4
+ *
5
+ * These options control how app definitions are discovered and where
6
+ * the bundled HTML files are output.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * defineMCPAppsConfig(
11
+ * { plugins: [react()] },
12
+ * {
13
+ * appsConfig: 'src/mcp-apps.ts',
14
+ * outDir: 'dist/apps',
15
+ * silenceOverrideWarnings: true,
16
+ * }
17
+ * );
18
+ * ```
19
+ */
20
+ export interface MCPAppOptions {
21
+ /**
22
+ * Path to the apps configuration file (relative to project root).
23
+ * This file should export apps created with `createApp()`.
24
+ *
25
+ * If not specified, will search for:
26
+ * - `src/mcp-apps.ts`
27
+ * - `src/mcp-apps.tsx`
28
+ * - `src/mcp/apps.ts`
29
+ * - `src/mcp/apps.tsx`
30
+ *
31
+ * @default auto-detected
32
+ */
33
+ appsConfig?: string;
34
+ /**
35
+ * Output directory for bundled app HTML files (relative to project root).
36
+ * @default 'public/mcp-web-apps'
37
+ */
38
+ outDir?: string;
39
+ /**
40
+ * Silence warnings when MCP-required settings override user-provided values.
41
+ * @default false
42
+ */
43
+ silenceOverrideWarnings?: boolean;
44
+ }
45
+ /**
46
+ * Define a Vite configuration for building MCP Apps as single HTML files.
47
+ *
48
+ * This function creates a complete Vite config that auto-discovers app
49
+ * definitions and bundles them into self-contained HTML files. These files
50
+ * can be served as MCP App resources that render inline in AI chat interfaces.
51
+ *
52
+ * **How it works:**
53
+ * 1. Scans for a config file (`src/mcp-apps.ts` or `src/mcp/apps.ts`)
54
+ * 2. Parses `createApp()` calls to find app names and components
55
+ * 3. Auto-generates entry files that render each component
56
+ * 4. Bundles everything into single HTML files
57
+ *
58
+ * **Features:**
59
+ * - No manual entry files needed - just define your apps!
60
+ * - Full Vite config flexibility - pass any standard Vite options
61
+ * - Automatic single-file bundling (JS, CSS, assets all inlined)
62
+ * - Watch mode support for development
63
+ * - PostMessage runtime for receiving props from the host
64
+ *
65
+ * **Critical settings that are always enforced:**
66
+ * - `build.assetsInlineLimit` → Maximum (for inlining)
67
+ * - `build.cssCodeSplit` → false (single CSS bundle)
68
+ * - `base` → './' (relative paths)
69
+ *
70
+ * @param viteConfig - Standard Vite configuration options (plugins, build settings, etc.)
71
+ * @param mcpOptions - MCP-specific options (appsConfig, outDir, silenceOverrideWarnings)
72
+ * @returns A Vite UserConfigExport ready for use in vite.config.ts
73
+ *
74
+ * @example Basic Usage
75
+ * ```typescript
76
+ * // vite.apps.config.ts
77
+ * import react from '@vitejs/plugin-react';
78
+ * import { defineMCPAppsConfig } from '@mcp-web/app/vite';
79
+ *
80
+ * export default defineMCPAppsConfig({
81
+ * plugins: [react()],
82
+ * });
83
+ * ```
84
+ *
85
+ * @example With Custom Options
86
+ * ```typescript
87
+ * import react from '@vitejs/plugin-react';
88
+ * import { defineMCPAppsConfig } from '@mcp-web/app/vite';
89
+ *
90
+ * export default defineMCPAppsConfig(
91
+ * {
92
+ * plugins: [react()],
93
+ * build: {
94
+ * sourcemap: true,
95
+ * minify: 'terser',
96
+ * },
97
+ * },
98
+ * {
99
+ * appsConfig: 'src/my-apps.ts',
100
+ * outDir: 'dist/apps',
101
+ * }
102
+ * );
103
+ * ```
104
+ *
105
+ * @example Apps Config File (src/mcp-apps.ts)
106
+ * ```typescript
107
+ * import { createApp } from '@mcp-web/app';
108
+ * import { Statistics } from './components/Statistics';
109
+ *
110
+ * export const statisticsApp = createApp({
111
+ * name: 'show_statistics',
112
+ * description: 'Display statistics visualization',
113
+ * component: Statistics,
114
+ * handler: () => ({
115
+ * completionRate: 0.75,
116
+ * totalTasks: 100,
117
+ * }),
118
+ * });
119
+ * ```
120
+ */
121
+ export declare function defineMCPAppsConfig(viteConfig?: UserConfig, mcpOptions?: MCPAppOptions): UserConfigExport;
122
+ export default defineMCPAppsConfig;
123
+ //# sourceMappingURL=vite-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAU,UAAU,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAGjE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAiZD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,GAAE,UAAe,EAC3B,UAAU,GAAE,aAAkB,GAC7B,gBAAgB,CAwFlB;AAED,eAAe,mBAAmB,CAAC"}