はじめに:すべてがToolに見えてしまう
タスク管理サービスをMCPサーバーとして公開すると考えてみましょう。タスクの取得、検索、作成、ステータス変更、今日の計画、週次レビュー。SDKではToolを簡単に登録できるため、すべてToolとして実装したくなります。
しかし、Tools・Resources・Promptsは、同じ機能を異なる形式で表す仕組みではありません。最も重要な違いは、単なる「処理・データ・指示」の違いではなく、誰が利用を開始するかです。
機能 | 一言で表すと | 主な利用主体 |
|---|---|---|
Tools | 処理を実行する | AIモデル |
Resources | データをコンテキストとして参照する | アプリケーション |
Prompts | 再利用可能な指示やワークフローを開始する | ユーザー |
これはMCPの公式仕様が示す、model-controlled、application-driven、user-controlledという区分に対応します。2026年7月13日時点で公式サイトが最新としている安定仕様は2025-11-25版です。
Tools・Resources・Promptsの違い
Toolsはモデルが実行する処理
Toolsは、モデルが会話の状況から必要性を判断して呼び出す処理です。API呼び出し、データベース検索、計算、外部システムの更新などを公開できます。
重要なのは、Toolが書き込み専用ではないことです。Tools仕様でも、データベースへの問い合わせや計算が例示されています。
tasks.create
tasks.update_status
tasks.search
tasks.calculate_workloadモデルが「期限切れ」「自分が担当」「優先度順」という条件を組み立て、必要なタイミングで検索するなら、tasks.searchは読み取り専用でもToolが自然です。
Resourcesはアドレスを持つコンテキスト
Resourcesは、ファイル、データベーススキーマ、アプリケーション固有の情報などを、モデルへ渡すコンテキストとして公開します。各ResourceはURIで識別されます。
task://tasks/TSK-123
task://projects/PRJ-1/summary
task://docs/status-rules
task://users/me/preferencesResources仕様で定義されるResource Templateを使えば、task://tasks/{task_id}のような動的な参照先も提供できます。クライアントはResourcesを一覧表示、検索、選択したり、会話へ自動追加したりできます。対応するサーバーでは、一覧変更通知や個別Resourceの更新購読も可能です。
Resourceは「読み取りAPI」の別名ではありません。URIで識別でき、その内容自体をコンテキストとして扱いたい情報に向いています。
Promptsはユーザーが選ぶワークフロー
Promptsは、サーバーが公開する構造化されたメッセージテンプレートです。引数を受け取り、埋め込みResourceを含むメッセージも返せます。クライアント上では、スラッシュコマンドやメニュー項目として提示されるイメージです。
plan_today
review_week
triage_overdue_tasks
prepare_sprint_retrospectivePrompts仕様では、ユーザーが明示的に選択するuser-controlledな機能とされています。Promptは、サーバーが密かに注入するシステムプロンプトではありません。ユーザーが発見し、必要なら引数を指定して開始する公開インターフェースです。
「何を返すか」ではなく「誰が開始するか」
分類に迷ったら、戻り値より開始主体を確認します。
- モデルが状況に応じて実行を判断する処理ならTool
- アプリケーションがURIで識別し、コンテキストとして提示するデータならResource
- ユーザーが明示的に開始する定型手順ならPrompt

これは排他的な分類ではありません。ユーザーがPromptを開始し、返されたメッセージを受けたモデルがToolsを呼び出すことがあります。PromptにはResourceも埋め込めます。ただし、Prompt自体がサーバー上でToolを直接実行するわけではありません。実際のTool選択と呼び出しは、ホスト、クライアント、モデルの実行ループで行われます。
タスク管理サービスへの割り当て
作成・更新・削除はTools
tasks.create
tasks.update_status
tasks.assign
tasks.delete外部状態を変更するため、Toolsとして公開します。特にtasks.deleteのような破壊的操作には、認可、入力検証、監査ログに加え、ユーザーが実行を確認・拒否できる設計が必要です。
MCPのannotationsで破壊性などを示せますが、それはヒントにすぎません。サーバーはクライアントの確認画面だけに依存せず、自身の安全策を実装します。
個別タスクとプロジェクト情報はResources
task://tasks/{task_id}
task://projects/{project_id}
task://projects/{project_id}/summary
task://docs/workflow-rules個別タスクの現在状態、プロジェクトの説明、運用ルールは、URIで識別可能な参照情報です。既知のIDを開く処理は、検索条件を組み立てる操作ではなく、アドレスを指定したコンテキスト取得と考えられます。
Resourceにも認可は必要です。URIを推測しにくくするだけでは不十分であり、読み取りごとにユーザーとテナントのアクセス権を検証します。
タスク検索は読み取り専用Tool
次の依頼を考えます。
自分が担当している期限切れのタスクを、優先度順に取得して。
これは単一URIの読み取りではありません。モデルが担当者、期限、完了状態、並び順を組み立てて実行するため、tasks.searchという読み取り専用Toolが自然です。
検索結果に各タスクのResource URIを含めれば、「発見はTool、詳細参照はResource」と分担できます。大量の結果を返す代わりに、ページングや件数制限を設け、選択に必要な項目だけを構造化して返すと扱いやすくなります。
今日の計画と週次レビューはPrompts
plan_today
review_week
prepare_standupplan_todayは、次の手順をモデルへ提示できます。
- 未完了タスクを確認する
- 期限切れタスクを抽出する
- 優先順位を整理する
- 今日取り組むタスクを3件提案する
- 変更はユーザー確認後に実行する
これは単一のAPI操作ではなく、ユーザーが開始し、モデルがResourcesとToolsを組み合わせて進める定型ワークフローです。MCP公式ブログのPrompt例でも、引数と埋め込みResourcesを組み合わせる方法が紹介されています。

要件 | 選択 | 理由 |
|---|---|---|
タスクを作成する | Tool | 外部状態を変更する |
ステータスを変更する | Tool | 副作用がある |
条件を指定して検索する | Tool | モデル主導の動的検索 |
IDが既知のタスクを参照する | Resource | URIで識別できる |
運用ルールを読む | Resource | 安定した参照情報 |
今日の計画を作る | Prompt | ユーザーが開始する定型手順 |
週次レビューを行う | Prompt | 複数機能を使うワークフロー |
すべてをToolにしない理由
次のようなToolsが並ぶと、モデルは境界を判断しにくくなります。
get_task
get_task_detail
fetch_task
find_task
search_task
list_tasks問題は個数だけでなく、責務の重複です。似た入力と説明を持つToolsが増えるほど、誤選択の余地が増えます。
すべてをToolにすると、タスク、プロジェクト、運用文書をURI空間で整理できず、Resource Template、クライアントでの選択、購読なども活かせません。また、「検索し、優先順位を付け、確認後に更新する」という手順をToolのdescriptionへ埋め込むと、個別操作の契約と業務フローが混ざります。定型手順はPromptへ分離した方が明確です。
RESTのGET・POSTとは別の軸で考える
GET → Resource、POST → Toolという対応は正しくありません。HTTPメソッドは転送上の操作を表しますが、MCPの分類は、モデルへ機能をどう見せ、誰が利用を開始するかを表します。
書き込みは原則Toolです。読み取りは用途で分けます。
Resource向き
- URIで識別できる
- 内容自体をコンテキストとして使う
- アプリケーションやユーザーが選択・閲覧する
- 同じ情報を繰り返し参照する
Tool向き
- 検索条件が動的である
- 集計や計算が必要である
- モデルが必要性を判断して取得する
- 複雑な業務処理を伴う
認可は分類基準ではなく、両方に必要な横断的要件です。
AIが使いやすいToolの設計
名前とdescriptionで境界を示す
名前はドメインと操作を一貫して組み合わせます。
tasks.create
tasks.search
tasks.update_status
tasks.deleteexecuteやtask_operationのように対象や操作が分からない名前は避けます。2025-11-25仕様では、Tool名は1〜128文字が推奨され、ASCII英数字、アンダースコア、ハイフン、ドットを使用し、サーバー内で一意にします。
悪いdescriptionは、利用場面と変更範囲が不明です。
Updates a task.改善例では境界まで書きます。
Updates the status of one existing task.
Use this only when the user has requested a status change.
This tool does not modify the task title, assignee, or due date.inputSchemaはモデル向けに再設計する
バックエンドAPIの型をそのまま公開すると、内部用フラグや曖昧な互換項目までモデルに見せる場合があります。inputSchemaは、モデルが正しい引数を組み立てられる最小の契約にします。
{
"name": "tasks.update_status",
"description": "Updates the status of one existing task.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"task_id": {
"type": "string",
"pattern": "^TSK-[0-9]+$",
"description": "Stable task identifier, such as TSK-123."
},
"status": {
"type": "string",
"enum": ["todo", "in_progress", "done"]
}
},
"required": ["task_id", "status"]
}
}自由入力よりenumを使い、必須項目や形式をSchemaへ入れ、安定IDと表示名を区別します。無関係な操作を一つのToolへ詰め込まないことも重要です。
inputSchemaは有効なJSON Schemaオブジェクトである必要があり、$schema省略時はJSON Schema 2020-12が既定です。構造化結果にはoutputSchemaを定義できます。
annotationsは安全策ではない
readOnlyHint、destructiveHint、idempotentHint、openWorldHintで性質を補足できます。ただし、Tools仕様は、信頼できるサーバーから得た場合を除き、annotationsを信頼できない情報として扱うよう求めています。認可、確認、入力検証、冪等性制御の代わりにはなりません。
まとめ:3つの質問で判断する
- モデルが状況に応じて実行する処理か? → Tool
- アプリケーションがURIで識別し、コンテキストとして扱うデータか? → Resource
- ユーザーが明示的に開始する定型作業か? → Prompt
読み取りでも動的な検索や計算ならToolになり、書き込みは原則Toolです。GETとResourceは同義ではありません。Promptsは固定文字列ではなく、ResourcesとToolsを活用する作業の入口になれます。
REST APIをそのまま移植するのではなく、Tool名、description、Schema、Resource URI、Promptの手順を、モデル・アプリケーション・ユーザーに向けたインターフェースとして設計することが、使いやすいMCPサーバーへの近道です。