@leanmcp/ui 0.2.0 → 0.3.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,138 @@
1
+ 'use strict';
2
+
3
+ require('reflect-metadata');
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var UI_APP_COMPONENT_KEY = "ui:app:component";
8
+ var UI_APP_URI_KEY = "ui:app:uri";
9
+ var UI_APP_OPTIONS_KEY = "ui:app:options";
10
+ function UIApp(options) {
11
+ return (target, propertyKey, descriptor) => {
12
+ const methodName = String(propertyKey);
13
+ const className = target.constructor.name.toLowerCase().replace("service", "");
14
+ const uri = options.uri ?? `ui://${className}/${methodName}`;
15
+ Reflect.defineMetadata(UI_APP_COMPONENT_KEY, options.component, descriptor.value);
16
+ Reflect.defineMetadata(UI_APP_URI_KEY, uri, descriptor.value);
17
+ Reflect.defineMetadata(UI_APP_OPTIONS_KEY, options, descriptor.value);
18
+ const existingMeta = Reflect.getMetadata("tool:meta", descriptor.value) || {};
19
+ Reflect.defineMetadata("tool:meta", {
20
+ ...existingMeta,
21
+ // New nested format (preferred by ext-apps 0.2.2)
22
+ ui: {
23
+ resourceUri: uri
24
+ },
25
+ // Legacy flat format (for backwards compatibility)
26
+ "ui/resourceUri": uri
27
+ }, descriptor.value);
28
+ return descriptor;
29
+ };
30
+ }
31
+ __name(UIApp, "UIApp");
32
+ function getUIAppMetadata(target) {
33
+ const component = Reflect.getMetadata(UI_APP_COMPONENT_KEY, target);
34
+ if (!component) return void 0;
35
+ return {
36
+ component,
37
+ uri: Reflect.getMetadata(UI_APP_URI_KEY, target),
38
+ ...Reflect.getMetadata(UI_APP_OPTIONS_KEY, target)
39
+ };
40
+ }
41
+ __name(getUIAppMetadata, "getUIAppMetadata");
42
+ function getUIAppUri(target) {
43
+ return Reflect.getMetadata(UI_APP_URI_KEY, target);
44
+ }
45
+ __name(getUIAppUri, "getUIAppUri");
46
+ var GPT_APP_COMPONENT_KEY = "gptapp:component";
47
+ var GPT_APP_URI_KEY = "gptapp:uri";
48
+ var GPT_APP_OPTIONS_KEY = "gptapp:options";
49
+ function GPTApp(options) {
50
+ return (target, propertyKey, descriptor) => {
51
+ const methodName = String(propertyKey);
52
+ const className = target.constructor.name.toLowerCase().replace("service", "");
53
+ const uri = options.uri ?? `ui://${className}/${methodName}`;
54
+ Reflect.defineMetadata(GPT_APP_COMPONENT_KEY, options.component, descriptor.value);
55
+ Reflect.defineMetadata(GPT_APP_URI_KEY, uri, descriptor.value);
56
+ Reflect.defineMetadata(GPT_APP_OPTIONS_KEY, options, descriptor.value);
57
+ const existingMeta = Reflect.getMetadata("tool:meta", descriptor.value) || {};
58
+ const uiMeta = {
59
+ resourceUri: uri
60
+ };
61
+ if (options.visibility) {
62
+ uiMeta.visibility = options.visibility === "private" ? [
63
+ "app"
64
+ ] : [
65
+ "model",
66
+ "app"
67
+ ];
68
+ }
69
+ const openAiMeta = {
70
+ // New nested format (preferred by ext-apps 0.2.2)
71
+ ui: uiMeta,
72
+ // Legacy flat format (for backwards compatibility)
73
+ "ui/resourceUri": uri,
74
+ "openai/outputTemplate": uri
75
+ };
76
+ if (options.widgetAccessible !== void 0) {
77
+ openAiMeta["openai/widgetAccessible"] = options.widgetAccessible;
78
+ }
79
+ if (options.visibility) {
80
+ openAiMeta["openai/visibility"] = options.visibility;
81
+ }
82
+ if (options.prefersBorder !== void 0) {
83
+ openAiMeta["openai/widgetPrefersBorder"] = options.prefersBorder;
84
+ }
85
+ if (options.widgetDomain) {
86
+ openAiMeta["openai/widgetDomain"] = options.widgetDomain;
87
+ }
88
+ if (options.widgetDescription) {
89
+ openAiMeta["openai/widgetDescription"] = options.widgetDescription;
90
+ }
91
+ if (options.csp) {
92
+ openAiMeta["openai/widgetCSP"] = options.csp;
93
+ }
94
+ if (options.fileParams) {
95
+ openAiMeta["openai/fileParams"] = options.fileParams;
96
+ }
97
+ if (options.invocation) {
98
+ if (options.invocation.invoking) openAiMeta["openai/toolInvocation/invoking"] = options.invocation.invoking;
99
+ if (options.invocation.invoked) openAiMeta["openai/toolInvocation/invoked"] = options.invocation.invoked;
100
+ }
101
+ Reflect.defineMetadata("tool:meta", {
102
+ ...existingMeta,
103
+ ...openAiMeta
104
+ }, descriptor.value);
105
+ return descriptor;
106
+ };
107
+ }
108
+ __name(GPTApp, "GPTApp");
109
+ function getGPTAppMetadata(target) {
110
+ const component = Reflect.getMetadata(GPT_APP_COMPONENT_KEY, target);
111
+ if (!component) return void 0;
112
+ return {
113
+ component,
114
+ uri: Reflect.getMetadata(GPT_APP_URI_KEY, target),
115
+ ...Reflect.getMetadata(GPT_APP_OPTIONS_KEY, target)
116
+ };
117
+ }
118
+ __name(getGPTAppMetadata, "getGPTAppMetadata");
119
+ function getGPTAppUri(target) {
120
+ return Reflect.getMetadata(GPT_APP_URI_KEY, target);
121
+ }
122
+ __name(getGPTAppUri, "getGPTAppUri");
123
+
124
+ exports.GPTApp = GPTApp;
125
+ exports.GPT_APP_COMPONENT_KEY = GPT_APP_COMPONENT_KEY;
126
+ exports.GPT_APP_OPTIONS_KEY = GPT_APP_OPTIONS_KEY;
127
+ exports.GPT_APP_URI_KEY = GPT_APP_URI_KEY;
128
+ exports.UIApp = UIApp;
129
+ exports.UI_APP_COMPONENT_KEY = UI_APP_COMPONENT_KEY;
130
+ exports.UI_APP_OPTIONS_KEY = UI_APP_OPTIONS_KEY;
131
+ exports.UI_APP_URI_KEY = UI_APP_URI_KEY;
132
+ exports.__name = __name;
133
+ exports.getGPTAppMetadata = getGPTAppMetadata;
134
+ exports.getGPTAppUri = getGPTAppUri;
135
+ exports.getUIAppMetadata = getUIAppMetadata;
136
+ exports.getUIAppUri = getUIAppUri;
137
+ //# sourceMappingURL=chunk-2HRO6CFU.js.map
138
+ //# sourceMappingURL=chunk-2HRO6CFU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/decorator/UIApp.ts","../src/decorator/GPTApp.ts"],"names":["UI_APP_COMPONENT_KEY","UI_APP_URI_KEY","UI_APP_OPTIONS_KEY","UIApp","options","target","propertyKey","descriptor","methodName","String","className","name","toLowerCase","replace","uri","Reflect","defineMetadata","component","value","existingMeta","getMetadata","ui","resourceUri","getUIAppMetadata","undefined","getUIAppUri","GPT_APP_COMPONENT_KEY","GPT_APP_URI_KEY","GPT_APP_OPTIONS_KEY","GPTApp","uiMeta","visibility","openAiMeta","widgetAccessible","prefersBorder","widgetDomain","widgetDescription","csp","fileParams","invocation","invoking","invoked","getGPTAppMetadata","getGPTAppUri"],"mappings":"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","file":"chunk-2HRO6CFU.js","sourcesContent":["/**\r\n * @UIApp Decorator\r\n * \r\n * Links an MCP tool to a React UI component.\r\n * When applied to a tool method, it:\r\n * 1. Adds _meta.ui/resourceUri to the tool definition\r\n * 2. Auto-registers a resource that renders the component to HTML\r\n * \r\n * This decorator is designed to work with @leanmcp/core decorators.\r\n */\r\nimport 'reflect-metadata';\r\nimport type React from 'react';\r\n\r\n// Metadata keys\r\nexport const UI_APP_COMPONENT_KEY = 'ui:app:component';\r\nexport const UI_APP_URI_KEY = 'ui:app:uri';\r\nexport const UI_APP_OPTIONS_KEY = 'ui:app:options';\r\n\r\n/**\r\n * Options for @UIApp decorator\r\n */\r\nexport interface UIAppOptions {\r\n /** \r\n * React component or path to component file (relative to service file).\r\n * - Use path string (e.g., './WeatherCard') for CLI build - avoids importing browser code in server\r\n * - Use component reference for direct SSR rendering\r\n */\r\n component: React.ComponentType<any> | string;\r\n /** Custom resource URI (auto-generated if not provided) */\r\n uri?: string;\r\n /** HTML document title */\r\n title?: string;\r\n /** Additional CSS styles */\r\n styles?: string;\r\n}\r\n\r\n\r\n/**\r\n * Decorator that links a tool to a UI component.\r\n * \r\n * When the tool is called, the host will fetch the UI resource\r\n * which returns the component rendered as HTML.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { Tool } from '@leanmcp/core';\r\n * import { UIApp } from '@leanmcp/ui';\r\n * import { WeatherCard } from './WeatherCard';\r\n * \r\n * class WeatherService {\r\n * @Tool({ description: 'Get weather for a city' })\r\n * @UIApp({ component: WeatherCard })\r\n * async getWeather(args: { city: string }) {\r\n * return { city: args.city, temp: 22 };\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function UIApp(options: UIAppOptions): MethodDecorator {\r\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\r\n const methodName = String(propertyKey);\r\n // Use same pattern as @Resource in @leanmcp/core: className without 'service' suffix\r\n const className = target.constructor.name.toLowerCase().replace('service', '');\r\n\r\n // Generate URI using ui:// scheme (required by ext-apps hosts)\r\n const uri = options.uri ?? `ui://${className}/${methodName}`;\r\n\r\n // Store metadata on the method\r\n Reflect.defineMetadata(UI_APP_COMPONENT_KEY, options.component, descriptor.value!);\r\n Reflect.defineMetadata(UI_APP_URI_KEY, uri, descriptor.value!);\r\n Reflect.defineMetadata(UI_APP_OPTIONS_KEY, options, descriptor.value!);\r\n\r\n // Also store the resource URI for the @Tool decorator to pick up\r\n // The @Tool decorator in @leanmcp/core should check for this\r\n const existingMeta = Reflect.getMetadata('tool:meta', descriptor.value) || {};\r\n Reflect.defineMetadata('tool:meta', {\r\n ...existingMeta,\r\n // New nested format (preferred by ext-apps 0.2.2)\r\n ui: {\r\n resourceUri: uri,\r\n },\r\n // Legacy flat format (for backwards compatibility)\r\n 'ui/resourceUri': uri,\r\n }, descriptor.value!);\r\n\r\n return descriptor;\r\n };\r\n}\r\n\r\n/**\r\n * Helper to get UIApp metadata from a method\r\n */\r\nexport function getUIAppMetadata(target: Function): UIAppOptions | undefined {\r\n const component = Reflect.getMetadata(UI_APP_COMPONENT_KEY, target);\r\n if (!component) return undefined;\r\n\r\n return {\r\n component,\r\n uri: Reflect.getMetadata(UI_APP_URI_KEY, target),\r\n ...Reflect.getMetadata(UI_APP_OPTIONS_KEY, target),\r\n };\r\n}\r\n\r\n/**\r\n * Helper to get the resource URI from a method\r\n */\r\nexport function getUIAppUri(target: Function): string | undefined {\r\n return Reflect.getMetadata(UI_APP_URI_KEY, target);\r\n}\r\n","/**\r\n * @GPTApp Decorator\r\n * \r\n * Links an MCP tool to a React UI component compliant with ChatGPT Apps SDK.\r\n * \r\n * When applied to a tool method, it:\r\n * 1. Adds _meta.ui/resourceUri to the tool definition\r\n * 2. Adds OpenAI-specific metadata (widgetAccessible, outputTemplate, etc.)\r\n * 3. Auto-registers a resource that renders the component to HTML with 'text/html+skybridge' mimeType\r\n */\r\nimport 'reflect-metadata';\r\nimport type React from 'react';\r\n\r\n// Metadata keys\r\nexport const GPT_APP_COMPONENT_KEY = 'gptapp:component';\r\nexport const GPT_APP_URI_KEY = 'gptapp:uri';\r\nexport const GPT_APP_OPTIONS_KEY = 'gptapp:options';\r\n\r\n/**\r\n * Options for @GPTApp decorator\r\n */\r\nexport interface GPTAppOptions {\r\n /** \r\n * React component or path to component file (relative to service file).\r\n * - Use path string (e.g., './WeatherCard') for CLI build - avoids importing browser code in server\r\n * - Use component reference for direct SSR rendering\r\n */\r\n component: React.ComponentType<any> | string;\r\n\r\n /** Custom resource URI (auto-generated ui://... if not provided) */\r\n uri?: string;\r\n\r\n /** HTML document title */\r\n title?: string;\r\n\r\n /** Additional CSS styles */\r\n styles?: string;\r\n\r\n // ========== GPT-specific options ==========\r\n\r\n /** \r\n * Allow widget to call tools via window.openai.callTool.\r\n * Maps to _meta[\"openai/widgetAccessible\"]\r\n */\r\n widgetAccessible?: boolean;\r\n\r\n /** \r\n * Tool visibility: 'public' (default) or 'private'.\r\n * 'private' hides the tool from the model but keeps it callable by the widget.\r\n * Maps to _meta[\"openai/visibility\"]\r\n */\r\n visibility?: 'public' | 'private';\r\n\r\n /** \r\n * Widget prefers border around iframe.\r\n * Maps to _meta[\"openai/widgetPrefersBorder\"]\r\n */\r\n prefersBorder?: boolean;\r\n\r\n /** \r\n * Widget domain for API allowlists.\r\n * Maps to _meta[\"openai/widgetDomain\"]\r\n */\r\n widgetDomain?: string;\r\n\r\n /** \r\n * Widget description for the model.\r\n * Maps to _meta[\"openai/widgetDescription\"]\r\n */\r\n widgetDescription?: string;\r\n\r\n /** \r\n * Content Security Policy configuration.\r\n * Maps to _meta[\"openai/widgetCSP\"]\r\n */\r\n csp?: {\r\n connect_domains?: string[];\r\n resource_domains?: string[];\r\n redirect_domains?: string[];\r\n frame_domains?: string[];\r\n };\r\n\r\n /** \r\n * File parameters (fields treated as file uploads).\r\n * Maps to _meta[\"openai/fileParams\"]\r\n */\r\n fileParams?: string[];\r\n\r\n /** \r\n * Invocation messages shown during tool call.\r\n * Maps to _meta[\"openai/toolInvocation\"]\r\n */\r\n invocation?: {\r\n invoking?: string; // e.g., \"Preparing the board…\"\r\n invoked?: string; // e.g., \"Board ready.\"\r\n };\r\n}\r\n\r\n\r\n/**\r\n * Decorator that links a tool to a UI component for ChatGPT Apps.\r\n * \r\n * When the tool is called, the host will fetch the UI resource\r\n * which returns the component rendered as HTML with 'text/html+skybridge'.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { Tool } from '@leanmcp/core';\r\n * import { GPTApp } from '@leanmcp/ui';\r\n * import { KanbanBoard } from './KanbanBoard';\r\n * \r\n * class KanbanService {\r\n * @Tool({ description: 'Show Kanban Board' })\r\n * @GPTApp({ \r\n * component: KanbanBoard,\r\n * widgetAccessible: true,\r\n * invocation: { invoking: 'Loading board...' }\r\n * })\r\n * async showBoard() { ... }\r\n * }\r\n * ```\r\n */\r\nexport function GPTApp(options: GPTAppOptions): MethodDecorator {\r\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\r\n const methodName = String(propertyKey);\r\n // Use same pattern as @Resource in @leanmcp/core: className without 'service' suffix\r\n const className = target.constructor.name.toLowerCase().replace('service', '');\r\n\r\n // Generate URI using ui:// scheme (required by ext-apps hosts)\r\n const uri = options.uri ?? `ui://${className}/${methodName}`;\r\n\r\n // Store metadata on the method\r\n Reflect.defineMetadata(GPT_APP_COMPONENT_KEY, options.component, descriptor.value!);\r\n Reflect.defineMetadata(GPT_APP_URI_KEY, uri, descriptor.value!);\r\n Reflect.defineMetadata(GPT_APP_OPTIONS_KEY, options, descriptor.value!);\r\n\r\n // Also store the resource URI and OpenAI-specific metadata for the @Tool decorator to pick up\r\n const existingMeta = Reflect.getMetadata('tool:meta', descriptor.value) || {};\r\n\r\n // Build nested ui metadata (preferred by ext-apps 0.2.2)\r\n const uiMeta: Record<string, any> = {\r\n resourceUri: uri,\r\n };\r\n\r\n // Map visibility to ext-apps format\r\n if (options.visibility) {\r\n uiMeta.visibility = options.visibility === 'private' ? ['app'] : ['model', 'app'];\r\n }\r\n\r\n const openAiMeta: Record<string, any> = {\r\n // New nested format (preferred by ext-apps 0.2.2)\r\n ui: uiMeta,\r\n // Legacy flat format (for backwards compatibility)\r\n 'ui/resourceUri': uri,\r\n 'openai/outputTemplate': uri,\r\n };\r\n\r\n if (options.widgetAccessible !== undefined) {\r\n openAiMeta['openai/widgetAccessible'] = options.widgetAccessible;\r\n }\r\n\r\n if (options.visibility) {\r\n openAiMeta['openai/visibility'] = options.visibility;\r\n }\r\n\r\n if (options.prefersBorder !== undefined) {\r\n openAiMeta['openai/widgetPrefersBorder'] = options.prefersBorder;\r\n }\r\n\r\n if (options.widgetDomain) {\r\n openAiMeta['openai/widgetDomain'] = options.widgetDomain;\r\n }\r\n\r\n if (options.widgetDescription) {\r\n openAiMeta['openai/widgetDescription'] = options.widgetDescription;\r\n }\r\n\r\n if (options.csp) {\r\n openAiMeta['openai/widgetCSP'] = options.csp;\r\n }\r\n\r\n if (options.fileParams) {\r\n openAiMeta['openai/fileParams'] = options.fileParams;\r\n }\r\n\r\n if (options.invocation) {\r\n if (options.invocation.invoking) openAiMeta['openai/toolInvocation/invoking'] = options.invocation.invoking;\r\n if (options.invocation.invoked) openAiMeta['openai/toolInvocation/invoked'] = options.invocation.invoked;\r\n }\r\n\r\n Reflect.defineMetadata('tool:meta', {\r\n ...existingMeta,\r\n ...openAiMeta,\r\n }, descriptor.value!);\r\n\r\n return descriptor;\r\n };\r\n}\r\n\r\n/**\r\n * Helper to get GPTApp metadata from a method\r\n */\r\nexport function getGPTAppMetadata(target: Function): GPTAppOptions | undefined {\r\n const component = Reflect.getMetadata(GPT_APP_COMPONENT_KEY, target);\r\n if (!component) return undefined;\r\n\r\n return {\r\n component,\r\n uri: Reflect.getMetadata(GPT_APP_URI_KEY, target),\r\n ...Reflect.getMetadata(GPT_APP_OPTIONS_KEY, target),\r\n };\r\n}\r\n\r\n/**\r\n * Helper to get the resource URI from a method\r\n */\r\nexport function getGPTAppUri(target: Function): string | undefined {\r\n return Reflect.getMetadata(GPT_APP_URI_KEY, target);\r\n}\r\n"]}
@@ -0,0 +1,124 @@
1
+ import 'reflect-metadata';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
5
+ var UI_APP_COMPONENT_KEY = "ui:app:component";
6
+ var UI_APP_URI_KEY = "ui:app:uri";
7
+ var UI_APP_OPTIONS_KEY = "ui:app:options";
8
+ function UIApp(options) {
9
+ return (target, propertyKey, descriptor) => {
10
+ const methodName = String(propertyKey);
11
+ const className = target.constructor.name.toLowerCase().replace("service", "");
12
+ const uri = options.uri ?? `ui://${className}/${methodName}`;
13
+ Reflect.defineMetadata(UI_APP_COMPONENT_KEY, options.component, descriptor.value);
14
+ Reflect.defineMetadata(UI_APP_URI_KEY, uri, descriptor.value);
15
+ Reflect.defineMetadata(UI_APP_OPTIONS_KEY, options, descriptor.value);
16
+ const existingMeta = Reflect.getMetadata("tool:meta", descriptor.value) || {};
17
+ Reflect.defineMetadata("tool:meta", {
18
+ ...existingMeta,
19
+ // New nested format (preferred by ext-apps 0.2.2)
20
+ ui: {
21
+ resourceUri: uri
22
+ },
23
+ // Legacy flat format (for backwards compatibility)
24
+ "ui/resourceUri": uri
25
+ }, descriptor.value);
26
+ return descriptor;
27
+ };
28
+ }
29
+ __name(UIApp, "UIApp");
30
+ function getUIAppMetadata(target) {
31
+ const component = Reflect.getMetadata(UI_APP_COMPONENT_KEY, target);
32
+ if (!component) return void 0;
33
+ return {
34
+ component,
35
+ uri: Reflect.getMetadata(UI_APP_URI_KEY, target),
36
+ ...Reflect.getMetadata(UI_APP_OPTIONS_KEY, target)
37
+ };
38
+ }
39
+ __name(getUIAppMetadata, "getUIAppMetadata");
40
+ function getUIAppUri(target) {
41
+ return Reflect.getMetadata(UI_APP_URI_KEY, target);
42
+ }
43
+ __name(getUIAppUri, "getUIAppUri");
44
+ var GPT_APP_COMPONENT_KEY = "gptapp:component";
45
+ var GPT_APP_URI_KEY = "gptapp:uri";
46
+ var GPT_APP_OPTIONS_KEY = "gptapp:options";
47
+ function GPTApp(options) {
48
+ return (target, propertyKey, descriptor) => {
49
+ const methodName = String(propertyKey);
50
+ const className = target.constructor.name.toLowerCase().replace("service", "");
51
+ const uri = options.uri ?? `ui://${className}/${methodName}`;
52
+ Reflect.defineMetadata(GPT_APP_COMPONENT_KEY, options.component, descriptor.value);
53
+ Reflect.defineMetadata(GPT_APP_URI_KEY, uri, descriptor.value);
54
+ Reflect.defineMetadata(GPT_APP_OPTIONS_KEY, options, descriptor.value);
55
+ const existingMeta = Reflect.getMetadata("tool:meta", descriptor.value) || {};
56
+ const uiMeta = {
57
+ resourceUri: uri
58
+ };
59
+ if (options.visibility) {
60
+ uiMeta.visibility = options.visibility === "private" ? [
61
+ "app"
62
+ ] : [
63
+ "model",
64
+ "app"
65
+ ];
66
+ }
67
+ const openAiMeta = {
68
+ // New nested format (preferred by ext-apps 0.2.2)
69
+ ui: uiMeta,
70
+ // Legacy flat format (for backwards compatibility)
71
+ "ui/resourceUri": uri,
72
+ "openai/outputTemplate": uri
73
+ };
74
+ if (options.widgetAccessible !== void 0) {
75
+ openAiMeta["openai/widgetAccessible"] = options.widgetAccessible;
76
+ }
77
+ if (options.visibility) {
78
+ openAiMeta["openai/visibility"] = options.visibility;
79
+ }
80
+ if (options.prefersBorder !== void 0) {
81
+ openAiMeta["openai/widgetPrefersBorder"] = options.prefersBorder;
82
+ }
83
+ if (options.widgetDomain) {
84
+ openAiMeta["openai/widgetDomain"] = options.widgetDomain;
85
+ }
86
+ if (options.widgetDescription) {
87
+ openAiMeta["openai/widgetDescription"] = options.widgetDescription;
88
+ }
89
+ if (options.csp) {
90
+ openAiMeta["openai/widgetCSP"] = options.csp;
91
+ }
92
+ if (options.fileParams) {
93
+ openAiMeta["openai/fileParams"] = options.fileParams;
94
+ }
95
+ if (options.invocation) {
96
+ if (options.invocation.invoking) openAiMeta["openai/toolInvocation/invoking"] = options.invocation.invoking;
97
+ if (options.invocation.invoked) openAiMeta["openai/toolInvocation/invoked"] = options.invocation.invoked;
98
+ }
99
+ Reflect.defineMetadata("tool:meta", {
100
+ ...existingMeta,
101
+ ...openAiMeta
102
+ }, descriptor.value);
103
+ return descriptor;
104
+ };
105
+ }
106
+ __name(GPTApp, "GPTApp");
107
+ function getGPTAppMetadata(target) {
108
+ const component = Reflect.getMetadata(GPT_APP_COMPONENT_KEY, target);
109
+ if (!component) return void 0;
110
+ return {
111
+ component,
112
+ uri: Reflect.getMetadata(GPT_APP_URI_KEY, target),
113
+ ...Reflect.getMetadata(GPT_APP_OPTIONS_KEY, target)
114
+ };
115
+ }
116
+ __name(getGPTAppMetadata, "getGPTAppMetadata");
117
+ function getGPTAppUri(target) {
118
+ return Reflect.getMetadata(GPT_APP_URI_KEY, target);
119
+ }
120
+ __name(getGPTAppUri, "getGPTAppUri");
121
+
122
+ export { GPTApp, GPT_APP_COMPONENT_KEY, GPT_APP_OPTIONS_KEY, GPT_APP_URI_KEY, UIApp, UI_APP_COMPONENT_KEY, UI_APP_OPTIONS_KEY, UI_APP_URI_KEY, __name, getGPTAppMetadata, getGPTAppUri, getUIAppMetadata, getUIAppUri };
123
+ //# sourceMappingURL=chunk-KX75VCMM.mjs.map
124
+ //# sourceMappingURL=chunk-KX75VCMM.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/decorator/UIApp.ts","../src/decorator/GPTApp.ts"],"names":["UI_APP_COMPONENT_KEY","UI_APP_URI_KEY","UI_APP_OPTIONS_KEY","UIApp","options","target","propertyKey","descriptor","methodName","String","className","name","toLowerCase","replace","uri","Reflect","defineMetadata","component","value","existingMeta","getMetadata","ui","resourceUri","getUIAppMetadata","undefined","getUIAppUri","GPT_APP_COMPONENT_KEY","GPT_APP_URI_KEY","GPT_APP_OPTIONS_KEY","GPTApp","uiMeta","visibility","openAiMeta","widgetAccessible","prefersBorder","widgetDomain","widgetDescription","csp","fileParams","invocation","invoking","invoked","getGPTAppMetadata","getGPTAppUri"],"mappings":"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","file":"chunk-KX75VCMM.mjs","sourcesContent":["/**\r\n * @UIApp Decorator\r\n * \r\n * Links an MCP tool to a React UI component.\r\n * When applied to a tool method, it:\r\n * 1. Adds _meta.ui/resourceUri to the tool definition\r\n * 2. Auto-registers a resource that renders the component to HTML\r\n * \r\n * This decorator is designed to work with @leanmcp/core decorators.\r\n */\r\nimport 'reflect-metadata';\r\nimport type React from 'react';\r\n\r\n// Metadata keys\r\nexport const UI_APP_COMPONENT_KEY = 'ui:app:component';\r\nexport const UI_APP_URI_KEY = 'ui:app:uri';\r\nexport const UI_APP_OPTIONS_KEY = 'ui:app:options';\r\n\r\n/**\r\n * Options for @UIApp decorator\r\n */\r\nexport interface UIAppOptions {\r\n /** \r\n * React component or path to component file (relative to service file).\r\n * - Use path string (e.g., './WeatherCard') for CLI build - avoids importing browser code in server\r\n * - Use component reference for direct SSR rendering\r\n */\r\n component: React.ComponentType<any> | string;\r\n /** Custom resource URI (auto-generated if not provided) */\r\n uri?: string;\r\n /** HTML document title */\r\n title?: string;\r\n /** Additional CSS styles */\r\n styles?: string;\r\n}\r\n\r\n\r\n/**\r\n * Decorator that links a tool to a UI component.\r\n * \r\n * When the tool is called, the host will fetch the UI resource\r\n * which returns the component rendered as HTML.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { Tool } from '@leanmcp/core';\r\n * import { UIApp } from '@leanmcp/ui';\r\n * import { WeatherCard } from './WeatherCard';\r\n * \r\n * class WeatherService {\r\n * @Tool({ description: 'Get weather for a city' })\r\n * @UIApp({ component: WeatherCard })\r\n * async getWeather(args: { city: string }) {\r\n * return { city: args.city, temp: 22 };\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function UIApp(options: UIAppOptions): MethodDecorator {\r\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\r\n const methodName = String(propertyKey);\r\n // Use same pattern as @Resource in @leanmcp/core: className without 'service' suffix\r\n const className = target.constructor.name.toLowerCase().replace('service', '');\r\n\r\n // Generate URI using ui:// scheme (required by ext-apps hosts)\r\n const uri = options.uri ?? `ui://${className}/${methodName}`;\r\n\r\n // Store metadata on the method\r\n Reflect.defineMetadata(UI_APP_COMPONENT_KEY, options.component, descriptor.value!);\r\n Reflect.defineMetadata(UI_APP_URI_KEY, uri, descriptor.value!);\r\n Reflect.defineMetadata(UI_APP_OPTIONS_KEY, options, descriptor.value!);\r\n\r\n // Also store the resource URI for the @Tool decorator to pick up\r\n // The @Tool decorator in @leanmcp/core should check for this\r\n const existingMeta = Reflect.getMetadata('tool:meta', descriptor.value) || {};\r\n Reflect.defineMetadata('tool:meta', {\r\n ...existingMeta,\r\n // New nested format (preferred by ext-apps 0.2.2)\r\n ui: {\r\n resourceUri: uri,\r\n },\r\n // Legacy flat format (for backwards compatibility)\r\n 'ui/resourceUri': uri,\r\n }, descriptor.value!);\r\n\r\n return descriptor;\r\n };\r\n}\r\n\r\n/**\r\n * Helper to get UIApp metadata from a method\r\n */\r\nexport function getUIAppMetadata(target: Function): UIAppOptions | undefined {\r\n const component = Reflect.getMetadata(UI_APP_COMPONENT_KEY, target);\r\n if (!component) return undefined;\r\n\r\n return {\r\n component,\r\n uri: Reflect.getMetadata(UI_APP_URI_KEY, target),\r\n ...Reflect.getMetadata(UI_APP_OPTIONS_KEY, target),\r\n };\r\n}\r\n\r\n/**\r\n * Helper to get the resource URI from a method\r\n */\r\nexport function getUIAppUri(target: Function): string | undefined {\r\n return Reflect.getMetadata(UI_APP_URI_KEY, target);\r\n}\r\n","/**\r\n * @GPTApp Decorator\r\n * \r\n * Links an MCP tool to a React UI component compliant with ChatGPT Apps SDK.\r\n * \r\n * When applied to a tool method, it:\r\n * 1. Adds _meta.ui/resourceUri to the tool definition\r\n * 2. Adds OpenAI-specific metadata (widgetAccessible, outputTemplate, etc.)\r\n * 3. Auto-registers a resource that renders the component to HTML with 'text/html+skybridge' mimeType\r\n */\r\nimport 'reflect-metadata';\r\nimport type React from 'react';\r\n\r\n// Metadata keys\r\nexport const GPT_APP_COMPONENT_KEY = 'gptapp:component';\r\nexport const GPT_APP_URI_KEY = 'gptapp:uri';\r\nexport const GPT_APP_OPTIONS_KEY = 'gptapp:options';\r\n\r\n/**\r\n * Options for @GPTApp decorator\r\n */\r\nexport interface GPTAppOptions {\r\n /** \r\n * React component or path to component file (relative to service file).\r\n * - Use path string (e.g., './WeatherCard') for CLI build - avoids importing browser code in server\r\n * - Use component reference for direct SSR rendering\r\n */\r\n component: React.ComponentType<any> | string;\r\n\r\n /** Custom resource URI (auto-generated ui://... if not provided) */\r\n uri?: string;\r\n\r\n /** HTML document title */\r\n title?: string;\r\n\r\n /** Additional CSS styles */\r\n styles?: string;\r\n\r\n // ========== GPT-specific options ==========\r\n\r\n /** \r\n * Allow widget to call tools via window.openai.callTool.\r\n * Maps to _meta[\"openai/widgetAccessible\"]\r\n */\r\n widgetAccessible?: boolean;\r\n\r\n /** \r\n * Tool visibility: 'public' (default) or 'private'.\r\n * 'private' hides the tool from the model but keeps it callable by the widget.\r\n * Maps to _meta[\"openai/visibility\"]\r\n */\r\n visibility?: 'public' | 'private';\r\n\r\n /** \r\n * Widget prefers border around iframe.\r\n * Maps to _meta[\"openai/widgetPrefersBorder\"]\r\n */\r\n prefersBorder?: boolean;\r\n\r\n /** \r\n * Widget domain for API allowlists.\r\n * Maps to _meta[\"openai/widgetDomain\"]\r\n */\r\n widgetDomain?: string;\r\n\r\n /** \r\n * Widget description for the model.\r\n * Maps to _meta[\"openai/widgetDescription\"]\r\n */\r\n widgetDescription?: string;\r\n\r\n /** \r\n * Content Security Policy configuration.\r\n * Maps to _meta[\"openai/widgetCSP\"]\r\n */\r\n csp?: {\r\n connect_domains?: string[];\r\n resource_domains?: string[];\r\n redirect_domains?: string[];\r\n frame_domains?: string[];\r\n };\r\n\r\n /** \r\n * File parameters (fields treated as file uploads).\r\n * Maps to _meta[\"openai/fileParams\"]\r\n */\r\n fileParams?: string[];\r\n\r\n /** \r\n * Invocation messages shown during tool call.\r\n * Maps to _meta[\"openai/toolInvocation\"]\r\n */\r\n invocation?: {\r\n invoking?: string; // e.g., \"Preparing the board…\"\r\n invoked?: string; // e.g., \"Board ready.\"\r\n };\r\n}\r\n\r\n\r\n/**\r\n * Decorator that links a tool to a UI component for ChatGPT Apps.\r\n * \r\n * When the tool is called, the host will fetch the UI resource\r\n * which returns the component rendered as HTML with 'text/html+skybridge'.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { Tool } from '@leanmcp/core';\r\n * import { GPTApp } from '@leanmcp/ui';\r\n * import { KanbanBoard } from './KanbanBoard';\r\n * \r\n * class KanbanService {\r\n * @Tool({ description: 'Show Kanban Board' })\r\n * @GPTApp({ \r\n * component: KanbanBoard,\r\n * widgetAccessible: true,\r\n * invocation: { invoking: 'Loading board...' }\r\n * })\r\n * async showBoard() { ... }\r\n * }\r\n * ```\r\n */\r\nexport function GPTApp(options: GPTAppOptions): MethodDecorator {\r\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\r\n const methodName = String(propertyKey);\r\n // Use same pattern as @Resource in @leanmcp/core: className without 'service' suffix\r\n const className = target.constructor.name.toLowerCase().replace('service', '');\r\n\r\n // Generate URI using ui:// scheme (required by ext-apps hosts)\r\n const uri = options.uri ?? `ui://${className}/${methodName}`;\r\n\r\n // Store metadata on the method\r\n Reflect.defineMetadata(GPT_APP_COMPONENT_KEY, options.component, descriptor.value!);\r\n Reflect.defineMetadata(GPT_APP_URI_KEY, uri, descriptor.value!);\r\n Reflect.defineMetadata(GPT_APP_OPTIONS_KEY, options, descriptor.value!);\r\n\r\n // Also store the resource URI and OpenAI-specific metadata for the @Tool decorator to pick up\r\n const existingMeta = Reflect.getMetadata('tool:meta', descriptor.value) || {};\r\n\r\n // Build nested ui metadata (preferred by ext-apps 0.2.2)\r\n const uiMeta: Record<string, any> = {\r\n resourceUri: uri,\r\n };\r\n\r\n // Map visibility to ext-apps format\r\n if (options.visibility) {\r\n uiMeta.visibility = options.visibility === 'private' ? ['app'] : ['model', 'app'];\r\n }\r\n\r\n const openAiMeta: Record<string, any> = {\r\n // New nested format (preferred by ext-apps 0.2.2)\r\n ui: uiMeta,\r\n // Legacy flat format (for backwards compatibility)\r\n 'ui/resourceUri': uri,\r\n 'openai/outputTemplate': uri,\r\n };\r\n\r\n if (options.widgetAccessible !== undefined) {\r\n openAiMeta['openai/widgetAccessible'] = options.widgetAccessible;\r\n }\r\n\r\n if (options.visibility) {\r\n openAiMeta['openai/visibility'] = options.visibility;\r\n }\r\n\r\n if (options.prefersBorder !== undefined) {\r\n openAiMeta['openai/widgetPrefersBorder'] = options.prefersBorder;\r\n }\r\n\r\n if (options.widgetDomain) {\r\n openAiMeta['openai/widgetDomain'] = options.widgetDomain;\r\n }\r\n\r\n if (options.widgetDescription) {\r\n openAiMeta['openai/widgetDescription'] = options.widgetDescription;\r\n }\r\n\r\n if (options.csp) {\r\n openAiMeta['openai/widgetCSP'] = options.csp;\r\n }\r\n\r\n if (options.fileParams) {\r\n openAiMeta['openai/fileParams'] = options.fileParams;\r\n }\r\n\r\n if (options.invocation) {\r\n if (options.invocation.invoking) openAiMeta['openai/toolInvocation/invoking'] = options.invocation.invoking;\r\n if (options.invocation.invoked) openAiMeta['openai/toolInvocation/invoked'] = options.invocation.invoked;\r\n }\r\n\r\n Reflect.defineMetadata('tool:meta', {\r\n ...existingMeta,\r\n ...openAiMeta,\r\n }, descriptor.value!);\r\n\r\n return descriptor;\r\n };\r\n}\r\n\r\n/**\r\n * Helper to get GPTApp metadata from a method\r\n */\r\nexport function getGPTAppMetadata(target: Function): GPTAppOptions | undefined {\r\n const component = Reflect.getMetadata(GPT_APP_COMPONENT_KEY, target);\r\n if (!component) return undefined;\r\n\r\n return {\r\n component,\r\n uri: Reflect.getMetadata(GPT_APP_URI_KEY, target),\r\n ...Reflect.getMetadata(GPT_APP_OPTIONS_KEY, target),\r\n };\r\n}\r\n\r\n/**\r\n * Helper to get the resource URI from a method\r\n */\r\nexport function getGPTAppUri(target: Function): string | undefined {\r\n return Reflect.getMetadata(GPT_APP_URI_KEY, target);\r\n}\r\n"]}
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { ReactNode, ButtonHTMLAttributes, Component, ErrorInfo, HTMLAttributes, InputHTMLAttributes } from 'react';
4
4
  import { McpUiAppCapabilities, App, McpUiHostContext, McpUiDisplayMode, McpUiHostStyles } from '@modelcontextprotocol/ext-apps';
5
- export { App, McpUiAppCapabilities, McpUiDisplayMode, McpUiHostContext, McpUiHostStyles, McpUiStyles, McpUiToolCancelledNotification, McpUiToolInputNotification, McpUiToolInputPartialNotification, McpUiToolResultNotification, PostMessageTransport } from '@modelcontextprotocol/ext-apps';
5
+ export { App, McpUiAppCapabilities, McpUiDisplayMode, McpUiHostContext, McpUiHostCss, McpUiHostStyles, McpUiResourceCsp, McpUiResourceMeta, McpUiStyles, McpUiTheme, McpUiToolCancelledNotification, McpUiToolInputNotification, McpUiToolInputPartialNotification, McpUiToolMeta, McpUiToolResultNotification, McpUiToolVisibility, PostMessageTransport, RESOURCE_MIME_TYPE, RESOURCE_URI_META_KEY, applyDocumentTheme, applyHostFonts, applyHostStyleVariables, getDocumentTheme } from '@modelcontextprotocol/ext-apps';
6
6
  import { CallToolResult, ContentBlock } from '@modelcontextprotocol/sdk/types.js';
7
7
  import { ToasterProps } from 'sonner';
8
8
  import * as class_variance_authority_types from 'class-variance-authority/types';
@@ -25,9 +25,10 @@ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
25
25
  import { Command as Command$1 } from 'cmdk';
26
26
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
27
27
  import { ClassValue } from 'clsx';
28
- export { UIApp, UIAppOptions, getUIAppMetadata, getUIAppUri } from './server.mjs';
28
+ export { GPTApp, GPTAppOptions, UIApp, UIAppOptions, getGPTAppMetadata, getGPTAppUri, getUIAppMetadata, getUIAppUri } from './server.mjs';
29
29
  import { ChartData, ChartType as ChartType$1, ChartOptions } from 'chart.js';
30
30
  export { AppBridge } from '@modelcontextprotocol/ext-apps/app-bridge';
31
+ import '@modelcontextprotocol/ext-apps/server';
31
32
 
32
33
  /**
33
34
  * App information (same as ext-apps Implementation)
@@ -121,6 +122,107 @@ declare function AppProvider({ appInfo, capabilities, options, onTeardown, child
121
122
  */
122
123
  declare function useMcpApp(): McpAppContextValue;
123
124
 
125
+ /**
126
+ * ChatGPT's window.openai interface
127
+ * Only includes properties that are confirmed to exist in the ChatGPT Apps SDK
128
+ */
129
+ interface OpenAISDK {
130
+ /** Call a server tool */
131
+ callTool: (name: string, args: Record<string, unknown>) => Promise<any>;
132
+ /** Current theme */
133
+ theme?: 'light' | 'dark';
134
+ /** Current locale */
135
+ locale?: string;
136
+ /** Display mode */
137
+ displayMode?: 'inline' | 'modal' | 'fullscreen';
138
+ /** Maximum height for the widget */
139
+ maxHeight?: number;
140
+ }
141
+ declare global {
142
+ interface Window {
143
+ openai?: OpenAISDK;
144
+ }
145
+ }
146
+ /**
147
+ * GPT App context value - available via useGptApp()
148
+ */
149
+ interface GptAppContextValue {
150
+ /** Whether connected to ChatGPT host */
151
+ isConnected: boolean;
152
+ /** Connection error, if any */
153
+ error: Error | null;
154
+ /** Theme from host */
155
+ theme: 'light' | 'dark';
156
+ /** Display mode */
157
+ displayMode: string;
158
+ /** Locale */
159
+ locale: string;
160
+ /** Max height from host */
161
+ maxHeight: number;
162
+ /** Call a server tool via ChatGPT */
163
+ callTool: (name: string, args?: Record<string, unknown>) => Promise<any>;
164
+ }
165
+ interface GPTAppProviderProps {
166
+ /** App name */
167
+ appName: string;
168
+ /** React children */
169
+ children: ReactNode;
170
+ }
171
+ /**
172
+ * GPTAppProvider - Root context for ChatGPT Apps
173
+ *
174
+ * Uses ChatGPT's native window.openai SDK for host communication.
175
+ *
176
+ * @example
177
+ * ```tsx
178
+ * function MyGPTApp() {
179
+ * return (
180
+ * <GPTAppProvider appName="MyApp">
181
+ * <MyContent />
182
+ * </GPTAppProvider>
183
+ * );
184
+ * }
185
+ * ```
186
+ */
187
+ declare function GPTAppProvider({ appName, children }: GPTAppProviderProps): react_jsx_runtime.JSX.Element;
188
+ /**
189
+ * Hook to access the GPT App context
190
+ *
191
+ * @example
192
+ * ```tsx
193
+ * function MyComponent() {
194
+ * const { isConnected, theme, callTool } = useGptApp();
195
+ * // ...
196
+ * }
197
+ * ```
198
+ */
199
+ declare function useGptApp(): GptAppContextValue;
200
+ /**
201
+ * Hook to call tools via ChatGPT SDK
202
+ * Similar to useTool but for GPT Apps
203
+ *
204
+ * @example
205
+ * ```tsx
206
+ * function MyComponent() {
207
+ * const { call, result, loading, error } = useGptTool('myTool');
208
+ *
209
+ * useEffect(() => {
210
+ * call({ param: 'value' });
211
+ * }, []);
212
+ *
213
+ * if (loading) return <div>Loading...</div>;
214
+ * return <div>{JSON.stringify(result)}</div>;
215
+ * }
216
+ * ```
217
+ */
218
+ declare function useGptTool(toolName: string): {
219
+ call: (args?: Record<string, unknown>) => Promise<any>;
220
+ result: any;
221
+ loading: boolean;
222
+ error: Error | null;
223
+ isConnected: boolean;
224
+ };
225
+
124
226
  /**
125
227
  * MCP-Native UI SDK - Core Types
126
228
  *
@@ -1521,4 +1623,4 @@ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>
1521
1623
  */
1522
1624
  declare const Input: React__default.ForwardRefExoticComponent<InputProps & React__default.RefAttributes<HTMLInputElement>>;
1523
1625
 
1524
- export { ActionButton, type ActionButtonProps, Alert, AlertDescription, AlertTitle, type AppInfo, type AppOptions, AppProvider, type AppProviderProps, AppShell, type AppShellProps, Badge, Button, type ButtonProps, Card, CardContent, type CardContentProps, CardDescription, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, Chart, type ChartProps, type ChartType, Checkbox, CodeBlock, type CodeBlockProps, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, type ConfirmConfig, DEFAULT_RESULT_CONFIG, DataGrid, type DataGridColumn, type DataGridProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, INITIAL_TOOL_STATE, Input, type InputProps, Label, type McpActionProps, type McpAppContextValue, Modal, type ModalProps, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RequireConnection, type RequireConnectionProps, type ResourceBinding, type ResourceMeta, ResourceView, type ResourceViewProps, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Skeleton, Slider, StreamingContent, type StreamingContentProps, Switch, TabContent, type TabContentProps, type TabItem, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, Textarea, Toaster, type ToolBinding, ToolButton, type ToolButtonProps, type ToolButtonState, type ToolCallState, type ToolContextValue, ToolDataGrid, type ToolDataGridColumn, type ToolDataGridProps, type ToolDataGridRowAction, ToolErrorBoundary, type ToolErrorBoundaryProps, ToolForm, type ToolFormField, type ToolFormProps, ToolInput, type ToolInputProps, type ToolInputSuggestion, ToolProvider, type ToolProviderProps, type ToolResultConfig, ToolSelect, type ToolSelectOption, type ToolSelectProps, type ToolState, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseHostContextReturn, type UseMessageReturn, type UseResourceOptions, type UseResourceReturn, type UseToolInputPartialReturn, type UseToolInputReturn, type UseToolOptions, type UseToolResultReturn, type UseToolReturn, type UseToolStreamOptions, type UseToolStreamReturn, badgeVariants, buttonVariants, cn, normalizeToolBinding, useFormField, useHostContext, useMcpApp, useMessage, useResource, useTool, useToolContext, useToolInput, useToolInputPartial, useToolResult, useToolStream, useToolSubscription };
1626
+ export { ActionButton, type ActionButtonProps, Alert, AlertDescription, AlertTitle, type AppInfo, type AppOptions, AppProvider, type AppProviderProps, AppShell, type AppShellProps, Badge, Button, type ButtonProps, Card, CardContent, type CardContentProps, CardDescription, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, Chart, type ChartProps, type ChartType, Checkbox, CodeBlock, type CodeBlockProps, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, type ConfirmConfig, DEFAULT_RESULT_CONFIG, DataGrid, type DataGridColumn, type DataGridProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GPTAppProvider, type GPTAppProviderProps, type GptAppContextValue, INITIAL_TOOL_STATE, Input, type InputProps, Label, type McpActionProps, type McpAppContextValue, Modal, type ModalProps, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RequireConnection, type RequireConnectionProps, type ResourceBinding, type ResourceMeta, ResourceView, type ResourceViewProps, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Skeleton, Slider, StreamingContent, type StreamingContentProps, Switch, TabContent, type TabContentProps, type TabItem, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, Textarea, Toaster, type ToolBinding, ToolButton, type ToolButtonProps, type ToolButtonState, type ToolCallState, type ToolContextValue, ToolDataGrid, type ToolDataGridColumn, type ToolDataGridProps, type ToolDataGridRowAction, ToolErrorBoundary, type ToolErrorBoundaryProps, ToolForm, type ToolFormField, type ToolFormProps, ToolInput, type ToolInputProps, type ToolInputSuggestion, ToolProvider, type ToolProviderProps, type ToolResultConfig, ToolSelect, type ToolSelectOption, type ToolSelectProps, type ToolState, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseHostContextReturn, type UseMessageReturn, type UseResourceOptions, type UseResourceReturn, type UseToolInputPartialReturn, type UseToolInputReturn, type UseToolOptions, type UseToolResultReturn, type UseToolReturn, type UseToolStreamOptions, type UseToolStreamReturn, badgeVariants, buttonVariants, cn, normalizeToolBinding, useFormField, useGptApp, useGptTool, useHostContext, useMcpApp, useMessage, useResource, useTool, useToolContext, useToolInput, useToolInputPartial, useToolResult, useToolStream, useToolSubscription };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { ReactNode, ButtonHTMLAttributes, Component, ErrorInfo, HTMLAttributes, InputHTMLAttributes } from 'react';
4
4
  import { McpUiAppCapabilities, App, McpUiHostContext, McpUiDisplayMode, McpUiHostStyles } from '@modelcontextprotocol/ext-apps';
5
- export { App, McpUiAppCapabilities, McpUiDisplayMode, McpUiHostContext, McpUiHostStyles, McpUiStyles, McpUiToolCancelledNotification, McpUiToolInputNotification, McpUiToolInputPartialNotification, McpUiToolResultNotification, PostMessageTransport } from '@modelcontextprotocol/ext-apps';
5
+ export { App, McpUiAppCapabilities, McpUiDisplayMode, McpUiHostContext, McpUiHostCss, McpUiHostStyles, McpUiResourceCsp, McpUiResourceMeta, McpUiStyles, McpUiTheme, McpUiToolCancelledNotification, McpUiToolInputNotification, McpUiToolInputPartialNotification, McpUiToolMeta, McpUiToolResultNotification, McpUiToolVisibility, PostMessageTransport, RESOURCE_MIME_TYPE, RESOURCE_URI_META_KEY, applyDocumentTheme, applyHostFonts, applyHostStyleVariables, getDocumentTheme } from '@modelcontextprotocol/ext-apps';
6
6
  import { CallToolResult, ContentBlock } from '@modelcontextprotocol/sdk/types.js';
7
7
  import { ToasterProps } from 'sonner';
8
8
  import * as class_variance_authority_types from 'class-variance-authority/types';
@@ -25,9 +25,10 @@ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
25
25
  import { Command as Command$1 } from 'cmdk';
26
26
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
27
27
  import { ClassValue } from 'clsx';
28
- export { UIApp, UIAppOptions, getUIAppMetadata, getUIAppUri } from './server.js';
28
+ export { GPTApp, GPTAppOptions, UIApp, UIAppOptions, getGPTAppMetadata, getGPTAppUri, getUIAppMetadata, getUIAppUri } from './server.js';
29
29
  import { ChartData, ChartType as ChartType$1, ChartOptions } from 'chart.js';
30
30
  export { AppBridge } from '@modelcontextprotocol/ext-apps/app-bridge';
31
+ import '@modelcontextprotocol/ext-apps/server';
31
32
 
32
33
  /**
33
34
  * App information (same as ext-apps Implementation)
@@ -121,6 +122,107 @@ declare function AppProvider({ appInfo, capabilities, options, onTeardown, child
121
122
  */
122
123
  declare function useMcpApp(): McpAppContextValue;
123
124
 
125
+ /**
126
+ * ChatGPT's window.openai interface
127
+ * Only includes properties that are confirmed to exist in the ChatGPT Apps SDK
128
+ */
129
+ interface OpenAISDK {
130
+ /** Call a server tool */
131
+ callTool: (name: string, args: Record<string, unknown>) => Promise<any>;
132
+ /** Current theme */
133
+ theme?: 'light' | 'dark';
134
+ /** Current locale */
135
+ locale?: string;
136
+ /** Display mode */
137
+ displayMode?: 'inline' | 'modal' | 'fullscreen';
138
+ /** Maximum height for the widget */
139
+ maxHeight?: number;
140
+ }
141
+ declare global {
142
+ interface Window {
143
+ openai?: OpenAISDK;
144
+ }
145
+ }
146
+ /**
147
+ * GPT App context value - available via useGptApp()
148
+ */
149
+ interface GptAppContextValue {
150
+ /** Whether connected to ChatGPT host */
151
+ isConnected: boolean;
152
+ /** Connection error, if any */
153
+ error: Error | null;
154
+ /** Theme from host */
155
+ theme: 'light' | 'dark';
156
+ /** Display mode */
157
+ displayMode: string;
158
+ /** Locale */
159
+ locale: string;
160
+ /** Max height from host */
161
+ maxHeight: number;
162
+ /** Call a server tool via ChatGPT */
163
+ callTool: (name: string, args?: Record<string, unknown>) => Promise<any>;
164
+ }
165
+ interface GPTAppProviderProps {
166
+ /** App name */
167
+ appName: string;
168
+ /** React children */
169
+ children: ReactNode;
170
+ }
171
+ /**
172
+ * GPTAppProvider - Root context for ChatGPT Apps
173
+ *
174
+ * Uses ChatGPT's native window.openai SDK for host communication.
175
+ *
176
+ * @example
177
+ * ```tsx
178
+ * function MyGPTApp() {
179
+ * return (
180
+ * <GPTAppProvider appName="MyApp">
181
+ * <MyContent />
182
+ * </GPTAppProvider>
183
+ * );
184
+ * }
185
+ * ```
186
+ */
187
+ declare function GPTAppProvider({ appName, children }: GPTAppProviderProps): react_jsx_runtime.JSX.Element;
188
+ /**
189
+ * Hook to access the GPT App context
190
+ *
191
+ * @example
192
+ * ```tsx
193
+ * function MyComponent() {
194
+ * const { isConnected, theme, callTool } = useGptApp();
195
+ * // ...
196
+ * }
197
+ * ```
198
+ */
199
+ declare function useGptApp(): GptAppContextValue;
200
+ /**
201
+ * Hook to call tools via ChatGPT SDK
202
+ * Similar to useTool but for GPT Apps
203
+ *
204
+ * @example
205
+ * ```tsx
206
+ * function MyComponent() {
207
+ * const { call, result, loading, error } = useGptTool('myTool');
208
+ *
209
+ * useEffect(() => {
210
+ * call({ param: 'value' });
211
+ * }, []);
212
+ *
213
+ * if (loading) return <div>Loading...</div>;
214
+ * return <div>{JSON.stringify(result)}</div>;
215
+ * }
216
+ * ```
217
+ */
218
+ declare function useGptTool(toolName: string): {
219
+ call: (args?: Record<string, unknown>) => Promise<any>;
220
+ result: any;
221
+ loading: boolean;
222
+ error: Error | null;
223
+ isConnected: boolean;
224
+ };
225
+
124
226
  /**
125
227
  * MCP-Native UI SDK - Core Types
126
228
  *
@@ -1521,4 +1623,4 @@ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>
1521
1623
  */
1522
1624
  declare const Input: React__default.ForwardRefExoticComponent<InputProps & React__default.RefAttributes<HTMLInputElement>>;
1523
1625
 
1524
- export { ActionButton, type ActionButtonProps, Alert, AlertDescription, AlertTitle, type AppInfo, type AppOptions, AppProvider, type AppProviderProps, AppShell, type AppShellProps, Badge, Button, type ButtonProps, Card, CardContent, type CardContentProps, CardDescription, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, Chart, type ChartProps, type ChartType, Checkbox, CodeBlock, type CodeBlockProps, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, type ConfirmConfig, DEFAULT_RESULT_CONFIG, DataGrid, type DataGridColumn, type DataGridProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, INITIAL_TOOL_STATE, Input, type InputProps, Label, type McpActionProps, type McpAppContextValue, Modal, type ModalProps, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RequireConnection, type RequireConnectionProps, type ResourceBinding, type ResourceMeta, ResourceView, type ResourceViewProps, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Skeleton, Slider, StreamingContent, type StreamingContentProps, Switch, TabContent, type TabContentProps, type TabItem, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, Textarea, Toaster, type ToolBinding, ToolButton, type ToolButtonProps, type ToolButtonState, type ToolCallState, type ToolContextValue, ToolDataGrid, type ToolDataGridColumn, type ToolDataGridProps, type ToolDataGridRowAction, ToolErrorBoundary, type ToolErrorBoundaryProps, ToolForm, type ToolFormField, type ToolFormProps, ToolInput, type ToolInputProps, type ToolInputSuggestion, ToolProvider, type ToolProviderProps, type ToolResultConfig, ToolSelect, type ToolSelectOption, type ToolSelectProps, type ToolState, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseHostContextReturn, type UseMessageReturn, type UseResourceOptions, type UseResourceReturn, type UseToolInputPartialReturn, type UseToolInputReturn, type UseToolOptions, type UseToolResultReturn, type UseToolReturn, type UseToolStreamOptions, type UseToolStreamReturn, badgeVariants, buttonVariants, cn, normalizeToolBinding, useFormField, useHostContext, useMcpApp, useMessage, useResource, useTool, useToolContext, useToolInput, useToolInputPartial, useToolResult, useToolStream, useToolSubscription };
1626
+ export { ActionButton, type ActionButtonProps, Alert, AlertDescription, AlertTitle, type AppInfo, type AppOptions, AppProvider, type AppProviderProps, AppShell, type AppShellProps, Badge, Button, type ButtonProps, Card, CardContent, type CardContentProps, CardDescription, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, Chart, type ChartProps, type ChartType, Checkbox, CodeBlock, type CodeBlockProps, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, type ConfirmConfig, DEFAULT_RESULT_CONFIG, DataGrid, type DataGridColumn, type DataGridProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GPTAppProvider, type GPTAppProviderProps, type GptAppContextValue, INITIAL_TOOL_STATE, Input, type InputProps, Label, type McpActionProps, type McpAppContextValue, Modal, type ModalProps, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RequireConnection, type RequireConnectionProps, type ResourceBinding, type ResourceMeta, ResourceView, type ResourceViewProps, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Skeleton, Slider, StreamingContent, type StreamingContentProps, Switch, TabContent, type TabContentProps, type TabItem, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, Textarea, Toaster, type ToolBinding, ToolButton, type ToolButtonProps, type ToolButtonState, type ToolCallState, type ToolContextValue, ToolDataGrid, type ToolDataGridColumn, type ToolDataGridProps, type ToolDataGridRowAction, ToolErrorBoundary, type ToolErrorBoundaryProps, ToolForm, type ToolFormField, type ToolFormProps, ToolInput, type ToolInputProps, type ToolInputSuggestion, ToolProvider, type ToolProviderProps, type ToolResultConfig, ToolSelect, type ToolSelectOption, type ToolSelectProps, type ToolState, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseHostContextReturn, type UseMessageReturn, type UseResourceOptions, type UseResourceReturn, type UseToolInputPartialReturn, type UseToolInputReturn, type UseToolOptions, type UseToolResultReturn, type UseToolReturn, type UseToolStreamOptions, type UseToolStreamReturn, badgeVariants, buttonVariants, cn, normalizeToolBinding, useFormField, useGptApp, useGptTool, useHostContext, useMcpApp, useMessage, useResource, useTool, useToolContext, useToolInput, useToolInputPartial, useToolResult, useToolStream, useToolSubscription };