@@ -16,7 +16,6 @@ import {
1616 PingRequestSchema ,
1717} from "@modelcontextprotocol/sdk/types.js" ;
1818import { AppNotification , AppRequest , AppResult } from "./types" ;
19- import { PostMessageTransport } from "./message-transport" ;
2019import {
2120 LATEST_PROTOCOL_VERSION ,
2221 McpUiAppCapabilities ,
@@ -47,8 +46,12 @@ import {
4746 McpUiRequestDisplayModeResultSchema ,
4847} from "./types" ;
4948import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js" ;
49+ import { PostMessageTransport } from "./message-transport" ;
50+ import { OpenAITransport , isOpenAIEnvironment } from "./openai/transport.js" ;
5051
5152export { PostMessageTransport } from "./message-transport" ;
53+ export { OpenAITransport , isOpenAIEnvironment } from "./openai/transport" ;
54+ export * from "./openai/types" ;
5255export * from "./types" ;
5356export {
5457 applyHostStyleVariables ,
@@ -100,7 +103,7 @@ export const RESOURCE_MIME_TYPE = "text/html;profile=mcp-app";
100103 *
101104 * @see ProtocolOptions from @modelcontextprotocol/sdk for inherited options
102105 */
103- type AppOptions = ProtocolOptions & {
106+ export type AppOptions = ProtocolOptions & {
104107 /**
105108 * Automatically report size changes to the host using ResizeObserver.
106109 *
@@ -111,6 +114,19 @@ type AppOptions = ProtocolOptions & {
111114 * @default true
112115 */
113116 autoResize ?: boolean ;
117+
118+ /**
119+ * Enable experimental OpenAI compatibility.
120+ *
121+ * When enabled (default), the App will auto-detect the environment:
122+ * - If `window.openai` exists → use OpenAI Apps SDK
123+ * - Otherwise → use MCP Apps protocol via PostMessageTransport
124+ *
125+ * Set to `false` to force MCP-only mode.
126+ *
127+ * @default true
128+ */
129+ experimentalOAICompatibility ?: boolean ;
114130} ;
115131
116132type RequestHandlerExtra = Parameters <
@@ -219,7 +235,10 @@ export class App extends Protocol<AppRequest, AppNotification, AppResult> {
219235 constructor (
220236 private _appInfo : Implementation ,
221237 private _capabilities : McpUiAppCapabilities = { } ,
222- private options : AppOptions = { autoResize : true } ,
238+ private options : AppOptions = {
239+ autoResize : true ,
240+ experimentalOAICompatibility : true ,
241+ } ,
223242 ) {
224243 super ( options ) ;
225244
@@ -988,47 +1007,73 @@ export class App extends Protocol<AppRequest, AppNotification, AppResult> {
9881007 return ( ) => resizeObserver . disconnect ( ) ;
9891008 }
9901009
1010+ /**
1011+ * Create the default transport based on detected platform.
1012+ * @internal
1013+ */
1014+ private createDefaultTransport ( ) : Transport {
1015+ const experimentalOAI = this . options ?. experimentalOAICompatibility ?? true ;
1016+ if ( experimentalOAI && isOpenAIEnvironment ( ) ) {
1017+ return new OpenAITransport ( ) ;
1018+ }
1019+ return new PostMessageTransport ( window . parent ) ;
1020+ }
1021+
9911022 /**
9921023 * Establish connection with the host and perform initialization handshake.
9931024 *
9941025 * This method performs the following steps:
995- * 1. Connects the transport layer
996- * 2. Sends `ui/initialize` request with app info and capabilities
997- * 3. Receives host capabilities and context in response
998- * 4. Sends `ui/notifications/initialized` notification
999- * 5. Sets up auto-resize using {@link setupSizeChangedNotifications} if enabled (default)
1026+ * 1. Auto-detects platform if no transport is provided
1027+ * 2. Connects the transport layer
1028+ * 3. Sends `ui/initialize` request with app info and capabilities
1029+ * 4. Receives host capabilities and context in response
1030+ * 5. Sends `ui/notifications/initialized` notification
1031+ * 6. Sets up auto-resize using {@link setupSizeChangedNotifications} if enabled (default)
1032+ * 7. For OpenAI mode: delivers initial tool input/result from window.openai
10001033 *
10011034 * If initialization fails, the connection is automatically closed and an error
10021035 * is thrown.
10031036 *
1004- * @param transport - Transport layer (typically PostMessageTransport)
1037+ * @param transport - Optional transport layer. If not provided, auto-detects
1038+ * based on the `platform` option:
1039+ * - `'openai'` or `window.openai` exists → uses {@link OpenAITransport}
1040+ * - `'mcp'` or no `window.openai` → uses {@link PostMessageTransport}
10051041 * @param options - Request options for the initialize request
10061042 *
10071043 * @throws {Error } If initialization fails or connection is lost
10081044 *
1009- * @example Connect with PostMessageTransport
1045+ * @example Auto-detect platform (recommended)
10101046 * ```typescript
10111047 * const app = new App(
10121048 * { name: "MyApp", version: "1.0.0" },
10131049 * {}
10141050 * );
10151051 *
1016- * try {
1017- * await app.connect(new PostMessageTransport(window.parent));
1018- * console.log("Connected successfully!");
1019- * } catch (error) {
1020- * console.error("Failed to connect:", error);
1021- * }
1052+ * // Auto-detects: OpenAI if window.openai exists, MCP otherwise
1053+ * await app.connect();
1054+ * ```
1055+ *
1056+ * @example Explicit MCP transport
1057+ * ```typescript
1058+ * await app.connect(new PostMessageTransport(window.parent));
1059+ * ```
1060+ *
1061+ * @example Explicit OpenAI transport
1062+ * ```typescript
1063+ * await app.connect(new OpenAITransport());
10221064 * ```
10231065 *
10241066 * @see {@link McpUiInitializeRequest } for the initialization request structure
10251067 * @see {@link McpUiInitializedNotification } for the initialized notification
1026- * @see {@link PostMessageTransport } for the typical transport implementation
1068+ * @see {@link PostMessageTransport } for MCP-compatible hosts
1069+ * @see {@link OpenAITransport } for OpenAI/ChatGPT hosts
10271070 */
10281071 override async connect (
1029- transport : Transport = new PostMessageTransport ( window . parent ) ,
1072+ transport ? : Transport ,
10301073 options ?: RequestOptions ,
10311074 ) : Promise < void > {
1075+ transport ??= this . createDefaultTransport ( ) ;
1076+
10321077 await super . connect ( transport ) ;
10331078
10341079 try {
@@ -1060,6 +1105,11 @@ export class App extends Protocol<AppRequest, AppNotification, AppResult> {
10601105 if ( this . options ?. autoResize ) {
10611106 this . setupSizeChangedNotifications ( ) ;
10621107 }
1108+
1109+ // For OpenAI mode: deliver initial state from window.openai
1110+ if ( transport instanceof OpenAITransport ) {
1111+ transport . deliverInitialState ( ) ;
1112+ }
10631113 } catch ( error ) {
10641114 // Disconnect if initialization fails.
10651115 void this . close ( ) ;
0 commit comments