mcpField
M
Migrate from OpenAI App

Migrate from OpenAI App

github.com/modelcontextprotocol開発3.0k91 回インストール1 日前に更新
リポジトリ

Migrate from OpenAI App について

既存の OpenAI Apps SDK アプリを MCP Apps SDK に移行するためのコーディングスキルです。サーバーとクライアントの変更、CSP・CORS 設定、実行時の確認を案内します。

主な機能

  1. 01OpenAI Apps から MCP Apps への移行
  2. 02サーバー・クライアント API の対応付け
  3. 03CSP オリジンの調査
  4. 04CORS 設定の案内
  5. 05移行確認チェックリスト

活用シーン

  1. 01既存の OpenAI アプリを MCP Apps に移行
  2. 02サーバーのツールとリソース登録を更新
  3. 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.tsApp クラス、ハンドラー、ライフサイクル
src/server/index.tsregisterAppTool、registerAppResource
src/spec.types.ts型定義
src/react/useApp.tsxReact アプリ用の 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)。オリジンが不足していても、エラーは表示されません。

移行コードを書く前に、アプリをビルドし、参照しているすべてのオリジンを調査してください。

  1. 既存のビルドコマンドを使ってアプリをビルドします
  2. 生成された HTML、CSS、JS を検索し、すべてのオリジンを調べます(「外部」オリジンだけではありません。すべてのネットワークリクエストに CSP の許可が必要です)
  3. 見つかった各オリジンについて、ソースまでたどります:
    • 定数に由来する場合 → 共通(開発環境と本番環境で同じ)
    • 環境変数または条件分岐に由来する場合 → その仕組みを記録し、開発環境と本番環境の両方の値を特定します
  4. 独自にリクエストを行う可能性のあるサードパーティライブラリ(分析、エラートラッキングなど)がないか確認します

調査結果を記録し、次の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.arguments
    window.openai.toolOutput古いグローバル → ontoolresult 内の params.structuredContent
    window.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 で読み込まれたら、以下を確認します。

  1. アプリがコンソールエラーなしで読み込まれる
  2. ontoolinput ハンドラーがツールの引数を受け取って実行される
  3. ontoolresult ハンドラーがツールの結果を受け取って実行される

コメント