Xでシェア

Writing / MCP

N° 10

MCPのTools・Resources・Promptsの違いと使い分け:タスク管理サービスで学ぶ設計判断

MCPのTools・Resources・Promptsを、単なる「処理・データ・指示」ではなく、モデル・アプリケーション・ユーザーの誰が利用を開始するかで整理します。タスク管理サービスを例に、読み取り専用ToolとResourceの境界、Promptによるワークフロー、AIが選びやすいTool名・description・Schemaの設計まで解説します。

このガイドに含まれます

MCP完全ガイド

この記事を読むとできるようになること

  • Tools・Resources・Promptsの責務を区別できる
  • タスク管理サービスに適したMCPインターフェースを設計できる

はじめに:すべてが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仕様でも、データベースへの問い合わせや計算が例示されています。

plaintext
 tasks.create
 tasks.update_status
 tasks.search
 tasks.calculate_workload

モデルが「期限切れ」「自分が担当」「優先度順」という条件を組み立て、必要なタイミングで検索するなら、tasks.searchは読み取り専用でもToolが自然です。

Resourcesはアドレスを持つコンテキスト

Resourcesは、ファイル、データベーススキーマ、アプリケーション固有の情報などを、モデルへ渡すコンテキストとして公開します。各ResourceはURIで識別されます。

plaintext
 task://tasks/TSK-123
 task://projects/PRJ-1/summary
 task://docs/status-rules
 task://users/me/preferences

Resources仕様で定義されるResource Templateを使えば、task://tasks/{task_id}のような動的な参照先も提供できます。クライアントはResourcesを一覧表示、検索、選択したり、会話へ自動追加したりできます。対応するサーバーでは、一覧変更通知や個別Resourceの更新購読も可能です。

Resourceは「読み取りAPI」の別名ではありません。URIで識別でき、その内容自体をコンテキストとして扱いたい情報に向いています。

Promptsはユーザーが選ぶワークフロー

Promptsは、サーバーが公開する構造化されたメッセージテンプレートです。引数を受け取り、埋め込みResourceを含むメッセージも返せます。クライアント上では、スラッシュコマンドやメニュー項目として提示されるイメージです。

plaintext
 plan_today
 review_week
 triage_overdue_tasks
 prepare_sprint_retrospective

Prompts仕様では、ユーザーが明示的に選択するuser-controlledな機能とされています。Promptは、サーバーが密かに注入するシステムプロンプトではありません。ユーザーが発見し、必要なら引数を指定して開始する公開インターフェースです。

「何を返すか」ではなく「誰が開始するか」

分類に迷ったら、戻り値より開始主体を確認します。

  • モデルが状況に応じて実行を判断する処理ならTool
  • アプリケーションがURIで識別し、コンテキストとして提示するデータならResource
  • ユーザーが明示的に開始する定型手順ならPrompt

これは排他的な分類ではありません。ユーザーがPromptを開始し、返されたメッセージを受けたモデルがToolsを呼び出すことがあります。PromptにはResourceも埋め込めます。ただし、Prompt自体がサーバー上でToolを直接実行するわけではありません。実際のTool選択と呼び出しは、ホスト、クライアント、モデルの実行ループで行われます。

タスク管理サービスへの割り当て

作成・更新・削除はTools

plaintext
 tasks.create
 tasks.update_status
 tasks.assign
 tasks.delete

外部状態を変更するため、Toolsとして公開します。特にtasks.deleteのような破壊的操作には、認可、入力検証、監査ログに加え、ユーザーが実行を確認・拒否できる設計が必要です。

MCPのannotationsで破壊性などを示せますが、それはヒントにすぎません。サーバーはクライアントの確認画面だけに依存せず、自身の安全策を実装します。

個別タスクとプロジェクト情報はResources

plaintext
 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

plaintext
 plan_today
 review_week
 prepare_standup

plan_todayは、次の手順をモデルへ提示できます。

  1. 未完了タスクを確認する
  2. 期限切れタスクを抽出する
  3. 優先順位を整理する
  4. 今日取り組むタスクを3件提案する
  5. 変更はユーザー確認後に実行する

これは単一のAPI操作ではなく、ユーザーが開始し、モデルがResourcesとToolsを組み合わせて進める定型ワークフローです。MCP公式ブログのPrompt例でも、引数と埋め込みResourcesを組み合わせる方法が紹介されています。

要件

選択

理由

タスクを作成する

Tool

外部状態を変更する

ステータスを変更する

Tool

副作用がある

条件を指定して検索する

Tool

モデル主導の動的検索

IDが既知のタスクを参照する

Resource

URIで識別できる

運用ルールを読む

Resource

安定した参照情報

今日の計画を作る

Prompt

ユーザーが開始する定型手順

週次レビューを行う

Prompt

複数機能を使うワークフロー

すべてをToolにしない理由

次のようなToolsが並ぶと、モデルは境界を判断しにくくなります。

plaintext
 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 → ResourcePOST → Toolという対応は正しくありません。HTTPメソッドは転送上の操作を表しますが、MCPの分類は、モデルへ機能をどう見せ、誰が利用を開始するかを表します。

書き込みは原則Toolです。読み取りは用途で分けます。

Resource向き

  • URIで識別できる
  • 内容自体をコンテキストとして使う
  • アプリケーションやユーザーが選択・閲覧する
  • 同じ情報を繰り返し参照する

Tool向き

  • 検索条件が動的である
  • 集計や計算が必要である
  • モデルが必要性を判断して取得する
  • 複雑な業務処理を伴う

認可は分類基準ではなく、両方に必要な横断的要件です。

AIが使いやすいToolの設計

名前とdescriptionで境界を示す

名前はドメインと操作を一貫して組み合わせます。

plaintext
 tasks.create
 tasks.search
 tasks.update_status
 tasks.delete

executetask_operationのように対象や操作が分からない名前は避けます。2025-11-25仕様では、Tool名は1〜128文字が推奨され、ASCII英数字、アンダースコア、ハイフン、ドットを使用し、サーバー内で一意にします。

悪いdescriptionは、利用場面と変更範囲が不明です。

plaintext
 Updates a task.

改善例では境界まで書きます。

plaintext
 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は、モデルが正しい引数を組み立てられる最小の契約にします。

json
{
  "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は安全策ではない

readOnlyHintdestructiveHintidempotentHintopenWorldHintで性質を補足できます。ただし、Tools仕様は、信頼できるサーバーから得た場合を除き、annotationsを信頼できない情報として扱うよう求めています。認可、確認、入力検証、冪等性制御の代わりにはなりません。

まとめ:3つの質問で判断する

  1. モデルが状況に応じて実行する処理か? → Tool
  2. アプリケーションがURIで識別し、コンテキストとして扱うデータか? → Resource
  3. ユーザーが明示的に開始する定型作業か? → Prompt

読み取りでも動的な検索や計算ならToolになり、書き込みは原則Toolです。GETとResourceは同義ではありません。Promptsは固定文字列ではなく、ResourcesとToolsを活用する作業の入口になれます。

REST APIをそのまま移植するのではなく、Tool名、description、Schema、Resource URI、Promptの手順を、モデル・アプリケーション・ユーザーに向けたインターフェースとして設計することが、使いやすいMCPサーバーへの近道です。

次のステップ

Python公式SDKで最小のMCPサーバーを作る:create_task Toolをstdioで公開する

Python公式MCP SDKのFastMCPを使い、入力検証・JSON保存・構造化出力・ToolErrorを備えたcreate_task Toolを実装します。MCP InspectorでSchemaを確認し、stdio経由でAIクライアントから呼び出すところまで解説します。

次の記事を読む