MCP拡張機能 - Tasks・MCP Apps・Skills
コアプロトコルの外側にあるオプトイン式の拡張機能 (Extensions) の仕組みと、主要な拡張を解説します。拡張はコアとは別にバージョン管理され、クライアントが未対応だと機能しません。採用の前に、対応状況の確認とフォールバックの設計が必要です。コアプロトコルの全体像は MCP入門、2026-07-28 版の変更点は MCP最新仕様 2026-07-28 の変更点と移行 を参照してください。
1. このドキュメントで扱うこと
- 拡張機構
- Tasks 拡張
- MCP Apps
- Skills over MCP
- 認可拡張
- Server Cards
- 対応状況の確認
- 採用判断
拡張機構
拡張は、コアの仕様の外側で定める、オプトインの追加機能です。モジュール的なもの (認証など)、専門的なもの (業界固有のロジック)、実験的なもの (コアへの取り込みを目指して育てている機能) があります。
拡張は、{vendor-prefix}/{extension-name} 形式の拡張識別子で識別します。公式の拡張は、io.modelcontextprotocol を接頭辞に使います。サードパーティの拡張は、衝突を避けるため、自分が所有するドメインを逆順にした接頭辞 (例: com.example/my-extension) を使います。
双方が capabilities.extensions で、対応を明示してオプトインします (SEP-2133)。2026-07-28 版はステートレスのため、宣言の場所が、方向ごとに決まっています。
- クライアント: 各リクエストの
_meta["io.modelcontextprotocol/clientCapabilities"]にextensionsを入れる - サーバー:
server/discoverの応答のcapabilities.extensionsに入れる
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/ui": {
"mimeTypes": ["text/html;profile=mcp-app"]
}
}
}
}
}
各拡張が、自分の設定オブジェクトのスキーマを定めます。空のオブジェクトは、設定がないことを示します。拡張は常に既定で無効で、開発者の明示的なオプトインが必要です。SDK は、拡張に対応しなくてもプロトコルに適合でき、対応する拡張を SDK のドキュメントに書くことが推奨されています。
拡張は、コアと独立して進化します。更新は拡張のリポジトリーの保守者が管理し、コアの保守者のレビューは要りません。互換性のない変更 (フィールドの削除や改名、型の変更、必須フィールドの追加) は、設定の中のフラグやバージョンで吸収し、避けられないときだけ、新しい識別子 (例: io.modelcontextprotocol/my-extension-v2) にします。
片方が対応していないときは、対応する側が、コアの動作へフォールバックするか、拡張が必須ならエラーで拒否します。たとえば、UI 付きのツールを出すサーバーは、UI 拡張に対応しないクライアントにも、意味のあるテキストの結果を返します。
公式の拡張は、MCP の GitHub 組織の ext- で始まるリポジトリーにあります。実験的な拡張は、experimental-ext- で始まるリポジトリーで、ワーキンググループなどの下で育てられ、SEP (Extensions Track) を経て公式になります。
Tasks 拡張
Tasks は、長時間かかる処理を、永続的なハンドルで扱う拡張です。識別子は io.modelcontextprotocol/tasks です。2025-11-25 版では、コアの実験的な機能でしたが、2026-07-28 版で拡張に移りました (SEP-2663。仕様は ext-tasks)。
接続を開いたまま待つのでは解決できない問題を、Tasks が扱います。
- 長い接続が要らない。多くのクライアントや中継機器は、数秒を超える接続にタイムアウトを設けている
- クラッシュに強い。タスク ID は永続的なハンドルで、クライアントが切断や再起動をしても、同じ ID で再開できる
- 進捗が見える。状態と、任意のステータスメッセージを持つ
- 途中で入力を求められる。
input_requiredになり、クライアントがtasks/updateで応える - サーバー主導。タスクにするかどうかは、リクエストごとにサーバーが決める。クライアントは、拡張を 1 回オプトインし、どちらの形の結果が来ても処理できるようにしておく
流れは次のとおりです。
- クライアントが、リクエストごとの capability に
io.modelcontextprotocol/tasksを入れる。サーバーもserver/discoverで同じ拡張を宣言する - サーバーは、長時間になると判断したリクエストに、最終結果の代わりに
CreateTaskResult(resultType: "task") を返す。taskId、初期状態、ttlMs、推奨のポーリング間隔 (pollIntervalMs) を含む。タスクは、応答を返す前に、永続的に作成する - クライアントが
tasks/getで状態を取得する。終了状態では、resultかerrorが入る - 途中で入力が必要なら、状態が
input_requiredになり、tasks/getの応答にinputRequestsが入る。クライアントはtasks/updateで、inputResponsesを返す completedでは、resultに、同期で返したはずの結果が入る。failedでは、errorに JSON-RPC のエラーが入る- クライアントは、
tasks/cancelでいつでも取り消しを要求できる。協調的な取り消しで、サーバーが必ず止まるとは限らない
| 状態 | 意味 |
|---|---|
working | 処理中 |
input_required | サーバーがクライアントの入力を待つ。inputRequests を参照 |
completed | 完了。result に最終出力 |
failed | 実行中に JSON-RPC エラー。error に詳細 |
cancelled | 取り消された (常に守られるとは限らない) |
completed、failed、cancelled は終了状態で、以後は変わりません。tasks/result と tasks/list は廃止されました。結果は tasks/get で得ます。ポーリングが基本ですが、サーバーが対応していれば、subscriptions/listen で notifications/tasks を購読して、状態の通知を受け取れます。通知には完全なタスクの状態が入るため、追加の tasks/get は不要です。
サーバーは、クライアントが拡張を宣言していないときに、CreateTaskResult を返してはいけません。クライアントは、タスク ID を永続化し (再起動後に再開するため)、pollIntervalMs を守ってポーリングします。
Tasks は、CI のパイプライン、バッチ処理、人間の承認、ジョブ ID を持つ外部システムのラップ、不安定な接続のような場面に向いています。数秒で終わる処理には、使わなくてかまいません。
MCP Apps
MCP Apps は、ツールの結果として、チャート、フォーム、ダッシュボード、動画のプレーヤーといった対話的な UIを、会話の中に描画する拡張です (識別子 io.modelcontextprotocol/ui)。別のウェブアプリへのリンクを返す代わりに、会話の流れの中で操作でき、アプリからサーバーのツールを呼び出し、ホストが新しい結果をアプリへ届けられます。
仕組みは、2 つの MCP のプリミティブの組み合わせです。
- ツールの定義の
_meta.ui.resourceUriに、ui://のリソースを指定する。ホストは、ツールを呼ぶ前に、このリソースを先読みできる - ホストが、サーバーから UI のリソース (通常は、JavaScript や CSS をまとめた HTML) を取得する。外部のスクリプトなどを読み込むオリジンは、
_meta.ui.cspで指定する - ウェブのホストは、HTML をサンドボックス化された iframe の中に描画する。
_meta.uiのpermissionsで、マイクやカメラなどの追加の権限を要求できる - アプリとホストは、postMessage の上の JSON-RPC (
ui/initializeなど、ui/で始まる独自のメソッドを含む、MCP の方言) で通信する。アプリは、ツールの呼び出し、メッセージの送信、モデルのコンテキストの更新を要求できる
セキュリティは、サンドボックス化された iframe が支えます。アプリは、親ページの DOM、Cookie、ローカルストレージに触れず、親を遷移させたり、スクリプトを実行したりできません。ホストは、アプリが呼べるツールや、リンクを開く機能を制限できます。サーバーの作者を完全に信頼しなくても、サードパーティのアプリを描画できる、というのが設計の狙いです。
向いているのは、データの探索 (地図やグラフのドリルダウン)、多数のオプションの設定フォーム、リッチなメディア (PDF、3D) の表示、リアルタイムの監視、複数段階のワークフローです。UI がもたらす利点が要らないなら、通常のウェブアプリのほうが単純です。
MCP Apps に未対応のクライアントのために、UI 付きのツールも、意味のあるテキストの結果を返す設計にします。詳細な API は 公式の MCP Apps ドキュメント を参照してください。
Skills over MCP
Skills over MCP (識別子 io.modelcontextprotocol/skills) は、Agent Skills の仕様 に沿ったスキル (SKILL.md と、任意の補助ファイルを含むディレクトリー) を、MCP サーバーから発見、取得するための拡張です。コードレビューや文書処理のような、複数のツールを組み合わせる再利用可能な手順を、それが説明するサービスと同じ場所に置けます。クライアントは、メタデータから使えるスキルを発見し、手順や補助ファイルは必要になったときに読みます。SEP-2640 は Final で、Skills over MCP ワーキンググループが維持しています。一方、SDK とホストの対応は、まだ進行中です。
サーバーは、resources capability と、この拡張の宣言 (任意の directoryRead 設定を含む) を持ち、次のメソッドを実装します。
| メソッド | 用途 |
|---|---|
skills/list | スキルの一覧。各項目に uri、frontmatter、ファイルのマニフェスト (resources) を持つ |
skills/get | URI を指定して、スキルの項目を 1 件取得 (更新にも使う) |
resources/read | SKILL.md や補助ファイルの内容を取得 (既存のリソース機能) |
resources/directory/read | 任意。ディレクトリーの直下の子を一覧 (directoryRead: true のとき) |
スキルの URI は、skill://code-review/SKILL.md のように、skill:// を推奨しますが、ほかのスキームも使えます。マニフェストは、SKILL.md と補助ファイルのすべてについて、URI、SHA-256 のダイジェスト、バイト数を持ちます。ホストは、使う前にバイト数とダイジェストを検証し、SKILL.md の frontmatter を、項目の frontmatter と突き合わせなければなりません。検証に失敗した内容は使わず、項目を更新します。ダイジェストは、サーバーのマニフェストとの整合性を示すだけで、内容を信頼してよいことは意味しません。スキルの内容は、信頼できない入力として扱います。ホスト側のコードの実行や、allowed-tools のような権限の付与には、スキルごとの利用者の明示的な承認が必要です。承認は、ファイルの URI とダイジェストの集合に束縛され、ファイルが変わったら取り消されます。
スキルの識別は、サーバーの識別と URI の組です。名前は、一意とは限らないラベルにすぎないため、ホストは同名のスキルが黙って入れ替わらないようにします。
認可拡張
認可の拡張は、ext-auth リポジトリーで管理される、コアの認可を補う仕組みです。
| 拡張 | 識別子 | 用途 |
|---|---|---|
| OAuth Client Credentials | io.modelcontextprotocol/oauth-client-credentials | 対話的なログインのない、マシン間 (M2M) 認証 |
| Enterprise-Managed Authorization | io.modelcontextprotocol/enterprise-managed-authorization | 企業の IdP による一元的なアクセス制御 |
仕組みと実装は、それぞれ MCPの認可 と MCPの認可拡張とエンタープライズ導入 で詳しく扱います。
Server Cards
Server Card は、MCP サーバーを、接続の前に発見するための、静的なメタデータの文書です (SEP-2127)。server/discover は、接続先を知り、接続できたあとの、ライブな発見です。Server Card は、その前の段階を埋め、クライアントや Registry が、サーバーの所在、トランスポート、対応するプロトコルのバージョンを、接続せずに知れるようにします。IDE の自動設定や、ドメインのクロールによるインデックス化が、主な用途です。
- 文書は、リモートの MCP サーバーの識別 (
name、version、descriptionなど)、リモートのエンドポイント (URL、ヘッダー、変数のテンプレート、対応するプロトコルのバージョン)、名前空間付きの_metaを持つ - ドメイン単位の発見は、AI Catalog (
/.well-known/ai-catalog.json) が、Server Card へのリンクを持つか、埋め込む。カード自体は、任意の URI に置けて、<streamable-http-url>/server-cardが推奨の場所 - 意図的に、ツール、リソース、プロンプトの定義と、capabilities、拡張の対応を含めない。これらは、ユーザーやセッションによって変わるため、静的な文書では表現できず、実行時に
*/listで確認する - 公開で、読み取り専用の文書。資格情報、内部ネットワークの構成、ユーザー固有のデータを含めてはならない。HTTPS で配信し、カードと
server/discoverが食い違うなら、ライブのserver/discoverの値を優先する
規定の詳細は、実験的な拡張のリポジトリー (experimental-ext-server-card) に置かれ、変わる可能性があります。ローカルにインストールするパッケージも扱う Registry の server.json とは別物です (詳細は MCP Registryとサーバーの配布)。
対応状況の確認
拡張は、クライアントとサーバーの双方が対応して初めて動きます。クライアントごとの対応は、公式の Extension Support Matrix で確認します。コミュニティが保守する一覧で、執筆時点では、おおむね次のとおりです。
| 拡張 | 対応状況の概要 |
|---|---|
| MCP Apps | Claude (ウェブ)、Claude Desktop、VS Code の GitHub Copilot、Microsoft 365 Copilot、Goose、Postman、ChatGPT、Cursor などが対応 |
| Skills | 一部対応 (ChatGPT、fast-agent、MCP Inspector は部分対応)。mcpc が対応 |
| OAuth Client Credentials | 一覧では mcpc が対応 |
| Enterprise-Managed Authorization | 一覧では Archestra.AI と mcpc が対応 |
Tasks は、この一覧には載っていません。この表は変わるため、採用の判断の直前に、必ず最新の一覧を確認してください。認可の拡張は、コアの認可の機能 (DCR、CIMD) とは別に追跡されます。
採用判断
拡張は、クライアントが未対応なら機能しません。採用の判断では、次のことを確認します。
- 利用するクライアントが、その拡張に対応しているか (対応状況の一覧と、実機での確認)
- 未対応のクライアントで、機能が失われたときの、フォールバックがあるか
- 拡張の仕様の成熟度。公式の拡張か、実験的な拡張か。実験的なものは、変わる可能性がある
2. 主要な拡張
| 拡張 | 用途 | 補足 |
|---|---|---|
| Tasks | 非同期の長時間処理、途中入力、永続的なハンドル | 2025-11-25 では実験的機能。2026-07-28 で拡張に移行 |
| MCP Apps | 対話的 UI の埋め込み | Claude Desktop などのホストで描画 |
| Skills | エージェントのワークフロー手順の配布 | SEP-2640 は Final。Skills over MCP ワーキンググループが維持。SDK とホストの対応は進行中 |
| OAuth Client Credentials | マシン間 (M2M) 認証 | 認可拡張 |
| Enterprise-Managed Authorization | IdP による一元的なアクセス制御 | 認可拡張 |
| Server Cards | 接続前のサーバーの発見 | 実験的な拡張のリポジトリーで規定 (SEP-2127) |
3. 開発者がつまずきやすいポイント
3.1 拡張をクライアントの対応なしに前提にする
拡張は、既定で無効で、双方の宣言が必要です。クライアントの _meta に、拡張が入っているかを確認してから使います。Tasks のように、結果の形が変わる拡張は、宣言していないクライアントに返してはいけません。
3.2 UI だけで結果を返す
MCP Apps に対応しないクライアントでは、UI が表示されません。ツールは、UI がなくても意味のあるテキストや構造化された結果を返します。
3.3 Tasks を、同期の呼び出しのように扱う
CreateTaskResult は、最終結果ではありません。resultType を確認し、tasks/get で、終了状態までポーリングします。pollIntervalMs を無視した高頻度のポーリングは避けます。タスク ID は、永続化して、再起動後に再開できるようにします。tasks/result と tasks/list は廃止されています。
3.4 input_required の応答先を取り違える
通常の MRTR では、再試行の tools/call に inputResponses を付けます。Tasks では、tasks/update で返します。どちらを使うかは、返ってきた結果の形で判断します。
3.5 拡張の識別子と設定を誤る
識別子は、完全な文字列 (io.modelcontextprotocol/tasks など) で、空のオブジェクトは設定がないことを示します。破壊的な変更は、新しい識別子になるため、バージョン付きの識別子が現れることがあります。
3.6 スキルの内容を信頼する
Skills で配られた SKILL.md は、信頼できない入力です。ツールの description と同様に、プロンプトインジェクションの経路になり得ます。ホスト側のコードの実行や権限の付与には、承認を求め、ダイジェストで内容の変化を検出します。詳細は AIエージェント特有の脅威 - プロンプトインジェクションとツール汚染 を参照してください。
3.7 Server Card にツールの一覧や機密を入れる
Server Card は公開文書です。ツールや capabilities は、実行時の */list と server/discover で確認するもので、カードには書きません。資格情報も入れません。
3.8 対応状況の一覧を固定の事実として扱う
一覧は、コミュニティが保守していて、頻繁に変わります。ドキュメントやコードに表を写さず、リンクを張り、採用の時点で確認します。
4. コード例
拡張を宣言するクライアントのリクエスト
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "run_pipeline",
"arguments": { "repo": "example/app" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
},
"io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" }
}
}
}
サーバーの宣言 (server/discover)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"supportedVersions": ["2026-07-28"],
"capabilities": {
"tools": {},
"extensions": {
"io.modelcontextprotocol/tasks": {},
"io.modelcontextprotocol/ui": {}
}
},
"ttlMs": 3600000,
"cacheScope": "public"
}
}
MCP Apps の UI を参照するツール定義
ツールの _meta.ui.resourceUri が、UI のリソースを指します。
{
"name": "show_sales_dashboard",
"description": "Show sales by region. Returns a text summary as well as an interactive dashboard.",
"inputSchema": {
"type": "object",
"properties": { "year": { "type": "integer" } },
"required": ["year"]
},
"_meta": {
"ui": { "resourceUri": "ui://sales/dashboard" }
}
}
Tasks のクライアントのポーリング
結果の形 (resultType) で処理を分けます。TypeScript の擬似コードです。タスクの項目の正確な形は、Tasks 拡張の仕様 (ext-tasks) で確認してください。
async function callMaybeTask(client: McpClient, params: CallToolParams) {
const first = await client.request("tools/call", params);
if (first.resultType !== "task") return first; // 通常の結果
const taskId = first.task.taskId;
await persistTaskId(taskId); // 再起動後に再開できるようにする
let delay = first.task.pollIntervalMs ?? 2000;
for (;;) {
await sleep(delay);
const t = await client.request("tasks/get", { taskId });
switch (t.status) {
case "completed":
return t.result;
case "failed":
throw new Error(t.error.message);
case "cancelled":
throw new Error("task cancelled");
case "input_required": {
const inputResponses = await collectInputs(t.inputRequests);
await client.request("tasks/update", { taskId, inputResponses });
break;
}
default:
delay = t.pollIntervalMs ?? delay; // working
}
}
}
5. まとめ
- 拡張は、コアの外側のオプトイン式の機能。
capabilities.extensionsで双方が宣言し、識別子は{vendor-prefix}/{extension-name} - Tasks は、長時間の処理を
taskIdのハンドルで扱い、tasks/getのポーリングとtasks/updateで進める。tasks/resultとtasks/listは廃止 - MCP Apps は、サンドボックス化された iframe に対話的な UI を描画する。未対応のクライアント向けに、テキストの結果も返す
- Skills over MCP は、
skills/listとskills/getとresources/readで、スキルを発見、取得する。内容は信頼できない入力で、ダイジェストで検証する - 認可の拡張は、OAuth Client Credentials と Enterprise-Managed Authorization
- Server Card は、接続前の発見のための公開メタデータ。ツールや capabilities は含まない
- 採用前に、Extension Support Matrix で対応状況を確認し、フォールバックを設計する