• Projects
  • Service
  • About
  • branding.bz
  • Podcast
  • Tips
  • FAQ
  • Recruit
  • Download
  • Contact
  • branding.bz(ブランド構築SaaS)
  • DESIGN NOW(デザインメディア)
  • X
  • LinkedIn
  • Spotify
  • Facebook

213-0011 神奈川県川崎市高津区久本3-6-7-303

© 2026 ID INC. All rights reserved

claude-skills/スキル
SKILLOfficialdevelopment

create-mcp-app

プラグイン
mcp-apps
ソース
GitHub で見る ↗
説明

このスキルの使用場面: ユーザーが「MCPアプリを作成したい」「MCPツールにUIを追加したい」「インタラクティブなMCPビューを構築したい」「MCPアプリのひな形を作りたい」と依頼したときや、MCPアプリのSDK(開発キット)パターン、UI資源の登録方法、MCPアプリのライフサイクル(動作の流れ)、またはホストとの連携について指導が必要な場合です。 インタラクティブなUIを備えたMCPアプリの構築について、包括的な指導を提供します。

原文を表示

This skill should be used when the user asks to "create an MCP App", "add a UI to an MCP tool", "build an interactive MCP View", "scaffold an MCP App", or needs guidance on MCP Apps SDK patterns, UI-resource registration, MCP App lifecycle, or host integration. Provides comprehensive guidance for building MCP Apps with interactive UIs.

ユースケース
  • MCPアプリを作成したいとき
  • MCPツールにUIを追加したいとき
  • インタラクティブなMCPビューを構築したいとき
  • MCPアプリのひな形を作りたいとき
  • MCPアプリのSDKパターンを学ぶとき
  • MCPアプリのライフサイクルについて指導を受けるとき
本文(日本語訳)

MCP アプリを作成する

MCP 対応ホスト(Claude Desktop など)内で動作する対話的なUI を構築します。MCP アプリは、MCP ツール(MCPが提供する機能)と HTML リソース(表示部分)を組み合わせて、リッチで対話的なコンテンツを実現します。

基本的な考え方:ツール+リソース

MCP アプリには、相互に連携する2つの部分が必要です:

  1. ツール — LLM/ホストから呼び出され、データを返す
  2. リソース — バンドル(一つに固めた)HTML UI を提供し、データを表示する

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

ホストがツールを呼び出す → ホストがリソース UI をレンダリング(画面に表示)する → サーバーが結果を返す → UI が結果を受け取る。

クイックスタート判断表

フレームワークの選択

フレームワーク SDK サポート 最適な用途
React useApp フック提供 React に詳しいチーム
Vanilla JS 手動でのライフサイクル管理 シンプルなアプリ、ビルド手順を省きたい場合
Vue/Svelte/Preact/Solid 手動でのライフサイクル管理 フレームワークの好み

プロジェクトの文脈

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

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

新規に MCP サーバーを作成する場合:

  • トランスポート(stdio または HTTP)でサーバーをセットアップ
  • ツールとリソースを登録
  • vite-plugin-singlefile でビルドシステムを構成

リファレンスコードの取得

SDK リポジトリをクローンして、動作例と API ドキュメントを参照します:

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-{フレームワーク}/ から学んで適応させます:

テンプレート 主要ファイル
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 リファレンス(ソースファイル)

JSDoc ドキュメントを /tmp/mcp-ext-apps/src/ から直接読みます:

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

応用パターン

詳細なレシピは /tmp/mcp-ext-apps/docs/patterns.md を参照:

  • アプリ限定ツール — 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 アプリ対応ホストの一実装例を示します。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'"

[!NOTE] SDK の例では bun を使いますが、生成されたプロジェクトはより広い互換性のため tsx をデフォルトにすべきです。

ハンドラー登録の順序

app.connect() を呼び出す前に、すべてのハンドラーを登録します:

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

// ハンドラーを先に登録
app.ontoolinput = (params) => { /* 入力を処理 */ };
app.ontoolresult = (result) => { /* 結果を処理 */ };
app.onhostcontextchanged = (ctx) => { /* コンテキスト変更を処理 */ };
app.onteardown = async () => { return {}; };
// など

// その後に接続
await app.connect();

よくある間違いと対策

  1. テキストフォールバック がない — UI 非対応ホスト向けに常に content 配列を提供
  2. CSP 設定がない — MCP アプリの HTML は同一オリジン(同じサーバー)のないリソースとして提供されます。localhost へのリクエストも含め、すべてのネットワークリクエストに CSP 設定が必須
  3. CSP や CORS 設定が間違った _meta オブジェクトにある — _meta.ui.csp と _meta.ui.domain は registerAppResource() の設定オブジェクトではなく、読み込みコールバックが返す contents[] オブジェクト内に置く
  4. app.connect() の後にハンドラーを登録 — app.connect() を呼び出す前にすべてのハンドラーを登録
  5. 大きな入力に対してストリーミングがない — 入力生成中の進行状況を表示するために ontoolinputpartial を使用

テスト

basic-host を使用したテスト

basic-host の例を使ってローカルで MCP アプリをテストします:

# ターミナル 1:サーバーをビルドして実行
npm run build && npm run serve

# ターミナル 2:basic-host を実行(クローンしたリポジトリから)
cd /tmp/mcp-ext-apps/examples/basic-host
npm install
SERVERS='["http://localhost:3001/mcp"]' npm run start
# http://localhost:8080 を開く

SERVERS をサーバー URL の JSON 配列で指定します(デフォルト:http://localhost:3001/mcp)。

sendLog でデバッグ

iframe の dev コンソールではなく、ホストアプリケーションにデバッグログを送信します:

await app.sendLog({ level: "info", data: "デバッグメッセージ" });
await app.sendLog({ level: "error", data: { error: err.message } });
原文(English)を表示

Create MCP App

Build interactive UIs that run inside MCP-enabled hosts like Claude Desktop. An MCP App combines an MCP tool with an HTML resource to display rich, interactive content.

Core Concept: Tool + Resource

Every MCP App requires two parts linked together:

  1. Tool - Called by the LLM/host, returns data
  2. Resource - Serves the bundled HTML UI that displays the data

The tool's _meta.ui.resourceUri references the resource's URI.

Host calls tool → Host renders resource UI → Server returns result → UI receives result.

Quick Start Decision Tree

Framework Selection

Framework SDK Support Best For
React useApp hook provided Teams familiar with React
Vanilla JS Manual lifecycle Simple apps, no build complexity
Vue/Svelte/Preact/Solid Manual lifecycle Framework preference

Project Context

Adding to existing MCP server:

  • Import registerAppTool, registerAppResource from SDK
  • Add tool registration with _meta.ui.resourceUri
  • Add resource registration serving bundled HTML

Creating new MCP server:

  • Set up server with transport (stdio or HTTP)
  • Register tools and resources
  • Configure build system with vite-plugin-singlefile

Getting Reference Code

Clone the SDK repository for working examples and API documentation:

git clone --branch "v$(npm view @modelcontextprotocol/ext-apps version)" --depth 1 https://github.com/modelcontextprotocol/ext-apps.git /tmp/mcp-ext-apps

Framework Templates

Learn and adapt from /tmp/mcp-ext-apps/examples/basic-server-{framework}/:

Template Key Files
basic-server-vanillajs/ server.ts, src/mcp-app.ts, mcp-app.html
basic-server-react/ server.ts, src/mcp-app.tsx (uses useApp hook)
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

Each template includes:

  • server.ts with registerAppTool and registerAppResource
  • main.ts entry point with HTTP and stdio transport setup
  • Client-side app (e.g., src/mcp-app.ts, src/mcp-app.tsx) with lifecycle handlers
  • src/global.css with global styles and host style variable fallbacks
  • vite.config.ts using vite-plugin-singlefile
  • package.json with npm run scripts and required dependencies
  • .gitignore excluding node_modules/ and dist/

API Reference (Source Files)

Read JSDoc documentation directly from /tmp/mcp-ext-apps/src/:

File Contents
src/app.ts App class, handlers (ontoolinput, ontoolresult, onhostcontextchanged, onteardown, etc.), lifecycle
src/server/index.ts registerAppTool, registerAppResource, helper functions
src/spec.types.ts All type definitions: McpUiHostContext, McpUiStyleVariableKey (CSS variable names), McpUiResourceCsp (CSP configuration), etc.
src/styles.ts applyDocumentTheme, applyHostStyleVariables, applyHostFonts
src/react/useApp.tsx useApp hook for React apps

Advanced Patterns

See /tmp/mcp-ext-apps/docs/patterns.md for detailed recipes:

  • App-only tools — visibility: ["app"], hiding tools from model
  • Polling — real-time dashboards, interval management
  • Chunked responses — large files, pagination, base64 encoding
  • Error handling — isError, informing model of failures
  • Binary resources — audio/video/etc via resources/read, blob field
  • Network requests — assets, fetch, CSP, _meta.ui.csp, CORS, _meta.ui.domain
  • Host context — theme, styling, fonts, safe area insets
  • Fullscreen mode — requestDisplayMode, display mode changes
  • Model context — updateModelContext, sendMessage, keeping model informed
  • View state — viewUUID, localStorage, state recovery
  • Visibility-based pause — IntersectionObserver, pausing animations/WebGL
  • Streaming input — ontoolinputpartial, progressive rendering

Reference Host Implementation

/tmp/mcp-ext-apps/examples/basic-host/ shows one way an MCP Apps-capable host could be implemented. Real-world hosts like Claude Desktop are more sophisticated—use basic-host for local testing and protocol understanding, not as a guarantee of host behavior.

Critical Implementation Notes

Adding Dependencies

Always use npm install to add dependencies rather than manually writing version numbers:

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 requires the split base MCP SDK packages (@modelcontextprotocol/client, server, node, express) at ^2.0.0; @modelcontextprotocol/core comes in transitively. Do not add the legacy @modelcontextprotocol/sdk v1 package or substitute unpublished local packages.

TypeScript Server Execution

Unless the user has specified otherwise, use tsx for running TypeScript server files. For example:

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'"

[!NOTE] The SDK examples use bun but generated projects should default to tsx for broader compatibility.

Handler Registration Order

Register ALL handlers BEFORE calling 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();

Common Mistakes to Avoid

  1. No text fallback - Always provide content array for non-UI hosts
  2. Missing CSP configuration - MCP Apps HTML is served as an MCP resource with no same-origin server; ALL network requests—even to localhost—require a CSP configuration
  3. CSP or CORS config in wrong _meta object - _meta.ui.csp and _meta.ui.domain go in the contents[] objects returned by registerAppResource()'s read callback, not in registerAppResource()'s config object
  4. Handlers after app.connect() - Register ALL handlers BEFORE calling app.connect()
  5. No streaming for large inputs - Use ontoolinputpartial to show progress during input generation

Testing

Using basic-host

Test MCP Apps locally with the basic-host example:

# 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

Configure SERVERS with a JSON array of your server URLs (default: http://localhost:3001/mcp).

Debug with sendLog

Send debug logs to the host application (rather than just the iframe's dev console):

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

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。