Перейти до змісту

Семплювання та кореневі каталоги

Машинний переклад

Цю сторінку перекладено автоматично з англомовної документації, і основною версією є англомовна сторінка. Якщо щось читається неправильно, на сторінці Переклади пояснено, як про це повідомити.

Обробник може попросити в під'єднаного клієнта ще дві речі: завершення від власної моделі клієнта (семплювання (sampling)) і робочі теки клієнта (кореневі каталоги (roots)).

Обидві можливості досі працюють на кожній версії протоколу, яку підтримує SDK. Але перш ніж будувати на них дизайн, прочитайте попередження:

Оголошено застарілими у специфікації 2026-07-28

Семплювання та кореневі каталоги є застарілими починаючи з 2026-07-28 (SEP-2577). Вони лишаються повністю працездатними й залишатимуться у специфікації щонайменше дванадцять місяців, перш ніж їх можна буде вилучити, але нові реалізації не повинні на них спиратися. Запропоновані шляхи міграції: замість семплювання інтегруйтеся безпосередньо з API вашого постачальника LLM, а замість кореневих каталогів передавайте каталоги через параметри інструментів, 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 (sampling.tools, якщо передаєте tools або tool_choice). Якщо він цього не зробив, виклик завершується помилкою протоколу -32021, замість того щоб надсилати запит, який клієнт не здатен обробити. Сесія до 2026 року без зворотного каналу (back-channel) завершується своєю звичною помилкою про відсутність зворотного каналу, бо надсилати нема куди.
  • На 2026-07-28 запит доставляється всередині багатораундового потоку (Багатораундові запити); на 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)
  • Впроваджений ListRootsResult містить список об'єктів Root: URI file:// і необов'язкове відображуване ім'я.
  • Перевірка та сама, що й для семплювання: без оголошеної можливості roots виклик завершується помилкою -32021 замість надсилання запиту.

По той бік з'єднання клієнт відповідає на обидва запити колбеками, які в нього вже є: sampling_callback і list_roots_callback, описаними на сторінці Колбеки клієнта.

На з'єднаннях покоління 2025

ctx.session.create_message(...) і ctx.session.list_roots() досі існують для коду, що керує сесією напряму. Вони працюють лише там, де є зворотний канал (з'єднання покоління 2025, не безстанові), а їх виклик викидає попередження про застарілість. Маркери резолверів, описані вище, — це підтримувана форма: вони обирають спосіб доставки за узгодженою версією й не попереджають.

Підсумки

  • Повертайте Sample(...) або ListRoots() з резолвера; інструмент отримує CreateMessageResult або ListRootsResult, як і будь-яку іншу залежність.
  • Клієнт мусить оголосити відповідну можливість, інакше виклик завершується помилкою -32021 замість надсилання запиту.
  • Обидві можливості оголошено застарілими у 2026-07-28: поки що повністю працездатні, але непридатні для нових проєктів. Надавайте перевагу API постачальника над семплюванням і явним параметрам над кореневими каталогами.

Як повідомляти, наскільки просунувся повільний інструмент: Перебіг виконання.