Уведомления о ходе выполнения и логировании в Model Context Protocol (MCP)
В мире искусственного интеллекта, где сложные задачи могут занимать значительное время, крайне важно обеспечить пользователей обратной связью. Представьте, что вы просите Claude выполнить глубокое исследование или обработать большой объем данных. Если в течение нескольких минут или даже секунд на экране ничего не происходит, у пользователя может возникнуть вопрос: "Работает ли что-то вообще, или система зависла?" Именно для решения этой проблемы в Anthropic API и, в частности, в Model Context Protocol (MCP) предусмотрены механизмы логирования и уведомлений о ходе выполнения.
Эти простые в реализации функции значительно улучшают пользовательский опыт, делая взаимодействие с инструментами Claude более прозрачным и предсказуемым. Вместо того чтобы гадать, что происходит "за кулисами", пользователи получают информацию в реальном времени, что позволяет им быть в курсе статуса длительных операций.
Зачем нужны логирование и уведомления о ходе выполнения?
Когда Claude вызывает внешний инструмент (tool), который требует времени для завершения — например, для поиска информации в интернете, выполнения сложных вычислений или обработки больших файлов — по умолчанию пользователь видит только конечный результат. В течение всего процесса выполнения инструмента интерфейс может оставаться статичным, что вызывает беспокойство и фрустрацию.
Включение логирования и уведомлений о ходе выполнения позволяет:
- Повысить прозрачность: Пользователи видят, какие шаги выполняет инструмент, и понимают, что процесс идет.
- Снизить тревожность: Отсутствие обратной связи часто приводит к мысли, что что-то сломалось. Уведомления устраняют эту неопределенность.
- Улучшить пользовательский опыт: Актуальная информация о статусе операции делает ожидание менее утомительным и более продуктивным.
- Облегчить отладку: Для разработчиков подробные логи могут быть бесценны при выявлении проблем в работе инструмента.
По сути, эти механизмы превращают "черный ящик" длительной операции в прозрачный процесс, где пользователь всегда знает, что происходит.
Реализация на стороне сервера (MCP Tool)
В Python MCP SDK логирование и уведомления о ходе выполнения реализуются через аргумент context, который автоматически предоставляется функциям вашего инструмента. Этот объект Context содержит методы, позволяющие инструменту обмениваться информацией с клиентским приложением во время своего выполнения.
Рассмотрим пример инструмента research, который выполняет исследование по заданной теме:
@mcp.tool(
name="research",
description="Research a given topic"
)
async def research(
topic: str = Field(description="Topic to research"),
*,
context: Context # Объект Context предоставляется автоматически
):
# Отправка информационного сообщения
await context.info("Начинаем исследование...")
# Отправка уведомления о ходе выполнения (20% завершено)
await context.report_progress(20, 100)
sources = await do_research(topic) # Выполнение основной части исследования
# Отправка еще одного информационного сообщения
await context.info("Составляем отчет...")
# Обновление хода выполнения (70% завершено)
await context.report_progress(70, 100)
results = await generate_report(sources) # Генерация отчета
return results
В этом примере используются два ключевых метода объекта Context:
await context.info("Ваше сообщение"): Этот метод отправляет текстовое сообщение клиенту. Его можно использовать для предоставления подробных логов, предупреждений или просто для информирования пользователя о текущем этапе.await context.report_progress(current_value, total_value): Этот метод отправляет числовое обновление о ходе выполнения. Он принимает два аргумента: текущее значение прогресса и общее значение, что позволяет клиенту рассчитать процент завершения. Вы также можете передать необязательное текстовое сообщение.
Эти вызовы можно вставлять в любой точке выполнения вашего инструмента, чтобы предоставлять актуальную информацию клиенту.
Реализация на стороне клиента
На стороне клиента необходимо настроить функции обратного вызова (callback functions) для обработки этих уведомлений. Сервер отправляет эти сообщения, но именно ваше клиентское приложение решает, как их представить пользователям.
Вот как это может выглядеть в Python SDK для клиента:
from mcp.client import ClientSession, stdio_client
from mcp.messages import LoggingMessageNotificationParams
# Функция обратного вызова для обработки лог-сообщений
async def logging_callback(params: LoggingMessageNotificationParams):
print(f"ЛОГ: {params.data}")
# Функция обратного вызова для обработки уведомлений о ходе выполнения
async def print_progress_callback(
progress: float, total: float | None, message: str | None
):
if total is not None:
percentage = (progress / total) * 100
status_message = f" ({message})" if message else ""
print(f"ПРОГРЕСС: {progress}/{total} ({percentage:.1f}%) {status_message}")
else:
print(f"ПРОГРЕСС: {progress} {message if message else ''}")
async def run_client_example():
# Предполагаем, что server_params настроены для подключения к MCP серверу
async with stdio_client(server_params) as (read, write):
async with ClientSession(
read,
write,
logging_callback=logging_callback # Регистрация коллбэка для логов на уровне сессии
) as session:
await session.initialize()
print("Вызываем инструмент 'research'...")
# Вызов инструмента с регистрацией коллбэка для прогресса
result = await session.call_tool(
name="research",
arguments={"topic": "история искусственного интеллекта"},
progress_callback=print_progress_callback, # Регистрация коллбэка для прогресса на уровне вызова инструмента
)
print(f"Инструмент 'research' завершен. Результат: {result}")
# Запуск клиентского примера (в реальном приложении это будет часть event loop)
# import asyncio
# asyncio.run(run_client_example())
Как видно из примера:
logging_callbackрегистрируется при созданииClientSession. Это означает, что все лог-сообщения, отправленные любым инструментом в рамках этой сессии, будут обрабатываться этой функцией.progress_callbackрегистрируется при каждом индивидуальном вызове инструмента черезsession.call_tool(). Это дает гибкость в обработке прогресса для разных инструментов или даже для разных вызовов одного и того же инструмента.
Внутри этих функций обратного вызова вы можете реализовать любую логику для отображения информации пользователю.
Варианты представления уведомлений
Способ представления этих уведомлений полностью зависит от типа вашего клиентского приложения:
- Приложения командной строки (CLI): Самый простой способ — это вывод сообщений и прогресса прямо в терминал, как показано в примерах выше. Можно использовать различные библиотеки для создания анимированных индикаторов прогресса или цветного вывода.
- Веб-приложения: Для динамического обновления веб-интерфейса можно использовать такие технологии, как WebSockets, Server-Sent Events (SSE) или регулярный опрос (polling) сервера. Эти технологии позволяют "проталкивать" обновления от сервера в браузер пользователя, где они могут быть отображены в виде прогресс-баров, статусных сообщений или динамически обновляемых логов.
- Настольные приложения: В десктопных приложениях вы можете обновлять стандартные элементы пользовательского интерфейса, такие как полосы прогресса (progress bars), текстовые поля статуса или специализированные окна логов.
Важно помнить, что реализация этих уведомлений является полностью необязательной. Вы можете игнорировать их, показывать только определенные типы или представлять их так, как это наиболее целесообразно для вашего приложения. Они служат исключительно для улучшения пользовательского опыта и не влияют на функциональность самого инструмента.
Заключение
Логирование и уведомления о ходе выполнения — это мощные, но простые в использовании функции Model Context Protocol (MCP), которые значительно повышают качество взаимодействия пользователей с инструментами Claude. Предоставляя прозрачную и своевременную обратную связь о длительных операциях, вы не только снижаете фрустрацию, но и создаете более интуитивно понятный и приятный пользовательский опыт. Интеграция этих механизмов в ваши MCP-инструменты — это небольшой шаг, который приносит большую пользу.