Claude Media
MCPのResources仕様を読み解く — resources/readでの参照の仕方

MCPのResources仕様を読み解く — resources/readでの参照の仕方

MCPのResources仕様が定めるresources/list・resources/readの挙動と、Annotations・URIスキームの使い分けを仕様原文から読み解きます。

Resourcesは、MCPサーバーがファイルやDBスキーマのようなデータをモデルに読ませるための仕組みです。Toolsとは違い「アプリケーション主導」という設計思想を取ります。モデルが自動で呼び出すのではなく、ホストアプリ側がどのリソースを文脈に含めるかを決める前提です。この記事では2026-07-28版の仕様原文から、resources/listresources/readの正確な挙動と、見落としやすいAnnotationsの使い方を読み解きます。

MCPのResources仕様で定義されていること

仕様が定めるのは主に3つのメッセージです。一覧を取るresources/list、中身を読むresources/read、パラメータ化されたリソースの雛形を取るresources/templates/listです。加えて、リソースの変更を検知する通知の仕組みも定義されています。resources/templates/listが持つ変数の候補を入力途中で絞り込みたいときは、MCPのCompletion仕様が定めるオートコンプリートの出番です。

Toolsと同じく、UIの形までは強制しません。ツリー表示で選ばせる、検索窓を出す、モデルの判断で自動的に文脈へ含める、といった実装は自由です。仕様が保証するのは、これらのメッセージのやり取りの形と、返ってくるデータの構造だけです。

resources/listで一覧を取得する仕組み

resourcesの能力(capability)を宣言したサーバーはresources/listに応答します。この一覧はページネーションに対応し、レスポンスにはnextCursorのほかttlMscacheScopeというキャッシュ用のフィールドが含まれます。同じ接続の中で他のリクエストの副作用として変化してはいけないという制約はToolsの一覧と同じ設計です。認可されたスコープによって見える集合が変わるのは許容されますが、それは呼び出しごとの認可情報に基づく変化として整理されています。

{
  "result": {
    "resultType": "complete",
    "resources": [
      {
        "uri": "file:///project/README.md",
        "name": "README.md",
        "mimeType": "text/markdown"
      }
    ],
    "nextCursor": "next-page-cursor",
    "ttlMs": 300000,
    "cacheScope": "public"
  }
}

resources/readで内容を取得する

resources/readはURIを1つ渡すだけのリクエストですが、返ってくるcontentsは配列です。1つのディレクトリリソースを読んだときに、配下の複数ファイルの中身をまとめて返す、といった使い方が想定されています。

Toolsのinput_requiredと同じ「複数回の往復リクエスト」(MRTR)パターンが、ここでも使えます。読み取りに追加の入力が必要なとき、サーバーはresources/readの結果としてInputRequiredResultを返せます。クライアントはinputResponsesを添えてリクエストを再送します。MRTRは2026-07-28版で新規導入され、それ以前のサーバー起点リクエスト方式を置き換えたパターンです。仕組みはTools側と共通なので、片方を実装すればもう片方への応用は難しくありません。

もう1つ見落としやすいのが、URIのスキームがhttps://のときの特別ルールです。詳しい条件は後述の「URIスキームの使い分け」でまとめて扱います。

テキストとバイナリではcontentsの中身の形が変わります。

{
  "contents": [
    { "uri": "file:///example.txt", "mimeType": "text/plain", "text": "本文" }
  ]
}
{
  "contents": [
    { "uri": "file:///example.png", "mimeType": "image/png", "blob": "base64-encoded-data" }
  ]
}

テキストはtextフィールドにそのまま文字列を入れ、バイナリはbase64エンコードしたblobフィールドに入れます。同じresources/readのレスポンスの中で、この2つのフォーマットはtextblobかで機械的に判別できます。

パラメータ化されたResource Templates

固定のURIではなく、file:///{path}のようなURIテンプレート(RFC 6570のURIテンプレート形式)でリソースの雛形を公開できます。resources/templates/listで取得し、テンプレートの引数は補完APIを通じて入力候補を提示できます。プロジェクト内の任意のファイルパスを受け付けるリソースのように、無限に近い集合を1つの定義で表現したいときに使う仕組みです。

変更を検知する仕組み

listChangedの能力を宣言したサーバーは、リソースの一覧が変わったときにnotifications/resources/list_changedを送ります。一覧そのものではなく、個々のリソースの中身の変更を追いたい場合はsubscribeの能力を使います。クライアントがsubscriptions/listenリクエストで監視したいURIをresourceSubscriptionsに指定すると、対象のリソースが変わるたびにサーバーからnotifications/resources/updatedが届きます。一覧レベルの変更検知と、個別リソースレベルの変更検知が別の能力として分かれている点が設計のポイントです。どちらも宣言しないサーバーはresources: {}のように空オブジェクトで宣言してかまいません。

リソースの増減が主な関心事ならlistChangedだけで足り、個々のファイルの中身が更新されたことをリアルタイムに伝えたいならsubscribeが要ります。両方を無条件に実装すると通知の配信コストが増えるので、サーバーが公開するリソースの性質(増減が多いか、中身の更新が多いか)に応じて選ぶのが実装上の判断になります。

Resourceが持つフィールド

1件のリソース定義はuri(一意な識別子)・nametitle(表示用の任意項目)・descriptioniconsmimeTypesize(バイト数、任意)で構成されます。nameは内部的な名前、titleは画面表示用の人間向けの名前という役割分担で、両方を持たせられます。sizeはクライアントが読み込み前にリソースの重さを見積もるために使えるヒントです。

Annotationsで使い方を制御する

リソース・リソーステンプレート・コンテンツブロックには、任意のannotationsを付けられます。audience"user""assistant"のどちらに向けた情報かを示す配列、priorityは0.0〜1.0で重要度を表し、1に近いほど「実質必須」、0に近いほど「完全に省略可」を意味します。lastModifiedはISO 8601形式の更新時刻です。

この3つは、Toolsの結果コンテンツ(テキスト・画像・音声・リソースリンク・埋め込みリソース)でも共通のフォーマットとして使われます。クライアントはこれを使って、対象読者でリソースを絞り込む、文脈に含める優先順位を決める、更新時刻順に並べ替える、といった処理ができます。大量のリソースを持つサーバーほど、Annotationsを適切に付けているかどうかが、モデルに渡る文脈の質を左右します。

URIスキームの使い分け

仕様が例示する標準スキームは3つです。https://はクライアントがサーバーを経由せず自力でWebから取得できる場合に使うべきものです。ただしサーバー自身がインターネット経由でダウンロードしてくる場合は、クライアントに直接フェッチさせたくないケースがあるため、その場合は他のスキームを使うべきだとされています。file://はファイルシステムのようにふるまうリソースに使い、実際の物理ファイルシステムに対応している必要はありません。ディレクトリのような特殊なリソースには、XDG MIMEタイプ(inode/directoryなど)を割り当てられます。git://はGitのバージョン管理システムとの統合用です。これら以外にも、URIの標準仕様(RFC 3986)に沿っていれば独自スキームを定義してかまいません。

存在しないリソースはどう返すか

エラー処理にも仕様独自の注意点があります。存在しないリソースへのresources/read-32602(Invalid Params)を返すべきで、後方互換のため-32002も同じ意味として受け入れるべきだとされています。そして空のcontents配列を「存在しない」の代わりに使ってはいけません。空配列は「リソースは存在するが中身がない」のか「そもそも存在しない」のか区別が付かず、意味が曖昧になるためです。

セキュリティ上の注意点

仕様はResourcesのセキュリティ考慮事項として5点を挙げています。すべてのリソースURIを検証すること、機微なリソースにはアクセス制御を実装すること、バイナリデータは適切にエンコードすること、操作の前にリソースの権限を確認すること、そしてfile://リソースを提供する際はディレクトリトラバーサル攻撃を防ぐためファイルパスをサニタイズすることです。

とくに最後の項目は実装で見落としやすいポイントです。file:///{path}のようなResource Templateでパスをそのまま受け取ると、../../etc/passwdのような相対パスの操作でファイルシステムの意図しない場所へ抜けられる余地が生まれます。テンプレートで任意のパスを受け付ける設計にするときほど、サーバー側でのパス正規化と許可範囲外へのアクセス拒否が欠かせません。

ToolsとResourcesの役割分担が実装に効く理由

Resources仕様を通読すると、Toolsとの役割分担が明確になります。Toolsはモデルが能動的に操作を起こす窓口、Resourcesはホストアプリが文脈として何を見せるかをコントロールする窓口です。この非対称性は、https://スキームの扱いにも表れています。クライアントが自力で取得できるものはサーバーを介在させない、というのは、サーバーを単なるプロキシにしないための設計判断です。自作サーバーでファイルシステムやドキュメントストアを公開するなら、Annotationsのpriorityを適切に設定することが、モデルの文脈枠を無駄に消費しないための実質的なレバーになります。

ResourcesとToolsという2つの仕組みは、Toolsの結果からもつながっています。ツールがresource_link型のコンテンツを返すと、そのURIはresources/readで参照できるものとして扱われます。ただし仕様は、ツールが返したresource_linkresources/listの一覧に必ず現れるとは限らないと明記しています。ツール呼び出しの副産物として一時的に生成されたリソースが、恒常的な一覧には載らないケースを想定した規定です。ResourcesとToolsを両方実装するサーバーでは、この非対称性を踏まえて「一覧に載せるリソース」と「ツール結果からだけ参照できるリソース」を意図的に使い分けられます。

まとめ

MCPのResources仕様は、resources/listresources/readresources/templates/listの3つのメッセージと、変更通知の仕組みを軸に構成されています。実装で押さえるべきは、空のcontents配列を「存在しない」の代用にしないこと、https://スキームを直接フェッチ可能な場合に限って使うこと、そしてAnnotationsで対象読者と優先度を明示することの3点です。Toolsの往復設計や決定的な順序といった共通の考え方はMCPのTools仕様を読み解くで扱っています。自分でMCPサーバーを実装する手順はMCPサーバー自作ガイドを、サーバーがどこまでの権限を持つべきかはMCPセキュリティガイドを参照してください。

この記事を共有:XはてブLinkedIn
MCP をもっと見る →