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

Логування

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

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

Пишіть логи з інструмента так само, як із будь-якої іншої функції Python: стандартною бібліотекою.

У MCP є можливість логування на рівні протоколу: сервер міг надсилати свої записи логу клієнту як сповіщення через методи об'єкта Context. Редакція специфікації 2026-07-28 оголошує цю можливість застарілою і нічим її не замінює, тому ця документація її не описує. Повний перелік застарілого і того, що робити натомість, — на сторінці Застарілі можливості.

Натомість робіть те саме, що й у будь-якій іншій програмі на Python: користуйтеся стандартною бібліотекою.

Інструмент, що пише логи

server.py
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") задає рівень, а налаштування логування, зроблене раніше, лишається недоторканим.

Про те, як повідомити під'єднаним клієнтам, що на сервері щось змінилося (список інструментів, ресурс), — на сторінці Підписки.