コンテンツにスキップ

サンプリングとルート

機械翻訳

このページは英語版ドキュメントから自動翻訳されたものであり、正式な版は英語版のページです。不自然な箇所があれば、翻訳についてで報告の方法を説明しています。

ハンドラーは、接続しているクライアントにさらに 2 つのことを要求できます。1 つはクライアント自身のモデルによる補完、つまりサンプリングです。もう 1 つはクライアントのワークスペースフォルダー、つまりルート(roots)です。

どちらも、SDK が話すすべてのプロトコルバージョンで引き続き動作します。ただし、これらを前提に設計する前に、次の警告を読んでください。

2026-07-28 仕様で非推奨

サンプリングとルートは 2026-07-28 で非推奨になりました(SEP-2577)。引き続き完全に機能し、削除の対象になるまで少なくとも 12 か月は仕様に残りますが、新しい実装はこれらを土台にすべきではありません。推奨される移行先は次のとおりです。サンプリングの代わりに LLM プロバイダーの API と直接統合し、ルートの代わりにツールのパラメーター、リソース URI、またはサーバー設定でディレクトリを渡します。SDK 全体の一覧は 非推奨の機能 にあります。

サンプリング:クライアントのモデルを借りる

リゾルバーが Sample(...) を返すと、ツールは補完結果を受け取ります。これは 依存関係Elicit を動かしているのと同じ依存関係のしくみを通ります。

server.py
from typing import Annotated

from mcp.server import MCPServer
from mcp.server.mcpserver import Resolve, Sample
from mcp.types import CreateMessageResult, SamplingMessage, TextContent

mcp = MCPServer("Bookshop")


def draft_blurb(title: str) -> Sample:
    prompt = f"Write a one-sentence blurb for the book {title!r}."
    return Sample(
        [SamplingMessage(role="user", content=TextContent(type="text", text=prompt))],
        max_tokens=60,
    )


@mcp.tool()
async def blurb(title: str, draft: Annotated[CreateMessageResult, Resolve(draft_blurb)]) -> str:
    """Draft a blurb for a book."""
    return draft.content.text if draft.content.type == "text" else "No blurb."
  • Sample(messages, max_tokens=...)sampling/createMessage のパラメーターをそのまま反映しています。注入される値はクライアントの CreateMessageResult です。tools または tool_choice を渡すと、代わりに CreateMessageResultWithTools になります。
  • クライアントは sampling ケイパビリティを宣言している必要があります(tools または tool_choice を渡す場合は sampling.tools)。宣言していない場合、クライアントが処理できないリクエストを送る代わりに、呼び出しは -32021 のプロトコルエラーで失敗します。バックチャネル(back-channel)のない 2026 年より前のセッションでは、送る経路がそもそもないため、いつものバックチャネルなしのエラーで失敗します。
  • 2026-07-28 では、リクエストはマルチラウンドトリップ(multi-round-trip)のフローの中で配送されます(マルチラウンドトリップリクエスト)。2025-11-25 では、クライアントへの単独のリクエストです。コードはどちらでも同じですが、マルチラウンドトリップのルールに注意してください。リクエストは再試行の各ラウンドでまったく同じ内容にならなければならないため、ツールの引数やその他の安定したデータだけから組み立ててください。
  • include_context には触れないでください。"none" 以外の値はそれ自体が非推奨で(SEP-2596)、ほとんどのクライアントが宣言しないケイパビリティを必要とします。

ルート:これはどこに置くべきか

ルートは、サーバーが操作してよいとクライアントが示すフォルダーです。参考情報としての案内であり、アクセス制御のしくみではありません。リゾルバーは ListRoots() を返します。

server.py
from typing import Annotated

from mcp.server import MCPServer
from mcp.server.mcpserver import ListRoots, Resolve
from mcp.types import ListRootsResult

mcp = MCPServer("Bookshop")


def workspace_roots() -> ListRoots:
    return ListRoots()


@mcp.tool()
async def catalog_folder(roots: Annotated[ListRootsResult, Resolve(workspace_roots)]) -> str:
    """Pick the folder the catalog export should go to."""
    if not roots.roots:
        return "No workspace folders shared."
    return str(roots.roots[0].uri)
  • 注入される ListRootsResultRoot のリストを持ちます。それぞれが file:// URI と、省略可能な表示名です。
  • 条件はサンプリングと同じです。roots ケイパビリティが宣言されていなければ、リクエストを送る代わりに呼び出しは -32021 で失敗します。

通信路の反対側では、クライアントはすでに持っているコールバックで両方のリクエストに応答します。sampling_callbacklist_roots_callback で、クライアントのコールバック で説明しています。

2025 年世代の接続では

ctx.session.create_message(...)ctx.session.list_roots() は、セッションを直接操作するコードのために今も存在します。これらはバックチャネルが存在する場所(2025 年世代の、ステートレスではない接続)でのみ動作し、呼び出すと非推奨の警告が出ます。上で紹介したリゾルバーのマーカーがサポートされる形です。ネゴシエートされたバージョンから配送方法を選び、警告も出しません。

まとめ

  • リゾルバーから Sample(...) または ListRoots() を返します。ツールは、ほかの依存関係と同じように CreateMessageResult または ListRootsResult を受け取ります。
  • クライアントは対応するケイパビリティを宣言しなければなりません。そうでなければ、リクエストは送られず、呼び出しは -32021 で失敗します。
  • どちらの機能も 2026-07-28 で非推奨です。当面は完全に機能しますが、新しい設計には向きません。サンプリングよりプロバイダーの API を、ルートより明示的なパラメーターを選んでください。

遅いツールがどこまで進んだかを報告するには、進捗 を参照してください。