AIエージェントとシステムをつなぐMCP入門(リソース編)
Back to Topはじめに
#本ページは「AIエージェントとシステムをつなぐMCP入門」の続編です。
今回は、リソースについて説明します。
MCPのリソースは、AIモデルが回答を生成する際に参照するコンテキスト情報(ファイル、ガイド、仕様など)を提供する機能です。
ツールが「AIモデルの判断」で実行され、プロンプトが「ユーザーの意思」で選択されるのに対し、リソースは「アプリケーション主導(Application-driven)」でその組み込みを決定します。
本記事で掲載しているコードはこちらで公開しています。
連載:AIエージェントとシステムをつなぐMCP入門
今回使用するライブラリなど
#- npm@11.11.1
- node@22.22.0
- typescript@6.0.3
- @modelcontextprotocol/sdk@1.29.0
- zod@4.3.6
使用例
#- 開発ガイドの共有: コーディング規約や設計方針をリソース化して、AI生成時の前提情報として渡します
- 仕様断片の参照: API仕様、エラーコード定義、入力制約などの抜粋をリソースとして公開し、コード生成の精度を高めます
- 動的パラメーターによって切り替える情報の提供: URIテンプレートを使い、可変パラメーターで内容が変わるリソースを提供します
ツール、プロンプト、リソースの違い
#これまでの特集でツール、プロンプト、リソースの主要要素に触れてきたので、ここで役割を振り返ります。
| 要素名 | 主な役割 | 制御主体 | 識別方法 |
|---|---|---|---|
| リソース | データ・コンテキスト(静的な知識)の提供 | アプリケーション主導 | リソースのURI |
| プロンプト | メッセージ・ワークフローのテンプレート | ユーザー主導 | プロンプト名 |
| ツール | 具体的な関数の実行(能動的なアクション) | AIモデルによる実行 | ツール名 |
リソースの種類
#MCPのリソースは、URIの与え方によって2種類に分かれます。
| 種類 | 説明 | 用途例 |
|---|---|---|
| 静的リソース | 固定URIで一意に特定されるリソース | ガイド、固定仕様、設定情報など |
| リソーステンプレート | URIテンプレート(RFC 6570)でパラメーター化されたリソース | IDや名前などの可変要素で内容が変わる情報 |
プロトコルメッセージ
#MCPのリソースに関するメッセージは6種類あります。
| メッセージ | 方向 | 説明 |
|---|---|---|
resources/list |
クライアント → サーバー | 利用可能なリソース一覧を取得する(ページネーション対応) |
resources/templates/list |
クライアント → サーバー | リソーステンプレート一覧を取得する |
resources/read |
クライアント → サーバー | URIを指定してリソースのコンテンツを取得する |
resources/subscribe |
クライアント → サーバー | 指定URIのリソース変更通知を購読する(ケーパビリティsubscribe: trueが必要) |
notifications/resources/updated |
クライアント ← サーバー | 購読中のリソースが変更されたことを通知する |
notifications/resources/list_changed |
クライアント ← サーバー | リソース一覧が変化したことを通知する(ケーパビリティlistChanged: trueが必要) |
※通知を検証するためには、リソースの源泉を別に設け かつ 源泉側の変更検知も必要なため、サンプルには含めていません。
sequenceDiagram actor client as MCP Client participant server as MCP Server client ->> server: リソース一覧取得(resources/list) server -->> client: リソース一覧 client ->> server: リソース取得(resources/read) server -->> client: リソース
データ構造(Data Types)
#- リソースコンテンツ
uri: リソースを一意に識別可能なURIname: リソース名title: 表示用のタイトルdescription(任意): リソースの説明icons(任意): アイコンリストmimeType(任意): コンテンツのMIMEタイプ。テキストまたはバイナリ(Base64エンコードが必要)を指定可。size(任意): バイト数
- アノテーション(Annotations): クライアントへのヒント
audience: 誰向けのリソースか示す情報。user,assistantまたは両方を指定可。priority: 0.0~1.0の数値で示される重要度(1.0が最重要)lastModified: 最終更新日時(ISO8601形式のタイムスタンプ)
URIスキーム
#リソースのURIには目的に応じたスキームを選びます。
| スキーム | 用途 | 備考 |
|---|---|---|
https:// |
Web上のリソースを参照 | クライアント自身がアクセスできる場合に使用する。サーバー経由で取得する場合は独自スキームの検討が推奨されます |
file:// |
ファイルシステムのような構造を表現したいリソース | ファイルシステムとのマッピングは必須ではなく、値の取得先は自由(DBや外部APIなど) |
git:// |
Gitリソース | コミット、ブランチ、パスなどのGit固有の構造を表現 |
| カスタム | 独自スキームによる任意のリソース | RFC3986準拠。本サンプルのmemory://、orders://もこれに該当 |
サーバーはすべてのリソースURIを検証する
サンプルでは省略していますが、パストラバーサルなど意図しないアクセスを防止しなければいけません。
fileでディレクトリを表現する場合
mimeTypeにinode/directory(XDG規格)を指定することが推奨されます。
実装サンプル
#コードの全体はこちらをご覧ください。
静的リソースの登録
#固定URIでリソースを公開する例です。
registerResourceの第2引数にURI文字列を渡すと静的リソースになります。
// リソース: アノテーション付きの静的リソース(テキストコンテンツ)
const testGuideUri = "memory://guides/testcase-prompt-playbook";
server.registerResource(
"testcase-prompt-playbook",
testGuideUri,
{
mimeType: "text/markdown",
description: "テスト観点生成のガイド",
annotations: {
audience: ["assistant"], // AIへの参照情報として位置づける
priority: 0.8, // 重要度(高め)
lastModified: "2026-06-28T00:00:00Z",
},
},
async () => ({
contents: [{
uri: testGuideUri, mimeType: "text/markdown",
text: [
// 実務ではもっと細かい指示が必要になりますが、行数を抑えるため最小限に留めています
"# APIテストケース作成ガイド",
"- 仕様の観点: 正常系、代替系、異常系、境界値、認可、冪等性",
"- 基本フローの正常系を中心に、代替系、異常系、その他の観点を付加する形にまとめる。",
"- ユースケースの検証を主眼とし、入力値検証などは含めない(単体テストで担保する)",
"- 必要に応じて分類しながら、箇条書きで簡潔にまとめる",
].join("\n")
}]
}),
);
バイナリコンテンツの指定例
バイナリコンテンツ(画像など)はblobにBase64エンコード文字列を設定します。
// リソース: バイナリコンテンツの例(画像)
server.registerResource(
"company-logo",
"file://assets/logo.png",
{ mimeType: "image/png", description: "企業ロゴ画像" },
async () => ({
contents: [{ uri: "file://assets/logo.png", mimeType: "image/png", blob: "<Base64エンコードされたデータ>" }],
}),
);
リソーステンプレートの登録
#ResourceTemplateクラスを使うと、URIテンプレート(RFC 6570)でパラメーター化されたリソースを公開できます。
{orderId}のようなプレースホルダーがリクエスト時に展開されます。
listコールバックはresources/listで返す候補一覧を定義します(省略不可、不要ならundefinedを渡します)。
resources/readリクエスト時、クライアントはorders://O00001/detailのようにテンプレートを展開したURIを指定します。
サーバー側では{orderId}部分が変数として分解され、ハンドラーに渡されます。
// リソーステンプレート: URIのパラメータで内容が変わる動的リソース
server.registerResource(
"order-detail",
new ResourceTemplate("orders://{orderId}/detail", {
list: async () => ({
resources: [
{ uri: "orders://O00001/detail", name: "O00001", mimeType: "application/json" },
{ uri: "orders://O00002/detail", name: "O00002", mimeType: "application/json" },
],
}),
}),
{ mimeType: "application/json", description: "受注詳細" },
async (uri, { orderId }) => ({
contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify({ orderId, status: "pending" }) }],
}),
);
- 動作確認
まとめ
#- リソースは、AIへの参照情報を明示的に管理したい場合に有効です。
- 静的リソースは固定情報(ガイド、仕様など)、リソーステンプレートは可変情報(IDベースの詳細など)に向いています。
- アノテーションを設定することで、クライアントがリソースを適切に選択し、優先順位付けできます
- プロンプトと組み合わせると、生成指示と参照情報の両方を標準化できます



