mcpField
C
create-mcp-app

create-mcp-app

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

create-mcp-app について

create-mcp-appは、MCP対応ホスト内で動作するインタラクティブなUIを構築するためのスキルです。MCPツールとHTMLリソースの組み合わせ方を案内し、フレームワーク例、実装手順、ローカルテスト方法を提供します。

主な機能

  1. 01MCPツールとHTMLリソースの組み合わせ
  2. 02ReactなどのUIフレームワーク向けガイド
  3. 03既存サーバーへのアプリ追加例
  4. 04ホストコンテキスト、ストリーミング、ビュー状態のパターン
  5. 05リファレンスホストを使ったローカルテスト

活用シーン

  1. 01MCPサーバーにインタラクティブなUIを追加
  2. 02ReactやVanilla JavaScriptでMCP Appを作成
  3. 03UIのライフサイクルとホストコンテキストを実装
  4. 04basic-hostでアプリをローカルテスト

MCP 対応

MCPツールがデータを返し、HTMLリソースがMCP対応ホスト向けのUIを提供するMCP Appの構築を案内します。MCPサーバーへのツールとリソースの登録方法も扱います。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/modelcontextprotocol/ext-apps --skill create-mcp-app

インストール後、Claude Code で/create-mcp-appを入力して読み込まれたか確認します。

詳細

MCP App の作成

Claude Desktop などの MCP 対応ホスト内で実行される、インタラクティブな UI を構築します。MCP App は、MCP ツールと HTML リソースを組み合わせて、リッチでインタラクティブなコンテンツを表示します。

基本概念:ツール + リソース

すべての MCP App には、次の 2 つの部分を関連付ける必要があります。

  1. ツール - LLM/ホストから呼び出され、データを返します
  2. リソース - データを表示するバンドル済み HTML UI を提供します

ツールの _meta.ui.resourceUri は、リソースの URI を参照します。

ホストがツールを呼び出す → ホストがリソースの UI をレンダリングする → サーバーが結果を返す → UI が結果を受け取る。

クイックスタートの選択ガイド

フレームワークの選択
フレームワークSDK のサポート最適な用途
ReactuseApp フックを提供React に慣れているチーム
Vanilla JSライフサイクルを手動で管理シンプルなアプリ、ビルドの複雑さを避けたい場合
Vue/Svelte/Preact/Solidライフサイクルを手動で管理特定のフレームワークを使いたい場合
プロジェクトの状況

既存の MCP サーバーに追加する場合:

  • SDK から registerAppTool、registerAppResource をインポートします
  • _meta.ui.resourceUri を指定してツール登録を追加します
  • バンドル済み HTML を提供するリソース登録を追加します

新しい MCP サーバーを作成する場合:

  • トランスポート(stdio または HTTP)を使ってサーバーをセットアップします
  • ツールとリソースを登録します
  • vite-plugin-singlefile を使ってビルドシステムを設定します

参考コードの取得

動作するサンプルと API ドキュメントを確認するには、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/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

各テンプレートには、次のものが含まれています。

  • registerAppTool と registerAppResource を含む server.ts
  • HTTP および stdio トランスポートのセットアップを含む main.ts エントリーポイント
  • ライフサイクルハンドラーを含むクライアント側アプリ(例:src/mcp-app.ts、src/mcp-app.tsx)
  • グローバルスタイルとホストスタイル変数のフォールバックを含む src/global.css
  • vite-plugin-singlefile を使用する vite.config.ts
  • npm run スクリプトと必要な依存関係を含む package.json
  • node_modules/ と dist/ を除外する .gitignore
API リファレンス(ソースファイル)

/tmp/mcp-ext-apps/src/ の JSDoc ドキュメントを直接参照します。

ファイル内容
src/app.tsApp クラス、ハンドラー(ontoolinput、ontoolresult、onhostcontextchanged、onteardown など)、ライフサイクル
src/server/index.tsregisterAppTool、registerAppResource、ヘルパー関数
src/spec.types.tsすべての型定義:McpUiHostContext、McpUiStyleVariableKey(CSS 変数名)、McpUiResourceCsp(CSP 設定)など
src/styles.tsapplyDocumentTheme、applyHostStyleVariables、applyHostFonts
src/react/useApp.tsxReact アプリ向けの useApp フック
高度なパターン

詳しい手順については、/tmp/mcp-ext-apps/docs/patterns.md を参照してください。

  • App 専用ツール — visibility: ["app"] を使って、ツールをモデルから隠します
  • ポーリング — リアルタイムダッシュボード、インターバル管理
  • 分割レスポンス — 大きなファイル、ページネーション、base64 エンコーディング
  • エラー処理 — isError を使って、失敗をモデルに通知します
  • バイナリーリソース — resources/read、blob フィールドを介した音声/動画など
  • ネットワークリクエスト — アセット、fetch、CSP、_meta.ui.csp、CORS、_meta.ui.domain
  • ホストコンテキスト — テーマ、スタイル、フォント、セーフエリアのインセット
  • 全画面モード — requestDisplayMode、表示モードの変更
  • モデルコンテキスト — updateModelContext、sendMessage を使って、モデルに最新情報を伝えます
  • ビューの状態 — viewUUID、localStorage、状態の復元
  • 表示状態に応じた一時停止 — IntersectionObserver を使って、アニメーション/WebGL を一時停止します
  • ストリーミング入力 — ontoolinputpartial、段階的なレンダリング
参照ホスト実装

/tmp/mcp-ext-apps/examples/basic-host/ は、MCP Apps に対応したホストの実装例を示しています。Claude Desktop のような実際のホストは、より高度な機能を備えています。basic-host はローカルでのテストとプロトコルの理解に使用し、ホストの動作を保証するものとして扱わないでください。

重要な実装上の注意事項

依存関係の追加

依存関係を追加する際は、バージョン番号を手動で記述せず、必ず npm install を使用してください。

npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/client@^2.0.0 @modelcontextprotocol/server@^2.0.0 @modelcontextprotocol/node@^2.0.0 @modelcontextprotocol/express@^2.0.0 zod@^4.2.0 express cors
npm install -D typescript vite vite-plugin-singlefile concurrently cross-env @types/node @types/express @types/cors

ext-apps 2.x では、分割されたベース MCP SDK パッケージ(@modelcontextprotocol/client、 server、node、express)の ^2.0.0 が必要です。@modelcontextprotocol/core は 推移的に導入されます。レガシー版の @modelcontextprotocol/sdk v1 パッケージを追加したり、 未公開のローカルパッケージで代用したりしないでください。

TypeScript サーバーの実行

ユーザーから別の指定がない限り、TypeScript サーバーファイルの実行には tsx を使用してください。例:

npm install -D tsx

npm pkg set scripts.dev="cross-env NODE_ENV=development concurrently 'cross-env INPUT=mcp-app.html vite build --watch' 'tsx --watch main.ts'"

メモ

SDK の例では bun を使用していますが、幅広い互換性を確保するため、生成されるプロジェクトでは tsx をデフォルトにしてください。

ハンドラーの登録順序

app.connect() を呼び出す前に、すべてのハンドラーを登録してください。

const app = new App({ name: "My App", version: "1.0.0" });

// Register handlers first
app.ontoolinput = (params) => { /* handle input */ };
app.ontoolresult = (result) => { /* handle result */ };
app.onhostcontextchanged = (ctx) => { /* handle context */ };
app.onteardown = async () => { return {}; };
// etc.

// Then connect
await app.connect();

よくある避けるべき間違い

  1. テキストのフォールバックがない - UI に対応していないホスト向けに、必ず content 配列を指定してください
  2. CSP の設定がない - MCP Apps の HTML は、同一オリジンのサーバーがない状態で MCP リソースとして提供されます。localhost 宛てであっても、すべてのネットワークリクエストに CSP 設定が必要です
  3. CSP または CORS の設定が誤った _meta オブジェクトにある - _meta.ui.csp と _meta.ui.domain は、registerAppResource() の設定オブジェクトではなく、registerAppResource() の読み取りコールバックが返す contents[] オブジェクトに指定してください
  4. app.connect() の後にハンドラーを登録する - app.connect() を呼び出す前に、すべてのハンドラーを登録してください
  5. 大きな入力にストリーミングを使っていない - 入力の生成中に進捗を表示するには、ontoolinputpartial を使用してください

テスト

basic-host の使用

basic-host の例を使って、MCP Apps をローカルでテストします。

# 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

SERVERS には、サーバー URL の JSON 配列を設定してください(デフォルト:http://localhost:3001/mcp)。

sendLog によるデバッグ

(iframe の開発者コンソールだけでなく)ホストアプリケーションにデバッグログを送信します。

await app.sendLog({ level: "info", data: "Debug message" });
await app.sendLog({ level: "error", data: { error: err.message } });

コメント