Обробка помилок
Машинний переклад
Цю сторінку перекладено автоматично з англомовної документації, і основною версією є англомовна сторінка. Якщо щось читається неправильно, на сторінці Переклади пояснено, як про це повідомити.
Інструмент може завершитися невдачею двома способами, і SDK обробляє їх зовсім по-різному.
Викиньте звичайний виняток — і його побачить модель. Викиньте MCPError — і його побачить протокол.
Ця сторінка — про те, як вибрати.
Помилка, яку модель може виправити
Візьмімо інструмент, який щось шукає, і нехай пошук нічого не знайде:
from mcp.server import MCPServer
mcp = MCPServer("Bookshop")
CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}
@mcp.tool()
def get_author(title: str) -> str:
"""Look up the author of a book in the catalog."""
if title not in CATALOG:
raise ValueError(f"No book titled {title!r} in the catalog.")
return CATALOG[title]
У цих двох рядках немає нічого специфічного для MCP. get_author викидає звичайний ValueError, як це зробила б будь-яка функція Python.
Викличте його з назвою, якої немає в каталозі, і подивіться на результат:
result.is_error # True
result.content # [TextContent(text="Error executing tool get_author: No book titled 'Nothing' in the catalog.")]
result.structured_content # None
- Запит виконався успішно. Результат є; на боці того, хто викликав, нічого не викинуто.
is_errorдорівнюєTrue, а повідомлення вашого винятку (з назвою інструмента на початку) лежить уcontent— саме там, де читає модель.structured_contentдорівнюєNone. У невдалого виклику немає значення, яке можна було б структурувати.
Це помилка інструмента, і так за замовчуванням обробляється будь-який виняток, який викидає ваш інструмент. І майже завжди це саме те, що потрібно.
Ваш інструмент викликає саме модель. Це вона обрала аргументи. Тож помилка інструмента — це репліка в розмові: модель читає «No book titled 'Nothing' in the catalog.», розуміє, що не вгадала назву, і викликає знову з кращою. Один raise — і маєте агента, що сам виправляє свої помилки.
Tip
Ніколи не повертайте повідомлення про помилку з інструмента через return. Повернутий рядок має is_error=False, тож для
моделі (і для кожного клієнтського інтерфейсу) це виглядає так, ніби інструмент спрацював і цей рядок і є відповіддю.
Пишіть raise. Сигнал — саме прапорець.
Помилка, яку модель не може виправити
Тепер замініть ValueError на MCPError.
from mcp import MCPError
from mcp.server import MCPServer
from mcp.types import INVALID_PARAMS
mcp = MCPServer("Bookshop")
CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}
@mcp.tool()
def get_author(title: str) -> str:
"""Look up the author of a book in the catalog."""
if title not in CATALOG:
raise MCPError(code=INVALID_PARAMS, message=f"No book titled {title!r} in the catalog.")
return CATALOG[title]
MCPError — це помилка протоколу в SDK. Це єдиний виняток, який обгортка інструмента не перехоплює: він поширюється далі, і весь запит tools/call завершується помилкою JSON-RPC замість результату.
{
"code": -32602,
"message": "No book titled 'Nothing' in the catalog."
}
- Результату немає. Ні
content, ніis_error— моделі нема чого читати. - Натомість помилку отримує застосунок-хост — так само, як отримав би, якби інструмента взагалі не існувало.
code,messageіdataдоходять без змін.INVALID_PARAMS— це-32602;mcp.typesекспортує його та інші коди помилок JSON-RPC (INVALID_REQUEST,INTERNAL_ERROR, ...) як константи, тож набирати магічні числа вручну не доведеться.
Check
Той самий пошук, той самий промах, але тепер виклик на боці клієнта викидає виняток замість того, щоб повернути результат:
mcp.shared.exceptions.MCPError: No book titled 'Nothing' in the catalog.
Перша версія давала моделі речення, на яке вона могла відреагувати. Ця не дає їй нічого.
Для get_author це однозначно гірше — і саме про це наступний розділ.
Який із них викидати
Ці два шляхи відповідають на два різні запитання.
- Викидайте будь-який виняток у разі збою виконання: те, що інструмент намагався зробити, не вдалося. Виклик обрала модель, тож саме модель має побачити наслідок і отримати шанс виправитися. Назва з помилкою, зовнішній API, що не відповів вчасно, рядок, якого не існує, — усе це помилки інструмента.
- Викидайте
MCPError, коли слід відхилити сам запит: клієнтові бракує можливості, від якої залежить інструмент, сервер не в тому стані, щоб обслуговувати будь-кого, той, хто викликає, пропустив обов'язковий крок. Жодна повторна спроба моделі нічого з цього не виправить, тож передавати їй повідомлення немає сенсу.
Вирішує одне запитання: чи могла б розумніша модель цього уникнути? Так -> звичайний виняток. Ні -> MCPError.
За цим критерієм друга версія get_author зробила хибний вибір: краща назва все виправляє, тож модель заслуговувала побачити повідомлення. Ця версія тут, щоб показати механізм, а не щоб його рекомендувати.
Info
MCPError імпортується як from mcp import MCPError і приймає code, message та необов'язкове
корисне навантаження data. Усе, що ви в них покладете, клієнт і отримає: SDK пересилає викинутий
MCPError дослівно, не очищуючи його.
Ресурс, якого не існує
Ресурси проводять ту саму межу й мають один іменований виняток для типового випадку.
from mcp.server import MCPServer
from mcp.server.mcpserver.exceptions import ResourceNotFoundError
mcp = MCPServer("Bookshop")
CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}
@mcp.resource("books://{title}")
def book(title: str) -> str:
"""The catalog entry for one book."""
if title not in CATALOG:
raise ResourceNotFoundError(f"No book titled {title!r} in the catalog.")
return f"{title} by {CATALOG[title]}"
books://{title} — це шаблон. Він збігається з будь-якою назвою, тому «URI коректний» і «книга існує» — два різні запитання, і відповісти на друге може лише ваша функція.
Коли не може — викиньте ResourceNotFoundError. SDK перетворює його на помилку протоколу, яку специфікація призначає для відсутнього ресурсу: -32602 із запитаним URI в data, тож клієнт знає, яке саме читання не вдалося.
{
"code": -32602,
"message": "No book titled 'Nothing' in the catalog.",
"data": {"uri": "books://Nothing"}
}
Зверніть увагу: тут немає напіврезультату з is_error=True. Читання ресурсу або повертає вміст, або завершується помилкою: у ресурсів є лише протокольний шлях. Про шаблони й усе інше, що стосується ресурсів, — на сторінці Ресурси.
Помилки, які ви ніколи не викидаєте
Некоректний аргумент ніколи не доходить до вашої функції.
Надішліть get_author параметр title, що не є рядком, — і SDK відхилить його за вхідною схемою ще до виклику вашої функції, як таку саму помилку інструмента з is_error=True, яку модель може прочитати й виправити. На сторінці Інструменти показано таке саме відхилення з обмеженням Field(le=50).
Це означає цілий клас інструкцій raise, які писати не треба: не перевіряйте повторно власні анотації типів.
Info
Усе на цій сторінці — те, що бачить клієнт, і Client у пам'яті, з яким ви писатимете
тести, бачить рівно те саме. Навіть raise_exceptions=True не перетворює помилку інструмента
назад на трасування: до моменту, коли цей прапорець міг би спрацювати, ваш виняток уже став
результатом з is_error=True. Перевіряйте результат через assert. Цей підхід описано на сторінці Тестування.
Підсумки
- Викиньте будь-який виняток в інструменті -> виклик повертає
is_error=Trueз вашим повідомленням уcontent. Модель читає його й може повторити спробу. Це поведінка за замовчуванням. - Викиньте
MCPError-> сам виклик завершується помилкою JSON-RPC. Модель нічого не бачить; розбирається хост.code,messageіdataдоходять без змін. - Вирішальне запитання: чи могла б розумніша модель цього уникнути? Так -> виняток. Ні ->
MCPError. ResourceNotFoundErrorз обробника ресурсу -> протокольний-32602з URI вdata.- Некоректні аргументи відхиляються за схемою ще до запуску вашої функції; для них
raiseне потрібен. from mcp import MCPError; константи кодів помилок — зmcp.types.
З помилками розібралися. Це все, що сервер надає назовні. Про те, що кожен обробник може читати і що робити у відповідь клієнтові під час роботи, — наступний розділ: Усередині обробника.
Точний текст помилок SDK, з якими ви найімовірніше зіткнетеся, що кожна з них означає і як виправити кожну одним рухом, — на сторінці Усунення несправностей.