MCP Appsでチャット内で実行確認ができる勉強のアプリを作ってみた!

MCP Appsでチャット内で実行確認ができる勉強のアプリを作ってみた!

2026.03.21

こんにちは、リテールアプリ共創部の戸田駿太です。

MCP Apps × Next.js × Monaco Editor で、AIチャットの中でJavaScriptコードを編集・実行できるVS Code風プレイグラウンドを作りました。
これを使うことで、JSの構文を学習する際にAIへの質問からコードの実行・修正・再質問までをチャット内で完結できるようになります。

作ったもの

AIに「スプレッド構文の使い方を教えて」などと聞くと、テキストの解説に加えて、編集・実行可能なコードウィジェットがチャット内に表示されます。

CleanShot 2026-03-21 at 20.01.41@2x.png

従来はコードブロックをコピーしてDevToolsなどに貼り付けて実行する必要がありましたが、このアプリではその場でコードを書き換えてRunボタンを押すだけで結果を確認できます。

従来の体験

  1. AIに質問する
  2. コードブロックで回答が返ってくる
  3. コードをコピーする
  4. DevToolsなど別の環境に貼り付けて実行する
  5. 修正したらまたコピペ…(3に戻る)

このアプリでの体験

  1. AIに質問する
  2. チャット内にVS Code風のエディタ+ターミナルのウィジェットが表示される
  3. その場でコードを編集して ▶ Run で実行
  4. わからなければ 💬 Ask AI でそのままAIに質問(2に戻る)

MCP Appsとは

MCP Apps は、MCPツールの呼び出し結果にカスタムHTML/React UIをインライン表示できる仕組みです。Claude Desktop、ChatGPT などが対応しています。

通常のMCPツールはテキストを返すだけですが、MCP Appsを使うとサンドボックスiframe内にReact UIを表示できます。

Claude Desktop のチャット画面

  ├── ユーザーの質問(通常のチャット)
  ├── AIの応答テキスト(通常のチャット)
  └── MCPツール呼び出し
        └── structuredContent を返す
              └── MCP Apps ウィジェット (iframe) がチャット内に描画される

MCP Appsを詳しく知りたい方はこちらの記事をご覧ください。

https://dev.classmethod.jp/articles/mcp-apps-introduction-overview/

アーキテクチャ

技術スタック

技術 用途
Next.js 16 (App Router) フレームワーク
@modelcontextprotocol/ext-apps MCP Apps SDK
mcp-handler Next.js 用 MCP ハンドラ(Vercel製)
@monaco-editor/react VS Codeのエディタエンジン
Tailwind CSS 4 スタイリング
Zod スキーマバリデーション
Vercel ホスティング

ディレクトリ構成

study-programming-mcp-apps/
├── app/
│   ├── mcp/
│   │   └── route.ts           # MCPサーバー + playgroundツール定義
│   ├── components/
│   │   ├── PlaygroundWidget.tsx # ウィジェット全体
│   │   ├── MonacoEditor.tsx    # Monaco Editor (dynamic import)
│   │   ├── TabBar.tsx          # script.js タブ
│   │   ├── Terminal.tsx        # ターミナル出力パネル
│   │   └── Toolbar.tsx         # Run / Clear / Copy / Ask AI ボタン
│   ├── hooks/
│   │   ├── use-mcp-app.ts     # MCP接続ブリッジ
│   │   └── useCodeExecution.ts # コード実行管理
│   ├── lib/
│   │   └── vscode-theme.ts    # VS Code風カラーパレット
│   ├── page.tsx               # エントリーポイント
│   └── layout.tsx             # iframe対応レイアウト
├── baseUrl.ts
├── middleware.ts
└── next.config.ts

実装のポイント

MCPツール定義 — AI → ウィジェットへのデータの流れ

MCP Apps では、サーバー側に2つのものを登録します。

  • ツール — AIが呼び出す関数。今回は playground という名前で、codeautoRun を引数に取る
  • リソース — ウィジェットのHTML。ツールが呼ばれたときにチャット内に表示されるUI本体

この2つを resourceUri でひも付けることで、「AIがツールを呼ぶ → 対応するUIが表示される」という流れになります。

https://github.com/ShuntaToda/study-programming-mcp-apps/blob/main/app/mcp/route.ts

ツールの戻り値にはcontentstructuredContent の2種類があります。contentはAIの会話コンテキストに残るテキスト、structuredContentはAIには見えずウィジェットだけに届くデータです。今回はウィジェットに表示したいコードを structuredContent 経由で渡しています。

ウィジェット側の受信 — useApp フックとステート管理

ウィジェット側のデータを受け取りのため、公式SDKの useApp フックに ontoolinputontoolresult のハンドラを登録します。

https://github.com/ShuntaToda/study-programming-mcp-apps/blob/main/app/hooks/use-mcp-app.ts

ここで1点注意があり、ハンドラは onAppCreated コールバック内で登録しなければなりません。useApp が内部で connect() の前にハンドラを設定してくれるため、接続直後のイベントも取りこぼさずに済みます。

開発中にハマったのが、MCPデータが届く前にデフォルトコードでMonaco Editorをマウントしてしまうという問題でした。一度マウントされたMonaco Editorは、propsが変わっても表示を更新してくれません。

https://github.com/ShuntaToda/study-programming-mcp-apps/blob/main/app/page.tsx#L14-L53

対処としては、connected && !data(接続済みだがデータ未着)の間はウィジェットをマウントせず、データが届いてから初めて PlaygroundWidget を描画するようにしました。

コード実行 — consoleを乗っ取る

▶ Run ボタンを押したときの処理を見ていきます。

https://github.com/ShuntaToda/study-programming-mcp-apps/blob/main/app/hooks/useCodeExecution.ts#L21-L63

console.log 等を一時的に上書きして、出力をReactのstateに流し込んでからターミナルパネルに表示し、実行後に元に戻す——というのが基本の流れです。コードの実行には AsyncFunction コンストラクタを使っており、await を含むコードにも対応できます。

MCP Appsのウィジェットはもともとホスト側のサンドボックスiframe内で動いているので、この eval ベースの方式でもセキュリティ上のリスクは限定的です。

ウィジェット → AIへの双方向通信 — sendMessage

ここまでの流れは AI → ウィジェット の一方向でした。ただ、せっかくコードを書き換えて実行できるなら、その結果についてAIに質問できたほうが学習体験として完成します。

app.sendMessage() を使うと、ウィジェットからClaudeの会話にメッセージを送れます。

https://github.com/ShuntaToda/study-programming-mcp-apps/blob/main/app/components/PlaygroundWidget.tsx#L46-L68

「💬 Ask AI」ボタンを押すと、エディタの現在のコードと実行結果をまとめてClaudeに送信します。コードを書き換えて実行してみたけど結果がよくわからない、というときにそのままAIに聞ける。AIがコードを提示 → ユーザーが試す → わからなければAIに聞く、という学習ループがチャット内で完結します。

開発中に気をつけたこと

Monaco EditorのCDN読み込みとCSP

MCP Appsのiframe sandboxは厳しいCSPがかかっています。Monaco Editorはデフォルトで cdn.jsdelivr.net からワーカーファイルを読み込むため、CSP設定で明示的に許可する必要がありました。

https://github.com/ShuntaToda/study-programming-mcp-apps/blob/main/app/mcp/route.ts#L49-L60

これを忘れると、エディタが永遠に「Loading...」のままになります。

試してみる

Vercelにデプロイ済みなので、Claude Desktopからすぐに試せます。claude_desktop_config.json に以下を追加して、Claude Desktopを再起動してください。

{
  "mcpServers": {
    "js-playground": {
      "command": "npx",
      "args": ["mcp-remote", "https://study-programming-mcp-apps.vercel.app/mcp"]
    }
  }
}

あとはClaudeに「スプレッド構文の使い方を教えて」などとJavaScriptについて質問すれば、playground ツールが呼ばれてウィジェットが表示されます。

まとめ

MCP Appsを使うことで、AIとの会話の中にインタラクティブなUIを埋め込むことができます。今回はJavaScriptのPlaygroundを作りましたが、同じ仕組みでグラフ描画ツール、フォームビルダー、データビジュアライザーなど、様々なウィジェットが実現できます。

今回紹介したアプリでは「AIにコードを聞いてコピペして実行」という往復が不要になり、チャットの中で完結する学習体験が作れました。

皆さんの参考になれば幸いです。

参考

https://github.com/ShuntaToda/study-programming-mcp-apps

https://modelcontextprotocol.io/docs/extensions/apps

https://github.com/modelcontextprotocol/ext-apps

https://github.com/vercel-labs/mcp-apps-nextjs-starter

https://dev.classmethod.jp/articles/mcpapps-20260309/

この記事をシェアする

FacebookHatena blogX

関連記事