Логування
Машинний переклад
Цю сторінку перекладено автоматично з англомовної документації, і основною версією є англомовна сторінка. Якщо щось читається неправильно, на сторінці Переклади пояснено, як про це повідомити.
Пишіть логи з інструмента так само, як із будь-якої іншої функції Python: стандартною бібліотекою.
У MCP є можливість логування на рівні протоколу: сервер міг надсилати свої записи логу клієнту як сповіщення через методи об'єкта Context. Редакція специфікації 2026-07-28 оголошує цю можливість застарілою і нічим її не замінює, тому ця документація її не описує. Повний перелік застарілого і того, що робити натомість, — на сторінці Застарілі можливості.
Натомість робіть те саме, що й у будь-якій іншій програмі на Python: користуйтеся стандартною бібліотекою.
Інструмент, що пише логи
import logging
from mcp.server import MCPServer
logger = logging.getLogger(__name__)
mcp = MCPServer("Bookshop")
@mcp.tool()
def search_books(query: str) -> str:
"""Search the catalog by title or author."""
logger.info("Searching for %r", query)
return f"Found 3 books matching {query!r}."
logging.getLogger(__name__)повертає логер, названий за вашим модулем. Створіть його один раз, угорі файлу.- Усередині інструмента викликайте
logger.info(...), як у будь-якій іншій функції. Нічого не треба впроваджувати, нічого не треба чекати черезawait, нічого специфічного для MCP.
Check
Викличте інструмент і подивіться на весь результат:
result.content # [TextContent(text="Found 3 books matching 'dune'.")]
result.structured_content # {'result': "Found 3 books matching 'dune'."}
Рядка логу в ньому ніде немає. Логи — для вас, людини, яка керує сервером. Модель
їх ніколи не бачить. Якщо модель має щось прочитати, поверніть це через return.
Куди це потрапляє
Для stdio-сервера це питання важливіше, ніж зазвичай. Хост запустив ваш сервер як підпроцес і читає MCP-повідомлення з його stdout. Стандартний потік помилок — ваш.
Стандартна бібліотека вже робить усе правильно: за замовчуванням вивід логів іде в sys.stderr. Рядки logger.info(...) потрапляють у термінал (або туди, куди хост збирає stderr підпроцесу), а потік протоколу лишається чистим.
Tip
Не використовуйте print() у stdio-сервері. print пише в stdout, а stdout належить протоколу.
Під час обслуговування SDK перенаправляє в stderr той stdout, який справді скинуто з буфера, тож
пошкодити потік протоколу він не може, але print() у процесі з блоковою буферизацією зазвичай лежить
нескинутим у буфері sys.stdout, доки інтерпретатор не спорожнить його під час виходу — просто
в потік протоколу. Навіть коли його перенаправлено, рядок потрапляє у вивід логів сирим: без рівня,
без імені логера і без можливості його відфільтрувати.
logger.debug("got here") — той самий один рядок зусиль, але він іде куди треба.
Рівень
Викликати logging.basicConfig() самостійно не потрібно. Конструктор MCPServer уже це зробив: з обробником, спрямованим у стандартний потік помилок, на рівні, який передано як log_level=, тож MCPServer("Bookshop", log_level="DEBUG") — це все, що потрібно, щоб побачити рядки logger.debug(...).
Типове значення — "INFO".
logging.basicConfig() ніколи не замінює обробники, що вже існують. Якщо налаштувати логування самостійно до створення сервера, ваше налаштування має перевагу.
Спробуйте самі
Запустіть сервер з MCP Inspector:
uv run mcp dev server.py
Викличте search_books на вкладці Tools. Inspector покаже результат: лише повернене значення. Рядок
Searching for 'dune'
пішов у стандартний потік помилок: у термінал, а не в потік протоколу.
Info
Якщо насправді потрібне трасування (кожен запит, скільки він тривав, чи завершився помилкою), потрібні не рядки логу, а спани. Ваш сервер уже їх генерує: SDK за замовчуванням трасує кожне повідомлення за допомогою OpenTelemetry. Див. OpenTelemetry.
Підсумки
- Можливість логування протоколу MCP оголошена застарілою специфікацією 2026-07-28 і нічим не замінена. Не будуйте на ній.
logger = logging.getLogger(__name__)на рівні модуля,logger.info(...)в інструменті. Оце й увесь шаблон.- Вивід логів ніколи не доходить до моделі. Доходить лише значення, яке ви повертаєте через
return. - Стандартний потік помилок — ваш; stdout належить протоколу. Під час обслуговування SDK перенаправляє скинутий з буфера сторонній stdout у stderr, але нескинутий
print()усе ще може вилитися в потік протоколу під час виходу, а перенаправлені рядки приходять без позначок; використовуйтеlogging, чий обробник скидає кожен запис. MCPServer(..., log_level="DEBUG")задає рівень, а налаштування логування, зроблене раніше, лишається недоторканим.
Про те, як повідомити під'єднаним клієнтам, що на сервері щось змінилося (список інструментів, ресурс), — на сторінці Підписки.