Migrate from OpenAI App について
既存の OpenAI Apps SDK アプリを MCP Apps SDK に移行するためのコーディングスキルです。サーバーとクライアントの変更、CSP・CORS 設定、実行時の確認を案内します。
主な機能
- 01OpenAI Apps から MCP Apps への移行
- 02サーバー・クライアント API の対応付け
- 03CSP オリジンの調査
- 04CORS 設定の案内
- 05移行確認チェックリスト
活用シーン
- 01既存の OpenAI アプリを MCP Apps に移行
- 02サーバーのツールとリソース登録を更新
- 03React アプリを MCP Apps のライフサイクルに適合
MCP 対応
MCP Apps SDK への移行を案内します。この SDK は MCP リソースとツールを使い、会話型クライアントで動作するインタラクティブなアプリを構築します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ modelcontextprotocol/ ext-apps --skill migrate-from-openai-appインストール後、Claude Code で/migrate-from-openai-appを入力して読み込まれたか確認します。
詳細
OpenAI App から MCP への移行
既存の OpenAI Apps SDK アプリケーションを MCP Apps SDK(@modelcontextprotocol/ext-apps)に移行します。MCP Apps SDK は、会話型クライアントでインタラクティブな UI を実現する、標準化されたオープンなプロトコルを提供します。
ベストプラクティス
- バージョン番号を手動で記述するのではなく、パッケージマネージャーを使って依存関係を追加してください(例:
npm install、pnpm add、yarn add)。これにより、パッケージマネージャーが互換性のある最新バージョンを解決できます。記憶を頼りにバージョン番号を指定しないでください。 - 最後の TODO 項目として、次の文言をそのまま追加してください:「このスキルの『完了前』チェックリストを読み直し、各チェックボックスに個別に対応してから、この TODO を完了としてマークしてください。対応した内容もそれぞれ記載してください。」
リファレンスコードの取得
完全な移行ドキュメントと動作するサンプルを参照するには、SDK リポジトリをクローンしてください。
git clone --branch "v$(npm view @modelcontextprotocol/ext-apps version)" --depth 1 https://github.com/modelcontextprotocol/ext-apps.git /tmp/mcp-ext-apps
移行リファレンスガイド
「移行前/移行後」の対応表がある移行リファレンスガイドを読んでください:/tmp/mcp-ext-apps/docs/migrate_from_openai_apps.md
API リファレンス(ソースファイル)
/tmp/mcp-ext-apps/src/* の JSDoc ドキュメントを直接読んでください:
| ファイル | 内容 |
|---|---|
src/app.ts | App クラス、ハンドラー、ライフサイクル |
src/server/index.ts | registerAppTool、registerAppResource |
src/spec.types.ts | 型定義 |
src/react/useApp.tsx | React アプリ用の useApp フック |
src/react/use*.ts* | React アプリ用のその他の use* フック |
フロントエンドフレームワークのサンプル
フロントエンドフレームワーク別に整理された基本的な SDK の使用例は、/tmp/mcp-ext-apps/examples/basic-server-{framework}/ を参照してください:
| テンプレート | 主なファイル |
|---|---|
basic-server-vanillajs/ | server.ts、src/mcp-app.ts、mcp-app.html |
basic-server-react/ | server.ts、src/mcp-app.tsx(useApp フックを使用) |
basic-server-vue/ | server.ts、src/App.vue |
basic-server-svelte/ | server.ts、src/App.svelte |
basic-server-preact/ | server.ts、src/mcp-app.tsx |
basic-server-solid/ | server.ts、src/mcp-app.tsx |
CSP の調査
MCP Apps の HTML はウェブページではなく MCP リソースとして提供され、同一オリジンのサーバーを持たないサンドボックス化された iframe 内で実行されます。すべてのオリジンを CSP に宣言する必要があります。JS/CSS バンドルを配信するオリジンも対象です(開発環境では localhost、本番環境では CDN)。オリジンが不足していても、エラーは表示されません。
移行コードを書く前に、アプリをビルドし、参照しているすべてのオリジンを調査してください。
- 既存のビルドコマンドを使ってアプリをビルドします
- 生成された HTML、CSS、JS を検索し、すべてのオリジンを調べます(「外部」オリジンだけではありません。すべてのネットワークリクエストに CSP の許可が必要です)
- 見つかった各オリジンについて、ソースまでたどります:
- 定数に由来する場合 → 共通(開発環境と本番環境で同じ)
- 環境変数または条件分岐に由来する場合 → その仕組みを記録し、開発環境と本番環境の両方の値を特定します
- 独自にリクエストを行う可能性のあるサードパーティライブラリ(分析、エラートラッキングなど)がないか確認します
調査結果を記録し、次の3つのリストに分けて、各オリジンが共通、開発環境のみ、本番環境のみのどれに該当するか記載してください。
- resourceDomains:画像、フォント、スタイル、スクリプトを配信するオリジン
- connectDomains:API/fetch リクエストのオリジン
- frameDomains:ネストされた iframe のオリジン
オリジンが見つからない場合、アプリにカスタム CSP ドメインは必要ない可能性があります。
CORS の設定
MCP クライアントはクロスオリジンリクエストを送信します。Express を使用している場合は、app.use(cors()) で対応できます。
生の HTTP サーバーでは、標準的な CORS を設定し、さらに次の項目を設定してください。
- 許可するヘッダー:
mcp-session-id、mcp-protocol-version、last-event-id - 公開するヘッダー:
mcp-session-id
主な概念上の変更点
サーバー側
生の server.registerTool()/server.registerResource() ではなく、registerAppTool() と registerAppResource() のヘルパーを使用してください。これらのヘルパーは MCP Apps のメタデータ形式を自動的に処理します。
サーバー側の対応表については、/tmp/mcp-ext-apps/docs/migrate_from_openai_apps.md を参照してください。
クライアント側
基本的なパラダイムの変化は、OpenAI ではコードの実行前に値が設定される同期グローバルオブジェクト(window.openai.toolInput、window.openai.theme)を使用するのに対し、MCP Apps では非同期イベントハンドラーを備えた App インスタンスを使用することです。
主な違い:
connect()を呼び出す前に、Appインスタンスを作成してハンドラー(ontoolinput、ontoolresult、onhostcontextchanged)を登録します。(接続直後にイベントが発生する可能性があるため、先にハンドラーを登録する必要があります。)- ハンドラーを介してツールデータにアクセスします。
app.ontoolinputはwindow.openai.toolInputに、app.ontoolresultはwindow.openai.toolOutputに対応します。 app.getHostContext()を介してホスト環境(テーマ、ロケールなど)にアクセスします。
React アプリでは、useApp フックがこのライフサイクルを自動的に管理します。パターンについては basic-server-react/ を参照してください。
クライアント側の対応表については、/tmp/mcp-ext-apps/docs/migrate_from_openai_apps.md を参照してください。
MCP Apps ではまだ利用できない機能
以下の OpenAI 機能には、まだ MCP の同等機能がありません。
サーバー側:
| OpenAI 機能 | 状況/回避策 |
|---|---|
_meta["openai/toolInvocation/invoking"] / _meta["openai/toolInvocation/invoked"] | 進行状況インジケーターはまだ利用できません |
_meta["openai/widgetDescription"] | 動的なコンテキストには app.updateModelContext() を使用します |
クライアント側:
| OpenAI 機能 | 状況/回避策 |
|---|---|
window.openai.widgetState / setWidgetState() | localStorage またはサーバー側の状態を使用します |
window.openai.uploadFile() / getFileDownloadUrl() | ファイル操作はまだ利用できません |
window.openai.requestModal() / requestClose() | モーダル管理はまだ利用できません |
window.openai.view | まだ利用できません |
完了前の確認事項
以下のチェックリストの各項目を、時間をかけて丁寧に確認してください。
-
サーバー側に OpenAI のパターンが残っていないか検索し、移行します。
パターン 意味 "openai/古いメタデータキー → _meta.ui.*text/html+skybridge古い MIME タイプ → RESOURCE_MIME_TYPE定数text/html;profile=mcp-app新しい MIME タイプですが、 RESOURCE_MIME_TYPE定数の使用を推奨します_domains"または_domains:snake_case の CSP → camelCase( connect_domains→connectDomains) -
クライアント側に OpenAI のパターンが残っていないか検索し、移行します。
パターン 意味 window.openai.toolInput古いグローバル → ontoolinputハンドラー内のparams.argumentswindow.openai.toolOutput古いグローバル → ontoolresult内のparams.structuredContentwindow.openai古いグローバル API → Appインスタンスのメソッド -
CSP の調査で特定した各オリジンが、
registerAppResource()の CSP 設定のどこに記載されているかを確認します。CSP の調査で特定したすべてのオリジン(全環境共通、開発環境のみ、本番環境のみ)を CSP 設定に含める必要があります。MCP Apps の HTML は、同一オリジンのサーバーがないサンドボックス化された iframe 内で実行されます。CSP 設定に含まれていないオリジンがあれば、今すぐ追加してください。 -
CSP の調査で特定した条件付き(開発環境のみ、本番環境のみ)の各オリジンについて、同じ設定項目(環境変数、設定ファイルなど)が実行時 URL と CSP エントリーの両方を制御している箇所を確認します。条件付きにすべきオリジンが CSP にハードコードされている場合は、今すぐ修正してください。アプリは本番環境で使用できる状態でなければなりません。
テスト
basic-host を使用する
basic-host のサンプルで移行したアプリをテストします。
# Terminal 1: Build and run your server
npm run build && npm run serve
# Terminal 2: Run basic-host (from cloned repo)
cd /tmp/mcp-ext-apps/examples/basic-host
npm install
SERVERS='["http://localhost:3001/mcp"]' npm run start
# Open http://localhost:8080
実行時の動作を確認する
アプリが basic-host で読み込まれたら、以下を確認します。
- アプリがコンソールエラーなしで読み込まれる
ontoolinputハンドラーがツールの引数を受け取って実行されるontoolresultハンドラーがツールの結果を受け取って実行される