@creature-ai/sdk 0.1.1 → 0.1.3

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.
@@ -1,7 +1,196 @@
1
- import { g as StateListener, f as HostClientEvents, e as HostClientState, H as HostClient, d as HostClientConfig, T as ToolResult, W as WidgetState, L as LogLevel, E as Environment, a as AppSessionState, b as AppSessionListener } from '../types-DcoqlK46.js';
2
- export { A as AppSessionOptions, c as HostContext, S as StructuredWidgetState } from '../types-DcoqlK46.js';
3
1
  export { applyDocumentTheme, applyHostFonts, applyHostStyleVariables, getDocumentTheme } from '@modelcontextprotocol/ext-apps';
4
2
 
3
+ /**
4
+ * Core types for the MCP SDK.
5
+ * These are framework-agnostic and shared between vanilla JS and React.
6
+ */
7
+ /**
8
+ * Environment types for host detection.
9
+ */
10
+ type Environment = "chatgpt" | "mcp-apps" | "standalone";
11
+ /**
12
+ * Display modes for UI resources.
13
+ * - "inline": Embedded within the conversation flow
14
+ * - "pip": Picture-in-picture floating panel
15
+ * - "fullscreen": Full-screen overlay
16
+ */
17
+ type DisplayMode = "inline" | "pip" | "fullscreen";
18
+ /**
19
+ * Log severity levels matching MCP protocol LoggingLevel.
20
+ * These are displayed in the host's DevConsole with appropriate colors.
21
+ */
22
+ type LogLevel = "debug" | "info" | "notice" | "warning" | "error";
23
+ /**
24
+ * Structured widget state format (ChatGPT-compatible).
25
+ * Allows separating model-visible content from private UI state.
26
+ */
27
+ interface StructuredWidgetState {
28
+ /** Content visible to the AI model on follow-up turns */
29
+ modelContent?: string | Record<string, unknown> | null;
30
+ /** UI-only state, hidden from model */
31
+ privateContent?: Record<string, unknown> | null;
32
+ /** File IDs for images the model can see */
33
+ imageIds?: string[];
34
+ }
35
+ /**
36
+ * Widget state can be structured (with modelContent/privateContent)
37
+ * or a simple key-value object.
38
+ */
39
+ type WidgetState = StructuredWidgetState | Record<string, unknown>;
40
+ /**
41
+ * Tool call result structure.
42
+ */
43
+ interface ToolResult<T = Record<string, unknown>> {
44
+ content?: Array<{
45
+ type: string;
46
+ text: string;
47
+ }>;
48
+ structuredContent?: T;
49
+ isError?: boolean;
50
+ source?: "agent" | "ui";
51
+ }
52
+ /**
53
+ * Host context sent from MCP Apps host.
54
+ * Follows MCP Apps spec with Creature extensions via [key: string]: unknown.
55
+ */
56
+ interface HostContext {
57
+ theme?: "light" | "dark";
58
+ styles?: {
59
+ variables?: Record<string, string>;
60
+ };
61
+ displayMode?: DisplayMode;
62
+ availableDisplayModes?: DisplayMode[];
63
+ viewport?: {
64
+ width: number;
65
+ height: number;
66
+ };
67
+ platform?: string;
68
+ /**
69
+ * Widget state restored from previous widget instance.
70
+ * Creature extension - passed via hostContext on ui/initialize.
71
+ */
72
+ widgetState?: WidgetState;
73
+ }
74
+ /**
75
+ * Configuration for creating a host client.
76
+ */
77
+ interface HostClientConfig {
78
+ /** Name of the client (for protocol handshake) */
79
+ name: string;
80
+ /** Version of the client */
81
+ version: string;
82
+ }
83
+ /**
84
+ * State managed by the host client.
85
+ */
86
+ interface HostClientState {
87
+ /** Whether the host connection is ready */
88
+ isReady: boolean;
89
+ /** The detected environment */
90
+ environment: Environment;
91
+ /** Current widget state */
92
+ widgetState: WidgetState | null;
93
+ }
94
+ /**
95
+ * Event handlers that can be registered on the host client.
96
+ */
97
+ interface HostClientEvents {
98
+ /** Called when tool input is received (before execution) */
99
+ "tool-input": (args: Record<string, unknown>) => void;
100
+ /** Called when tool result is received */
101
+ "tool-result": (result: ToolResult) => void;
102
+ /** Called when theme changes (MCP Apps only) */
103
+ "theme-change": (theme: "light" | "dark") => void;
104
+ /** Called when host requests teardown (MCP Apps only) */
105
+ teardown: () => Promise<void> | void;
106
+ /** Called when widget state changes (restored or updated) */
107
+ "widget-state-change": (widgetState: WidgetState | null) => void;
108
+ }
109
+ /**
110
+ * Listener for state changes.
111
+ */
112
+ type StateListener = (state: HostClientState, prevState: HostClientState) => void;
113
+ /**
114
+ * Host client interface.
115
+ * Implemented by McpAppHostClient and ChatGptAppHostClient.
116
+ */
117
+ interface HostClient {
118
+ /** Get current state */
119
+ getState(): HostClientState;
120
+ /** Subscribe to state changes. Returns unsubscribe function. */
121
+ subscribe(listener: StateListener): () => void;
122
+ /** Call a tool on the MCP server */
123
+ callTool<T = Record<string, unknown>>(toolName: string, args: Record<string, unknown>): Promise<ToolResult<T>>;
124
+ /** Send a notification to the host (MCP Apps only, no-op on ChatGPT) */
125
+ sendNotification(method: string, params: unknown): void;
126
+ /** Set widget state */
127
+ setWidgetState(state: WidgetState | null): void;
128
+ /**
129
+ * Request a display mode change from the host.
130
+ *
131
+ * The host may refuse or coerce the request (e.g., "pip" → "fullscreen" on mobile).
132
+ * Always check `availableDisplayModes` in host context before calling, and handle
133
+ * the returned mode differing from the requested mode.
134
+ *
135
+ * @param params - Object containing the requested display mode
136
+ * @returns Promise resolving to the actual display mode granted by the host
137
+ */
138
+ requestDisplayMode(params: {
139
+ mode: DisplayMode;
140
+ }): Promise<{
141
+ mode: DisplayMode;
142
+ }>;
143
+ /**
144
+ * Send a log message to the host's DevConsole.
145
+ *
146
+ * Logs are sent via the MCP protocol's `notifications/message` notification
147
+ * and displayed in the host's unified log viewer alongside server logs.
148
+ *
149
+ * @param level - Log severity level
150
+ * @param message - Log message
151
+ * @param data - Optional structured data to include
152
+ */
153
+ log(level: LogLevel, message: string, data?: Record<string, unknown>): void;
154
+ /** Register an event handler. Returns unsubscribe function. */
155
+ on<K extends keyof HostClientEvents>(event: K, handler: HostClientEvents[K]): () => void;
156
+ /** Start listening for host messages */
157
+ connect(): void;
158
+ /** Stop listening for host messages */
159
+ disconnect(): void;
160
+ }
161
+ /**
162
+ * WebSocket connection status.
163
+ */
164
+ type WebSocketStatus = "disconnected" | "connecting" | "connected" | "error";
165
+ /**
166
+ * Configuration for creating a WebSocket client.
167
+ */
168
+ interface WebSocketClientConfig<TReceive = unknown> {
169
+ /** Called when a message is received */
170
+ onMessage?: (message: TReceive) => void;
171
+ /** Called when connection status changes */
172
+ onStatusChange?: (status: WebSocketStatus, error?: string) => void;
173
+ /** Whether to auto-reconnect on disconnect (default: true) */
174
+ reconnect?: boolean;
175
+ /** Base interval for reconnection attempts in ms (default: 1000) */
176
+ reconnectInterval?: number;
177
+ }
178
+ /**
179
+ * WebSocket client interface.
180
+ */
181
+ interface WebSocketClient<TSend = unknown, TReceive = unknown> {
182
+ /** Current connection status */
183
+ readonly status: WebSocketStatus;
184
+ /** Error message if status is "error" */
185
+ readonly error: string | undefined;
186
+ /** Connect to the WebSocket server */
187
+ connect(): void;
188
+ /** Disconnect from the WebSocket server */
189
+ disconnect(): void;
190
+ /** Send a message to the server */
191
+ send(message: TSend): void;
192
+ }
193
+
5
194
  declare abstract class Subscribable {
6
195
  private stateListeners;
7
196
  private eventHandlers;
@@ -20,14 +209,16 @@ declare abstract class Subscribable {
20
209
  * with the ChatGPT host client. Handles the protocol handshake, tool calls,
21
210
  * notifications, and automatic style/theme application.
22
211
  */
23
- declare class McpHostClient extends Subscribable implements HostClient {
212
+ declare class McpAppHostClient extends Subscribable implements HostClient {
24
213
  private state;
25
214
  private config;
26
215
  private app;
27
216
  private connected;
28
217
  constructor(config: HostClientConfig);
218
+ /**
219
+ * Get the current client state.
220
+ */
29
221
  getState(): HostClientState;
30
- private setState;
31
222
  /**
32
223
  * Connect to the MCP Apps host.
33
224
  *
@@ -36,20 +227,6 @@ declare class McpHostClient extends Subscribable implements HostClient {
36
227
  * with host context including theme, styles, and widgetState.
37
228
  */
38
229
  connect(): void;
39
- /**
40
- * Set up notification handlers on the App instance.
41
- *
42
- * Maps the official SDK's callback pattern to our event emitter pattern,
43
- * allowing consumers to use `.on("tool-result", ...)` etc.
44
- */
45
- private setupHandlers;
46
- /**
47
- * Initiate connection using PostMessageTransport.
48
- *
49
- * The SDK's App.connect() handles the protocol handshake correctly:
50
- * the guest (App) sends `ui/initialize` to the host.
51
- */
52
- private initiateConnection;
53
230
  /**
54
231
  * Disconnect from the host.
55
232
  *
@@ -89,6 +266,11 @@ declare class McpHostClient extends Subscribable implements HostClient {
89
266
  * @param state - New widget state (or null to clear)
90
267
  */
91
268
  setWidgetState(state: WidgetState | null): void;
269
+ requestDisplayMode(params: {
270
+ mode: DisplayMode;
271
+ }): Promise<{
272
+ mode: DisplayMode;
273
+ }>;
92
274
  /**
93
275
  * Send a log message to the host's DevConsole.
94
276
  *
@@ -96,15 +278,44 @@ declare class McpHostClient extends Subscribable implements HostClient {
96
278
  * to the host. Logs appear in the unified DevConsole alongside server logs,
97
279
  * with appropriate color coding based on level.
98
280
  *
99
- * The logger name is automatically set to the app name from config.
100
- *
101
281
  * @param level - Log severity level (debug, info, notice, warning, error)
102
282
  * @param message - Log message
103
283
  * @param data - Optional structured data to include with the log
104
284
  */
105
285
  log(level: LogLevel, message: string, data?: Record<string, unknown>): void;
286
+ /**
287
+ * Update internal state and notify listeners.
288
+ */
289
+ private setState;
290
+ /**
291
+ * Set up notification handlers on the App instance.
292
+ *
293
+ * Maps the official SDK's callback pattern to our event emitter pattern,
294
+ * allowing consumers to use `.on("tool-result", ...)` etc.
295
+ */
296
+ private setupHandlers;
297
+ /**
298
+ * Initiate connection using PostMessageTransport.
299
+ *
300
+ * The SDK's App.connect() handles the protocol handshake correctly:
301
+ * the guest (App) sends `ui/initialize` to the host.
302
+ */
303
+ private initiateConnection;
304
+ /**
305
+ * Apply theme, styles, and fonts from host context.
306
+ */
307
+ private applyHostContext;
308
+ /**
309
+ * Extract text content from SDK result content array.
310
+ * Filters to only include text items since our ToolResult type expects text.
311
+ */
312
+ private extractTextContent;
106
313
  }
107
314
 
315
+ /**
316
+ * OpenAI bridge interface exposed by ChatGPT Apps SDK.
317
+ * Available on `window.openai` when running inside ChatGPT.
318
+ */
108
319
  interface OpenAIBridge {
109
320
  toolOutput?: Record<string, unknown>;
110
321
  widgetState?: WidgetState;
@@ -116,39 +327,108 @@ interface OpenAIBridge {
116
327
  text?: string;
117
328
  }>;
118
329
  }>;
330
+ requestDisplayMode?: (args: {
331
+ mode: string;
332
+ }) => Promise<{
333
+ mode: string;
334
+ }>;
119
335
  }
120
336
  declare global {
121
337
  interface Window {
122
338
  openai?: OpenAIBridge;
123
339
  }
124
340
  }
125
- declare class ChatGPTHostClient extends Subscribable implements HostClient {
341
+ /**
342
+ * ChatGPT Apps host client implementation.
343
+ *
344
+ * Bridges the ChatGPT Apps SDK (`window.openai`) to provide a consistent
345
+ * interface with the MCP Apps host client. Handles initial data processing,
346
+ * globals updates, and widget state synchronization.
347
+ */
348
+ declare class ChatGptAppHostClient extends Subscribable implements HostClient {
126
349
  private state;
127
350
  private config;
128
351
  private connected;
129
352
  private hasProcessedInitialData;
130
353
  private globalsHandler;
131
354
  constructor(config: HostClientConfig);
355
+ /**
356
+ * Get the current client state.
357
+ */
132
358
  getState(): HostClientState;
133
- private setState;
359
+ /**
360
+ * Connect to the ChatGPT host.
361
+ *
362
+ * Processes initial data from `window.openai` and sets up a listener
363
+ * for subsequent `openai:set_globals` events.
364
+ */
134
365
  connect(): void;
366
+ /**
367
+ * Disconnect from the host.
368
+ *
369
+ * Removes the globals event listener.
370
+ */
135
371
  disconnect(): void;
136
- private processInitialData;
137
- private setupGlobalsListener;
372
+ /**
373
+ * Call a tool on the MCP server via the ChatGPT bridge.
374
+ *
375
+ * @param toolName - Name of the tool to call
376
+ * @param args - Arguments to pass to the tool
377
+ * @returns Tool result with content and structuredContent
378
+ */
138
379
  callTool<T = Record<string, unknown>>(toolName: string, args: Record<string, unknown>): Promise<ToolResult<T>>;
380
+ /**
381
+ * Send a notification to the host.
382
+ *
383
+ * No-op on ChatGPT — notifications are not supported.
384
+ */
139
385
  sendNotification(_method: string, _params: unknown): void;
386
+ /**
387
+ * Set widget state and sync with the ChatGPT host.
388
+ *
389
+ * @param state - New widget state (or null to clear)
390
+ */
140
391
  setWidgetState(state: WidgetState | null): void;
141
392
  /**
142
393
  * Log a message to the console.
143
394
  *
144
395
  * ChatGPT doesn't have a DevConsole, so logs go to browser console only.
145
- * This provides API parity with McpHostClient.
396
+ * This provides API parity with McpAppHostClient.
146
397
  *
147
398
  * @param level - Log severity level
148
399
  * @param message - Log message
149
400
  * @param data - Optional structured data
150
401
  */
151
402
  log(level: LogLevel, message: string, data?: Record<string, unknown>): void;
403
+ /**
404
+ * Update internal state and notify listeners.
405
+ */
406
+ private setState;
407
+ /**
408
+ * Process initial data from `window.openai`.
409
+ *
410
+ * Called once on connect to handle any tool output or widget state
411
+ * that was set before the client connected.
412
+ */
413
+ private processInitialData;
414
+ /**
415
+ * Set up listener for `openai:set_globals` events.
416
+ *
417
+ * ChatGPT dispatches this event when tool output or widget state
418
+ * changes after initial load.
419
+ */
420
+ private setupGlobalsListener;
421
+ /**
422
+ * Request a display mode change from the ChatGPT host.
423
+ *
424
+ * @param params - Display mode to request
425
+ * @returns The resulting display mode
426
+ */
427
+ requestDisplayMode(params: {
428
+ mode: DisplayMode;
429
+ }): Promise<{
430
+ mode: DisplayMode;
431
+ }>;
152
432
  }
153
433
 
154
434
  /**
@@ -163,53 +443,15 @@ declare class ChatGPTHostClient extends Subscribable implements HostClient {
163
443
  */
164
444
  declare function detectEnvironment(): Environment;
165
445
 
166
- type PartialState<TState extends AppSessionState> = {
167
- [K in keyof TState]?: Partial<TState[K]> | TState[K];
168
- };
169
- declare class AppSession<TInternal extends Record<string, unknown> = Record<string, unknown>, TBackend extends Record<string, unknown> = Record<string, unknown>, TUi extends WidgetState | null = WidgetState | null> {
170
- readonly id: string;
171
- private _state;
172
- private listeners;
173
- private hostClient;
174
- private hostUnsubscribe;
175
- constructor(initialState?: Partial<AppSessionState<TInternal, TBackend, TUi>>, options?: {
176
- id?: string;
177
- });
178
- private generateId;
179
- get state(): AppSessionState<TInternal, TBackend, TUi>;
180
- get internal(): TInternal;
181
- get backend(): TBackend;
182
- get ui(): TUi;
183
- subscribe(listener: AppSessionListener<AppSessionState<TInternal, TBackend, TUi>>): () => void;
184
- private notify;
185
- setState(partial: PartialState<AppSessionState<TInternal, TBackend, TUi>>): void;
186
- setInternal(internal: TInternal | Partial<TInternal>): void;
187
- setBackend(backend: TBackend | Partial<TBackend>): void;
188
- setUi(ui: TUi): void;
189
- updateUi(partial: TUi extends null ? never : Partial<NonNullable<TUi>>): void;
190
- bindHost(host: HostClient): () => void;
191
- unbindHost(): void;
192
- injectAppSessionId<T extends Record<string, unknown>>(data: T): T & {
193
- appSessionId: string;
194
- };
195
- }
196
-
197
- type ChannelStatus = "disconnected" | "connecting" | "connected" | "error";
198
- interface ChannelClientConfig<TReceive = unknown> {
199
- onMessage?: (message: TReceive) => void;
200
- onStatusChange?: (status: ChannelStatus, error?: string) => void;
201
- reconnect?: boolean;
202
- reconnectInterval?: number;
203
- }
204
- interface ChannelClient<TSend = unknown, TReceive = unknown> {
205
- readonly status: ChannelStatus;
206
- readonly error: string | undefined;
207
- connect(): void;
208
- disconnect(): void;
209
- send(message: TSend): void;
210
- }
211
- declare function createChannel<TSend = unknown, TReceive = unknown>(url: string, config?: ChannelClientConfig<TReceive>): ChannelClient<TSend, TReceive>;
446
+ /**
447
+ * Create a WebSocket client with automatic reconnection.
448
+ *
449
+ * @param url - WebSocket server URL
450
+ * @param config - Client configuration
451
+ * @returns WebSocket client instance
452
+ */
453
+ declare function createWebSocket<TSend = unknown, TReceive = unknown>(url: string, config?: WebSocketClientConfig<TReceive>): WebSocketClient<TSend, TReceive>;
212
454
 
213
455
  declare function createHost(config: HostClientConfig): HostClient;
214
456
 
215
- export { AppSession, AppSessionListener, AppSessionState, type ChannelClient, type ChannelClientConfig, type ChannelStatus, ChatGPTHostClient, Environment, HostClient, HostClientConfig, HostClientEvents, HostClientState, LogLevel, McpHostClient, StateListener, ToolResult, WidgetState, createChannel, createHost, detectEnvironment };
457
+ export { ChatGptAppHostClient, type DisplayMode, type Environment, type HostClient, type HostClientConfig, type HostClientEvents, type HostClientState, type HostContext, type LogLevel, McpAppHostClient, type StateListener, type StructuredWidgetState, type ToolResult, type WebSocketClient, type WebSocketClientConfig, type WebSocketStatus, type WidgetState, createHost, createWebSocket, detectEnvironment };