Семплювання та кореневі каталоги
Машинний переклад
Цю сторінку перекладено автоматично з англомовної документації, і основною версією є англомовна сторінка. Якщо щось читається неправильно, на сторінці Переклади пояснено, як про це повідомити.
Обробник може попросити в під'єднаного клієнта ще дві речі: завершення від власної моделі клієнта (семплювання (sampling)) і робочі теки клієнта (кореневі каталоги (roots)).
Обидві можливості досі працюють на кожній версії протоколу, яку підтримує SDK. Але перш ніж будувати на них дизайн, прочитайте попередження:
Оголошено застарілими у специфікації 2026-07-28
Семплювання та кореневі каталоги є застарілими починаючи з 2026-07-28 (SEP-2577). Вони лишаються повністю працездатними й залишатимуться у специфікації щонайменше дванадцять місяців, перш ніж їх можна буде вилучити, але нові реалізації не повинні на них спиратися. Запропоновані шляхи міграції: замість семплювання інтегруйтеся безпосередньо з API вашого постачальника LLM, а замість кореневих каталогів передавайте каталоги через параметри інструментів, URI ресурсів або конфігурацію сервера. Повний перелік для всього SDK — на сторінці Застарілі можливості.
Семплювання: позичити модель клієнта
Резолвер повертає Sample(...), а інструмент отримує завершення — через той самий механізм залежностей, що виконує Elicit на сторінці Залежності:
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():
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: URIfile://і необов'язкове відображуване ім'я. - Перевірка та сама, що й для семплювання: без оголошеної можливості
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 постачальника над семплюванням і явним параметрам над кореневими каталогами.
Як повідомляти, наскільки просунувся повільний інструмент: Перебіг виконання.