MCP Appの作り方 — create-mcp-appスキルで雛形を生成する
create-mcp-appスキルをAIコーディングエージェントに入れると、MCP Appのサーバー・UI・設定ファイル一式が自動生成されます。導入からローカル動作確認までの手順です。
MCP Appを一から手作業で構築すると、サーバー・UI・ビルド設定を揃えるだけで何ファイルも書くことになり、動かすまでに時間がかかります。create-mcp-app スキルをAIコーディングエージェントに入れると、この雛形生成を1回の指示で終わらせられます。Claude Codeなら公式プラグインとして配布されており、インストールから動作確認までを本記事で順番に追います。
この手順でできること
create-mcp-app はMCP Appsのアーキテクチャ・ベストプラクティス・動くサンプルコードを含んだスキルで、エージェントがこれを読み込んでプロジェクトを生成します。実行環境にはNode.js 18以上が必要で、事前にインストールしておきます。MCPのツールとリソースの両方を組み合わせる仕組みのため、事前にMCPのツール・リソースの基本を知っていると読みやすくなります。
手作業でセットアップすることもでき、後半の「手動セットアップの流れ」で扱います。まずはスキルを使う経路から進めます。
スキルをインストールする
Claude Codeでは、公式プラグインマーケットプレイスから直接インストールできます。
/plugin marketplace add modelcontextprotocol/ext-apps
/plugin install mcp-apps@modelcontextprotocol-ext-appsVercel Skills CLIを使う方法もあります。
npx skills add modelcontextprotocol/ext-apps手動でインストールする場合は、リポジトリをクローンしてスキルフォルダをコピーします。
git clone https://github.com/modelcontextprotocol/ext-apps.git
mkdir -p .claude/skills
cp -r ext-apps/plugins/mcp-apps/skills/create-mcp-app .claude/skills/create-mcp-appグローバルに入れたい場合は .claude/skills/ の代わりに ~/.claude/skills/ へコピーすれば、全プロジェクトで使えるようになります。プロジェクト単位でしか使わないなら .claude/skills/ へのコピーで十分です。インストール後は「使えるスキルを教えて」とエージェントに聞き、create-mcp-app が一覧に出ることを確認します。
他のエージェントでのスキル配置先
Claude Code以外のエージェントでもスキルディレクトリの規約に沿えば動きます。配置先はエージェントごとに異なります。
| エージェント | スキルディレクトリ(macOS/Linux) |
|---|---|
| Claude Code | スキルディレクトリ(macOS/Linux)~/.claude/skills/ |
| VS Code / GitHub Copilot | スキルディレクトリ(macOS/Linux)~/.copilot/skills/ |
| Gemini CLI | スキルディレクトリ(macOS/Linux)~/.gemini/skills/ |
| Cline | スキルディレクトリ(macOS/Linux)~/.cline/skills/ |
| Goose | スキルディレクトリ(macOS/Linux)~/.config/goose/skills/ |
| Codex | スキルディレクトリ(macOS/Linux)~/.codex/skills/ |
| Cursor | スキルディレクトリ(macOS/Linux)~/.cursor/skills/ |
このリストは網羅的ではなく、他のエージェントもスキルをサポートしている場合があります。各エージェントのドキュメントで配置先を確認してください。
アプリを作らせて動かす
スキルが入った状態で、作りたいアプリを自然文で指示します。
Create an MCP App that displays a color pickerエージェントは create-mcp-app スキルが関係すると判断してその指示を読み込み、サーバー・UI・設定ファイル一式を含む完全なプロジェクトを組み立てます。生成後は依存関係をインストールし、ビルドしてサーバーを起動します。
npm install && npm run build && npm run serveコマンドは生成されたアプリのフォルダ内で実行する必要があります。プロジェクトのルートディレクトリのまま実行すると、対象ファイルが見つからずビルドに失敗します。
テストする
ローカルで起動しただけでは、MCP Apps対応ホストがないと画面は見られません。テスト方法は主に2つあります。
Claudeでテストする
ClaudeとClaude Desktopは両方ともMCP Appsに対応しています。ローカルサーバーをインターネットに公開する必要があり、cloudflared でトンネルするのが手早い方法です。
npx cloudflared tunnel --url http://localhost:3001生成されたURL(https://random-name.trycloudflare.com のような形式)を、Claudeの設定からカスタムコネクタとして追加します。プロフィール → 設定 → コネクタ → カスタムコネクタを追加、の順です。カスタムコネクタはPro・Max・Teamの有料プランで利用できます。カスタムコネクタ自体の作り方はCoworkカスタムコネクタ自作ガイドで扱っています。
basic-hostでテストする
ext-apps リポジトリには開発用のテストホストが同梱されています。
git clone https://github.com/modelcontextprotocol/ext-apps.git
cd ext-apps/examples/basic-host
npm install
SERVERS='["http://localhost:3001/mcp"]' npm starthttp://localhost:8080 にアクセスすると、ツールを選んで呼び出せるシンプルなインターフェースが表示されます。ツールを呼ぶとホストがUIリソースを取得し、サンドボックスiframe内にレンダリングします。
2つの方法は用途が異なります。どちらを軸にするかは開発の段階で選びます。
| 観点 | cloudflared + Claude | basic-host |
|---|---|---|
| 起動の手間 | cloudflared + Claudeトンネル公開 + カスタムコネクタ登録が必要 | basic-hostnpm start のみ |
| Claude上の見え方の確認 | cloudflared + Claudeできる | basic-hostできない(汎用UIでの表示のみ) |
| 必要プラン | cloudflared + ClaudePro・Max・Teamの有料プラン | basic-host不要 |
| 反復速度 | cloudflared + Claude変更のたびにトンネル・コネクタを維持する分遅い | basic-hostローカル完結で速い |
UIの見た目やツール呼び出しのロジックを素早く反復したい開発初期の段階では、basic-hostを主なテスト環境にする方が効率的です。basic-hostは App クラスの実装が期待どおりに動くかを確認する用途に向いていて、ツール結果の受け渡しやDOM更新のロジックを直しては再読み込みする往復を、トンネルやコネクタの張り直しなしで繰り返せます。一方でbasic-hostが表示するのは汎用のiframeホストであり、サンドボックスのCSPやレイアウト崩れなど、Claude固有のホスト実装に依存する挙動までは再現しません。ロジックが固まったらcloudflaredの手順に切り替え、Claude上での実際の見え方とCSP周りの挙動を確認するのが安全です。プロジェクト構成そのものは共通なので、途中でテスト方法を切り替えてもサーバー・UIのコードを書き直す必要はありません。
手動セットアップの流れ
エージェントを使わず自分で構成したい場合、プロジェクトはサーバー用コードとUI用コードを分けて置くのが典型的な構成です。package.json / tsconfig.json / vite.config.ts / server.ts(ツールとリソースを持つMCPサーバー)/ mcp-app.html(UIのエントリポイント)/ src/mcp-app.ts(UIロジック)という6ファイルが基本セットになります。
依存パッケージは次のとおりです。
npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/sdk
npm install -D typescript vite vite-plugin-singlefile express cors @types/express @types/cors tsxext-apps パッケージはサーバー側(ツールとリソースの登録)とクライアント側(ホストとの通信を担う App クラス)の両方のヘルパーを提供します。vite-plugin-singlefile はUIとアセットを1つのHTMLファイルに束ねるためのプラグインで、必須ではありませんが、CSPの個別設定を避けたい場合に便利です。
設定ファイルの役割も押さえておくと迷いにくくなります。package.json は "type": "module" でESモジュール構文を有効にし、build スクリプトが INPUT 環境変数でどのHTMLファイルを束ねるかをViteに伝えます。tsconfig.json は ES2022 をターゲットにモジュール解決を bundler に設定し、ルートのサーバーコードと src/ 配下のUIコードの両方を include に含めます。vite.config.ts では viteSingleFile() プラグインを有効にし、ビルド出力先を dist に、入力ファイルを環境変数 INPUT 経由で指定します。この3ファイルが揃って初めて、サーバーコードとUIコードを1つのビルドパイプラインで扱えるようになります。
サーバー側では registerAppTool でツールに _meta.ui.resourceUri を持たせ、registerAppResource で同じURIに対応するビルド済みHTMLを返す実装にします。公式サンプルでは、現在時刻を返すシンプルなツールを例に、McpServer インスタンスを作り、ui://get-time/mcp-app.html というURIをツールとリソースの両方に紐づけます。サーバー自体はExpressでHTTP経由に公開し、/mcp エンドポイントに StreamableHTTPServerTransport を接続する構成が定番です。
UI側は App クラスの connect() でホストとの通信を確立し、ontoolresult コールバックでツール結果を受け取り、callServerTool() でユーザー操作に応じてサーバーのツールを呼び出します。サンプルの mcp-app.ts では、ボタンのクリックイベントに callServerTool() を紐づけ、返ってきた結果をDOM要素に反映する流れになっています。ツール呼び出しはサーバーへの往復が発生するため、レイテンシーを前提にUIを設計する必要があります。App クラスにはこのほか、ログ出力・URLを開く・モデルの文脈を構造化データで更新するメソッドも用意されています。
つまずきやすいポイント
- コマンドの実行場所を間違える:
npm install && npm run build && npm run serveは生成されたアプリのフォルダ内で実行する。プロジェクトルートで実行すると失敗する - カスタムコネクタが無料プランで使えない: カスタムコネクタはPro・Max・Teamの有料プランが前提。Freeプランでは追加できない
- CSPの設定漏れ:
vite-plugin-singlefileを使わず外部スクリプトやアセットを読み込む場合、_meta.ui.cspでオリジンを明示しないとホストがブロックする - basic-hostへの接続先ミス:
SERVERS環境変数はJSON配列文字列で渡す必要があり、末尾のスラッシュや/mcpパスの有無で接続に失敗することがある - テスト方法を最後まで1つに固定してしまう: basic-hostだけで確認を終えると、Claude固有のサンドボックスCSPやレイアウト崩れに気づかないまま公開してしまう。仕上げ段階では必ずcloudflared経由でClaude上の見え方も確認する
- 手動セットアップでのモジュール設定漏れ:
package.jsonに"type": "module"を書き忘れると、ESモジュール構文のインポート文がエラーになる
まとめ
create-mcp-app スキルを入れれば、AIコーディングエージェントに1回指示するだけでMCP Appのプロジェクト一式を生成できます。Claude Codeへの導入はプラグインマーケットプレイス経由が最短で、生成後は npm install && npm run build && npm run serve でローカル起動し、Claudeのカスタムコネクタかbasic-hostで動作確認します。手作業で構成したい場合も、サーバー・UI・ビルド設定という3層構造は変わりません。MCP Apps自体の仕組みはMCP Appsとはで解説しています。