
MCP Apps v1.2の新機能 「リソース読み取りAPI」 を試してみた
はじめに
MCP Apps は、AIチャットの会話内にインタラクティブなUI(ダッシュボード、フォーム、可視化など)を埋め込むための Model Context Protocol(MCP)の公式拡張仕様です。2026年1月26日に v1.0.0 として正式リリースされてから約2ヶ月、すでに v1.2.2 まで進化しています。
v1.2.0 で追加された app.readResource() / app.listResources() によって、MCP Apps のUI側からサーバーリソースへ直接アクセスできるようになりました。従来はツール呼び出し経由でしか取得できなかったデータを、UIが能動的に取得できる設計が可能になっています。
この記事では、このリソース読み取り/一覧APIを中心に、v1.2.x 系の新機能を実際に試しながら解説します。読者としては、MCPサーバーを開発中の方や、これから MCP Apps を導入したいエンジニアの方を想定しています。
MCP Apps v1.0〜v1.2 の進化を振り返る
まず、v1.0.0 から v1.2.2 までの変更を一覧で確認してみましょう。
| バージョン | リリース日 | 主な変更 |
|---|---|---|
| v1.0.0 | 2026-01-26 | 正式仕様リリース。ui:// URIスキーム、Tool-UI Linkage、サンドボックスセキュリティモデル |
| v1.0.1 | 2026-01-26 | 依存パッケージ更新、ドキュメント修正 |
| v1.1.0 | 2026-02-22 | PDF検索、フルスクリーン対応 |
| v1.1.1 | 2026-02-24 | 音声/動画サポート、PDF改善、MCPBパッケージング |
| v1.1.2 | 2026-02-25 | PDFサーバーのパス検証、download-file メソッド追加 |
| v1.2.0 | 2026-03-06 | リソース読み取り/一覧API追加、autoResize修正 |
| v1.2.1 | 2026-03-10 | ビルド修正、E2Eテスト改善、セキュリティパッチ |
| v1.2.2 | 2026-03-10 | zod/v4 からのスキーマインポート修正 |
特に注目すべきマイルストーンは3つあります。
1つ目は v1.1.0 でのPDF検索・フルスクリーン対応です。MCP Apps のUIが全画面表示に対応し、PDFビューアのような本格的なアプリケーションが実現可能になりました。
2つ目は v1.1.1 での音声/動画サポートです。テキストやグラフだけでなく、メディアリッチなUIが構築できるようになっています。
3つ目が今回のメインテーマである v1.2.0 でのリソース読み取り/一覧API です。これが MCP Apps の設計パターンを大きく広げる重要な追加機能です。
v1.2.0の目玉機能「リソース読み取り/一覧API」とは
従来の MCP Apps の制約
v1.2.0 以前の MCP Apps では、UIがサーバーからデータを取得するには、ツール呼び出しの結果として渡されるデータに依存していました。つまり、LLMがツールを呼び出す → ツールがデータと共にUIリソースを返す → UIがそのデータを表示する、という一方向の流れでした。
UIが追加のデータを必要とする場合、ホスト経由でツールを再度呼び出す必要があり、LLMの介在が必須でした。
v1.2.0 で変わったこと
app.readResource() と app.listResources() の追加により、UIからサーバーリソースへ直接アクセスできるようになりました。これはMCPの「リソース」プリミティブ(MCP サーバーが公開するデータソース)をUI側から利用できるようにしたものです。
従来(v1.1.x以前):
- LLM がツールを呼び出す
- ツールがデータ付きで UI リソースを返す
- UI がそのデータを表示する(データは固定、追加取得にはLLMの再介在が必要)
v1.2.0 以降:
- LLM がツールを呼び出す
- ツールが UI リソースを返す
- UI が表示される
- UI が
app.listResources()でリソース一覧を取得(LLM不要) - UI が
app.readResource(uri)で個別リソースを読み取り(LLM不要) - UI が動的にデータを更新
ポイントは、ステップ4〜6が LLM を介さずにUI主導で実行できるようになった点です。
ユースケース例
この新APIが活きるシーンをいくつか挙げてみます。
- 設定ファイルの動的読み込み: UIからサーバー上の設定リソースを取得して、ユーザーが編集・保存できるフォームを構築
- データブラウジング: ファイル一覧をリソースとして公開し、UIでファイルブラウザを実現
- ダッシュボードの自動更新: 定期的にリソースを再取得して、リアルタイムデータを表示
なお、リソースの読み取りはホスト側の許可ポリシーに依存します。すべてのリソースに無条件でアクセスできるわけではなく、ホストがどのリソースへのアクセスを許可するかを制御する点にご注意ください。
実際に試してみた ─ 環境構築とクイックスタート
前提条件
- Node.js(v18以上推奨)
- pnpm
参考にしたスターターテンプレート
今回は Vercel Labs が公開している mcp-apps-nextjs-starter を参考に、Claude Code に実装を依頼しました。このスターターは Next.js ベースの MCP Apps の最小構成で、MCPサーバーとウィジェットUIを1つの Next.js アプリに同居させるアーキテクチャを採用しています。
プロジェクト構成
実装したプロジェクトの構成は以下のとおりです。
demo-mcp-apps-v1.2.0/
├── app/
│ ├── globals.css — グローバルスタイル
│ ├── hooks/
│ │ └── use-mcp-app.ts — MCP Apps 接続フック
│ ├── layout.tsx — ルートレイアウト(iframe ブートストラップ含む)
│ ├── mcp/
│ │ └── route.ts — MCP サーバーエンドポイント
│ ├── page.tsx — メイン UI(Resource Browser)
│ └── types/
│ └── global.d.ts — Window 型拡張
├── lib/
│ └── sample-resources.ts — サンプルリソース定義
├── baseUrl.ts — 公開 URL 解決(トンネル / Vercel)
├── middleware.ts — CORS ヘッダー付与
├── next.config.ts — assetPrefix 設定
├── package.json
└── tsconfig.json
Next.js のルートページ(app/page.tsx)がそのままウィジェットUIとなり、app/mcp/route.ts がMCPサーバーとして機能します。MCPサーバーは起動時に / のHTMLをself-fetchし、UIリソースとしてホストに返す仕組みです。
依存パッケージ
package.json の主要な依存パッケージです。
{
"dependencies": {
"@modelcontextprotocol/ext-apps": "^1.2.2",
"@modelcontextprotocol/sdk": "1.25.2",
"mcp-handler": "^1.0.7",
"next": "16.1.6",
"react": "19.2.3",
"react-dom": "19.2.3",
"zod": "^4.3.6"
}
}
@modelcontextprotocol/ext-apps— MCP Apps のクライアント/サーバーSDK。registerAppTool、registerAppResourceなどを提供@modelcontextprotocol/sdk— MCP プロトコル本体mcp-handler— Next.js の Route Handler で MCP サーバーを動かすためのハンドラzod— ツール引数のスキーマバリデーション
ホストへの接続
Vercelにデプロイして起動したMCPサーバーのURLを、MCP Apps 対応ホストに登録します。
https://xxxx-xxx-xxx/mcp
(xxxx-xxx-xxxはVercelデプロイ後に取得可能なドメイン)
Claude.ai、ChatGPT、Cursor のいずれでも、設定画面の MCP / Apps セクションにこのURLを追加するだけで接続できます。
接続方法はこちらの記事をご参照ください。
app.readResource() の基本的な使い方
v1.2.0 で追加された app.readResource() を使うと、UIからサーバーのリソースを直接読み取れます。
注意: 以下のコード例は SDK v1.2.2 時点の API に基づく記述です。API の詳細は変更される可能性があるため、最新の仕様は 公式APIドキュメント を参照してください。
(画像を差し込む)
// MCP App(UI側): リソースの読み取り
import { App } from "@modelcontextprotocol/ext-apps";
const app = new App();
// ホストとの通信を確立(必須!)
await app.connect();
// サーバーリソースを読み取る
const resource = await app.readResource("config://app-settings");
console.log(resource);
// {
// contents: [
// {
// uri: "config://app-settings",
// mimeType: "application/json",
// text: '{"theme": "dark", "language": "ja", ...}'
// }
// ]
// }
// 取得したデータをUIに反映
const settings = JSON.parse(resource.contents[0].text);
document.getElementById("theme-select").value = settings.theme;
app.listResources() でリソース一覧を取得
利用可能なリソースの一覧を取得する app.listResources() も追加されています。

ソースコードの例は次の通りです。
// MCP App(UI側): リソース一覧の取得
const { resources } = await app.listResources();
console.log(resources);
// [
// { uri: "config://app-settings", name: "アプリ設定", mimeType: "application/json" },
// { uri: "data://metrics/cpu", name: "CPU使用率", mimeType: "application/json" },
// { uri: "data://metrics/memory", name: "メモリ使用率", mimeType: "application/json" },
// ]
// UIにリソース一覧を表示
resources.forEach((res) => {
const option = document.createElement("option");
option.value = res.uri;
option.textContent = res.name;
document.getElementById("resource-selector").appendChild(option);
});
React での利用例
React を使っている場合は、useApp() フックを組み合わせて利用できます。
// MCP App(React): useApp() + リソースAPI
import { useApp } from "@modelcontextprotocol/ext-apps/react";
import { useState, useEffect } from "react";
function Dashboard() {
const app = useApp();
const [resources, setResources] = useState([]);
const [selectedData, setSelectedData] = useState(null);
useEffect(() => {
// リソース一覧を取得
app.listResources().then(({ resources }) => {
setResources(resources);
});
}, [app]);
const handleSelect = async (uri) => {
// 選択されたリソースを読み取り
const result = await app.readResource(uri);
setSelectedData(JSON.parse(result.contents[0].text));
};
return (
<div>
<h2>利用可能なリソース</h2>
<select onChange={(e) => handleSelect(e.target.value)}>
<option value="">選択してください</option>
{resources.map((res) => (
<option key={res.uri} value={res.uri}>
{res.name}
</option>
))}
</select>
{selectedData && (
<pre>{JSON.stringify(selectedData, null, 2)}</pre>
)}
</div>
);
}
export default Dashboard;
ダウンロード機能
v1.1.2 で追加された download-file メソッド(SDK上は app.downloadFile())を使うと、MCP Apps のUI内からホスト経由でファイルをダウンロードさせることができます。通常のブラウザとは異なり、MCP Apps はサンドボックスiframe内で動作するため、<a download> や Blob URL による直接ダウンロードはできません。代わりに、ホストにダウンロードリクエストを送り、ホスト側がファイル保存を処理する仕組みです。
今回の実装では、リソースブラウザで選択中のリソースをダウンロードできるようにしました。

ソースコードの例は次の通りです。
// app/hooks/use-mcp-app.ts — ダウンロードヘルパー
export async function requestFileDownload(options: {
filename: string;
content: string;
mimeType: string;
}) {
if (!singletonApp) throw new Error("Not connected to MCP host");
return singletonApp.downloadFile({
contents: [
{
type: "resource" as const,
resource: {
uri: `file:///${options.filename}`,
text: options.content,
mimeType: options.mimeType,
},
},
],
});
}
downloadFile の引数は MCP のリソース形式に準拠しており、uri、text、mimeType を持つリソースオブジェクトを contents 配列で渡します。uri には file:/// スキームでファイル名を指定します。
UI側からの呼び出しは以下のようになります。
// app/page.tsx — ダウンロードボタンのハンドラ
const handleDownload = useCallback(async () => {
if (!content?.text) return;
const resource = resources.find((r) => r.uri === selectedUri);
const ext = content.mimeType === "application/json" ? ".json" : ".md";
const filename = (resource?.name ?? "resource").replace(/\s+/g, "-") + ext;
try {
await requestFileDownload({
filename,
content: content.text,
mimeType: content.mimeType ?? "text/plain",
});
setStatus(`${filename} をダウンロードしました`);
} catch (err) {
console.error("Download failed:", err);
setStatus("ダウンロードに失敗しました");
}
}, [content, selectedUri, resources]);
リソース名からファイル名を生成し、MIME タイプに応じて拡張子(.json / .md)を付与しています。requestFileDownload が内部で app.downloadFile() を呼び出し、ホストにファイルデータを送信します。
なお、downloadFile はホスト側の対応が必要なため、すべてのMCPホストで動作するわけではない点に注意してください。対応状況はホストごとに異なります。
まとめ
MCP Apps v1.2.x の主なポイントを整理します。
- v1.2.0 でリソース読み取り/一覧APIが追加され、UIからサーバーリソースへの直接アクセスが可能になった
app.readResource()/app.listResources()により、LLMを介さないデータ取得が実現し、より動的なUI設計パターンが使える- v1.1.x 系では PDF検索、フルスクリーン、音声/動画サポートなど、メディア系機能が大幅に強化
- エコシステムも急速に拡大中: FastMCP 3.0 Beta 2 での対応、Microsoft Power Apps MCP Server のプレビュー、Google Cloud MCP サーバー自動有効化など
今後もクラスメソッドではMCP Appsの機能追加を追っていきます。Xでも発信していきますのでお楽しみに。







