Skip to content

Commit 152b953

Browse files
docs: how to migrate from openai apps (#260)
* Create migrate_from_openai_apps.md * Update AGENTS.md * Update docs/migrate_from_openai_apps.md Co-authored-by: Jonathan Hefner <jonathan@hefner.pro> * address PR review comments - Remove AGENTS.md reference to migration guide - Add note that OpenAITransport is not yet available (PR #172) - Remove unnecessary note about return type ordering --------- Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
1 parent 574a768 commit 152b953

File tree

1 file changed

+197
-0
lines changed

1 file changed

+197
-0
lines changed

docs/migrate_from_openai_apps.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Migrating from OpenAI Apps SDK to MCP Apps SDK
2+
3+
This guide helps you migrate from the OpenAI Apps SDK (`window.openai.*`) to the MCP Apps SDK (`@modelcontextprotocol/ext-apps`).
4+
5+
## Quick Start Comparison
6+
7+
| OpenAI Apps SDK | MCP Apps SDK |
8+
| --------------------------------- | ---------------------------------- |
9+
| Implicit global (`window.openai`) | Explicit instance (`new App(...)`) |
10+
| Properties pre-populated on load | Async connection + notifications |
11+
| Sync property access | Getters + event handlers |
12+
13+
## Setup & Connection
14+
15+
| OpenAI | MCP Apps | Notes |
16+
| -------------------------------- | -------------------------------------------------- | ------------------------------------------------------ |
17+
| `window.openai` (auto-available) | `const app = new App({name, version}, {})` | MCP requires explicit instantiation |
18+
| (implicit) | `await app.connect()` | MCP requires async connection; auto-detects OpenAI env |
19+
|| `await app.connect(new OpenAITransport())` | Force OpenAI mode (not yet available, see [PR #172](https://github.com/modelcontextprotocol/ext-apps/pull/172)) |
20+
|| `await app.connect(new PostMessageTransport(...))` | Force MCP mode explicitly |
21+
22+
## Host Context Properties
23+
24+
| OpenAI | MCP Apps | Notes |
25+
| --------------------------- | --------------------------------------------- | --------------------------------------- |
26+
| `window.openai.theme` | `app.getHostContext()?.theme` | `"light"` \| `"dark"` |
27+
| `window.openai.locale` | `app.getHostContext()?.locale` | BCP 47 language tag (e.g., `"en-US"`) |
28+
| `window.openai.displayMode` | `app.getHostContext()?.displayMode` | `"inline"` \| `"pip"` \| `"fullscreen"` |
29+
| `window.openai.maxHeight` | `app.getHostContext()?.viewport?.maxHeight` | Max container height in px |
30+
| `window.openai.safeArea` | `app.getHostContext()?.safeAreaInsets` | `{ top, right, bottom, left }` |
31+
| `window.openai.userAgent` | `app.getHostContext()?.userAgent` | Host user agent string |
32+
|| `app.getHostContext()?.availableDisplayModes` | MCP adds: which modes host supports |
33+
|| `app.getHostContext()?.toolInfo` | MCP adds: tool metadata during call |
34+
35+
## Tool Data (Input/Output)
36+
37+
| OpenAI | MCP Apps | Notes |
38+
| ------------------------------------ | ---------------------------------------------------- | ----------------------------------- |
39+
| `window.openai.toolInput` | `app.ontoolinput = (params) => { params.arguments }` | Tool arguments; MCP uses callback |
40+
| `window.openai.toolOutput` | `app.ontoolresult = (params) => { params.content }` | Tool result; MCP uses callback |
41+
| `window.openai.toolResponseMetadata` | `app.ontoolresult``params._meta` | Widget-only metadata from server |
42+
|| `app.ontoolinputpartial = (params) => {...}` | MCP adds: streaming partial args |
43+
|| `app.ontoolcancelled = (params) => {...}` | MCP adds: cancellation notification |
44+
45+
## Calling Tools
46+
47+
| OpenAI | MCP Apps | Notes |
48+
| ------------------------------------------ | ----------------------------------------------------- | ---------------------------- |
49+
| `await window.openai.callTool(name, args)` | `await app.callServerTool({ name, arguments: args })` | Call another MCP server tool |
50+
51+
## Sending Messages
52+
53+
| OpenAI | MCP Apps | Notes |
54+
| ----------------------------------------------------- | ------------------------------------------------------------------------------------ | --------------------------------- |
55+
| `await window.openai.sendFollowUpMessage({ prompt })` | `await app.sendMessage({ role: "user", content: [{ type: "text", text: prompt }] })` | MCP uses structured content array |
56+
57+
## External Links
58+
59+
| OpenAI | MCP Apps | Notes |
60+
| -------------------------------------------- | ----------------------------------- | ------------------------------------ |
61+
| `await window.openai.openExternal({ href })` | `await app.openLink({ url: href })` | Different param name: `href``url` |
62+
63+
## Display Mode
64+
65+
| OpenAI | MCP Apps | Notes |
66+
| -------------------------------------------------- | --------------------------------------------------------- | ----------------------------------- |
67+
| `await window.openai.requestDisplayMode({ mode })` | `await app.requestDisplayMode({ mode })` | Same API |
68+
|| Check `app.getHostContext()?.availableDisplayModes` first | MCP lets you check what's available |
69+
70+
## Size Reporting
71+
72+
| OpenAI | MCP Apps | Notes |
73+
| --------------------------------------------- | ----------------------------------------- | ----------------------------------- |
74+
| `window.openai.notifyIntrinsicHeight(height)` | `app.sendSizeChanged({ width, height })` | MCP includes width |
75+
| Manual only | Auto via `{ autoResize: true }` (default) | MCP auto-reports via ResizeObserver |
76+
77+
## State Persistence
78+
79+
| OpenAI | MCP Apps | Notes |
80+
| ------------------------------------- | -------- | ----------------------------------------------- |
81+
| `window.openai.widgetState` || Not directly available in MCP |
82+
| `window.openai.setWidgetState(state)` || Use alternative mechanisms (`localStorage`, server-side state, etc.) |
83+
84+
## File Operations (Not Yet in MCP Apps)
85+
86+
| OpenAI | MCP Apps | Notes |
87+
| ---------------------------------------------------- | -------- | ------------------- |
88+
| `await window.openai.uploadFile(file)` || Not yet implemented |
89+
| `await window.openai.getFileDownloadUrl({ fileId })` || Not yet implemented |
90+
91+
## Other (Not Yet in MCP Apps)
92+
93+
| OpenAI | MCP Apps | Notes |
94+
| ------------------------------------------- | -------- | ------------------- |
95+
| `await window.openai.requestModal(options)` || Not yet implemented |
96+
| `window.openai.requestClose()` || Not yet implemented |
97+
| `window.openai.view` || Not yet mapped |
98+
99+
## Event Handling
100+
101+
| OpenAI | MCP Apps | Notes |
102+
| ------------------------------ | ------------------------------------------- | -------------------------------- |
103+
| Read `window.openai.*` on load | `app.ontoolinput = (params) => {...}` | Register before `connect()` |
104+
| Read `window.openai.*` on load | `app.ontoolresult = (params) => {...}` | Register before `connect()` |
105+
| Poll or re-read properties | `app.onhostcontextchanged = (ctx) => {...}` | MCP pushes context changes |
106+
|| `app.onteardown = async () => {...}` | MCP adds: cleanup before unmount |
107+
108+
## Logging
109+
110+
| OpenAI | MCP Apps | Notes |
111+
| ------------------ | --------------------------------------------- | ------------------------------- |
112+
| `console.log(...)` | `app.sendLog({ level: "info", data: "..." })` | MCP provides structured logging |
113+
114+
## Host Info
115+
116+
| OpenAI | MCP Apps | Notes |
117+
| ------ | --------------------------- | ------------------------------------------------- |
118+
|| `app.getHostVersion()` | Returns `{ name, version }` of host |
119+
|| `app.getHostCapabilities()` | Check `serverTools`, `openLinks`, `logging`, etc. |
120+
121+
## Full Migration Example
122+
123+
### Before (OpenAI)
124+
125+
```typescript
126+
// OpenAI Apps SDK
127+
const theme = window.openai.theme;
128+
const toolArgs = window.openai.toolInput;
129+
const toolResult = window.openai.toolOutput;
130+
131+
// Call a tool
132+
const result = await window.openai.callTool("get_weather", { city: "Tokyo" });
133+
134+
// Send a message
135+
await window.openai.sendFollowUpMessage({ prompt: "Weather updated!" });
136+
137+
// Report height
138+
window.openai.notifyIntrinsicHeight(400);
139+
140+
// Open link
141+
await window.openai.openExternal({ href: "https://example.com" });
142+
```
143+
144+
### After (MCP Apps)
145+
146+
```typescript
147+
import { App } from "@modelcontextprotocol/ext-apps";
148+
149+
const app = new App(
150+
{ name: "MyApp", version: "1.0.0" },
151+
{},
152+
{ autoResize: true }, // auto height reporting
153+
);
154+
155+
// Register handlers BEFORE connect
156+
app.ontoolinput = (params) => {
157+
console.log("Tool args:", params.arguments);
158+
};
159+
160+
app.ontoolresult = (params) => {
161+
console.log("Tool result:", params.content);
162+
};
163+
164+
app.onhostcontextchanged = (ctx) => {
165+
if (ctx.theme) applyTheme(ctx.theme);
166+
};
167+
168+
// Connect (auto-detects OpenAI vs MCP)
169+
await app.connect();
170+
171+
// Access context
172+
const theme = app.getHostContext()?.theme;
173+
174+
// Call a tool
175+
const result = await app.callServerTool({
176+
name: "get_weather",
177+
arguments: { city: "Tokyo" },
178+
});
179+
180+
// Send a message
181+
await app.sendMessage({
182+
role: "user",
183+
content: [{ type: "text", text: "Weather updated!" }],
184+
});
185+
186+
// Open link (note: url not href)
187+
await app.openLink({ url: "https://example.com" });
188+
```
189+
190+
## Key Differences Summary
191+
192+
1. **Initialization**: OpenAI is implicit; MCP requires `new App()` + `await app.connect()`
193+
2. **Data Flow**: OpenAI pre-populates; MCP uses async notifications (register handlers before `connect()`)
194+
3. **Auto-resize**: MCP has built-in ResizeObserver support via `autoResize` option
195+
4. **Structured Content**: MCP uses `{ type: "text", text: "..." }` arrays for messages
196+
5. **Context Changes**: MCP pushes updates via `onhostcontextchanged`; no polling needed
197+
6. **Capabilities**: MCP lets you check what the host supports before calling methods

0 commit comments

Comments
 (0)