← На главную

Опубликовано

MCP и память агента: экосистема вокруг модели

Автор: Гусев Николай [портфолио]

Темы: agents, mcp, kniga

Седьмая часть цикла по книге AI Agents and Applications Роберто Инфанте (Manning, 2026). Глава 13: MCP-серверы и память агента на чекпоинтах. Предыдущие части: фундамент и промпты, суммаризация с живым замером, LangGraph, RAG в глубину, продвинутый RAG, агенты и мультиагентность.

Зачем вообще MCP

К главе об агентах у нас агент с тремя инструментами. Каждый инструмент - функция рядом с агентом, в том же процессе, в той же виртуальной среде. Это работает, пока инструменты твои и их мало.

Теперь реальная задача: агенту нужны погода, календарь, почта, тикет-трекер, вики, поиск по базе знаний. Каждая интеграция - свой код: аутентификация, лимиты, обработка ошибок, формат ответа, обновление при смене API провайдера. И главное: этот код пишут все, кому нужен тот же сервис. Десять команд, которым нужна погода, пишут десять одинаковых обёрток над одним API - и десять раз чинят их, когда провайдер меняет формат ответа.

Model Context Protocol (MCP) - открытый протокол, который стандартизирует подключение инструментов и источников данных. Сервис сам публикует свои функции как MCP-сервер. Агент подключается как клиент и получает готовые инструменты. Обвязка написана один раз - тем, кто знает сервис лучше всех, - и её чинит тот же человек, который чинит сервис.

Протокол вышел в конце 2024 года и быстро стал стандартом де-факто: OpenAI и Google приняли его в API и SDK. Каталоги серверов: официальный репозиторий проекта MCP, mcp.so и smithery.ai. Число интеграций в них меняется, поэтому выбирать сервер стоит по его возможностям и поддержке, а не по размеру каталога. Тысячи готовых интеграций, которые не пишут - подключают.

Архитектура: хост, клиент, сервер

Три роли, и их стоит различать. MCP-хост - приложение агента: всё, что агент умеет и где живёт его состояние, внутри хоста. MCP-клиент - прослойка внутри хоста, держащая соединение с одним сервером; клиентов столько, сколько серверов. MCP-сервер - поставщик инструментов: публикует список функций (имя, описание, схему аргументов) и исполняет вызовы.

Ключевое свойство: для модели инструмент с MCP-сервера неотличим от локальной функции. Та же схема вызова, тот же выбор по описанию. Граф агента не меняется - меняется список инструментов, и в этом весь смысл: подключить новый сервер - это конфигурация, а не код.

"Заметки на полях". Рядом с MCP стоит коротко обозначить A2A (Agent2Agent, обмен между агентами): эти протоколы легко спутать, потому что оба связывают участников системы. Через MCP агент вызывает инструмент - например, получает погоду. Через A2A он поручает самостоятельному агенту задачу - например, подобрать маршрут с учётом погоды. Исполнитель сам выбирает шаги и может использовать MCP. В Hermes локальная делегация через профили и субагентов решает сходную задачу, но не равна обмену по стандарту A2A; для самого протокола есть отдельный плагин. Подробный механизм Hermes разберём в заключительной бонусной статье: каждому механизму дадим пример и ссылку на соответствующий урок по книге.

Источник: официальное описание A2A и его связи с MCP. Наш материал: профили, скиллы и A2A.

Транспорт - два варианта, и выбор определяет профиль эксплуатации. stdio: сервер запускается хостом как дочерний процесс на той же машине, обмен через стандартные ввод-вывод, без сетевого подключения к MCP-серверу - для локальных ресурсов и быстрого старта. Это не отменяет прав процесса и ключей к внешним сервисам. Streamable HTTP: сервер как сетевой сервис для прода и общих источников. В проде требует нормальной аутентификации - книга упоминает это одной строкой, а сервер без аутентификации в интернете это дыра.

В примере главы используется асинхронный клиент: вызов возвращает результат после ожидания ответа сервера. В Python такой вызов нужно ожидать через await. Сама сеть не требует, чтобы любой клиент был асинхронным, а задержка зависит и от транспорта, и от работы инструмента.

"Заметки на полях". MCP появился в 2024 году, но 28 июля 2026 года вышла новая спецификация. Из протокола убрали обязательное начальное рукопожатие initialize и HTTP-сессии с Mcp-Session-Id. Теперь версия и возможности клиента передаются с каждым запросом, а server/discover позволяет узнать поддерживаемые версии и возможности сервера. Практический смысл: запрос легче направить любому экземпляру сервера за балансировщиком, без привязки к одному соединению. Это не запрет памяти приложения: состояние операции при необходимости связывают с явным идентификатором, который передаётся в аргументах инструмента.

Изменения: официальный changelog MCP 2026-07-28.

Как устроен сервер изнутри

Сокращённый каркас по примеру главы на FastMCP 2, отдельной библиотеке для разработки MCP-серверов. Многоточие обозначает пропущенную реализацию запроса к погодному API; это не готовый рабочий сервер:

from fastmcp import FastMCP

mcp = FastMCP("mcp-accuweather")

@mcp.tool(description="Get weather conditions for a location.")
async def get_weather_conditions(location: str) -> dict:
    # поиск location_key, потом текущие условия
    ...

if __name__ == "__main__":
    mcp.run(transport="streamable-http", host="127.0.0.1",
            port=8020, path="/accu-mcp-server")

Вся публикация - декоратор @mcp.tool с описанием. Описание делает ту же работу, что и у локального инструмента: по нему модель решает, звать ли его. Сервер запускается одной командой и висит на порту как обычный HTTP-сервис. Официальные SDK есть для Python, JavaScript, Java, Kotlin, C# - протокол с нуля писать не нужно, повторишь то, что уже решено.

"Заметки на полях". Разберём учебный пример, не связанный с корпоративной инфраструктурой. Один агент подключает локальный файловый инструмент по stdio и погодный сервис по HTTP. Подключения разные, но приложение получает от обоих описание инструментов и вызывает их через MCP. Если сетевой сервер обновил внутреннюю работу с погодным API, при сохранении контракта инструментов клиент агента менять не нужно. Для локального сервера обновляют его пакет и перезапускают процесс. Если же изменились имя инструмента, аргументы или формат ответа, совместимость нужно проверить заново.

Проверка до интеграции: MCP Inspector

Самый полезный инструмент главы - MCP Inspector. Визуальная консоль: подключаешься к серверу, видишь список инструментов глазами потребителя, вызываешь руками, смотришь сырой ответ.

Порядок проверки книга проводит правильно: сервер - инспектор - тестовый клиент кодом - и только потом агент. Если инструмент сломан, ты видишь это в инспекторе напрямую: статус, сырой JSON, схему. Если проверять сразу агентом, поломка доедет замаскированной: агент отвечает странно, и ты отлаживаешь агента, хотя сломан сервер.

Дополнение из практики: инспектор - это ещё и проверка описания глазами потребителя. Формулировка, ясная автору сервера, в инспекторе часто читается иначе - и это последний шанс поправить её до того, как её увидят тысячи агентов.

"Заметки на полях". Перед действием с последствиями нужно проверить, что именно будет изменено, куда уйдут данные и кто разрешил операцию. Чтение тоже не автоматически безопасно: ответ может содержать персональные данные или вредоносные инструкции. MCP задаёт протокол обмена, но не заменяет контроль доступа и проверку содержимого. Обновления серверов требуют проверки схем и повторного тестирования вызовов. У июльской версии есть изменения и за пределами простого вызова инструмента. Долгие операции вынесены в расширение Tasks: клиент получает идентификатор задачи и проверяет её состояние. Если серверу нужны дополнительные сведения, он возвращает input_required - запрос уточнения, на который клиент отвечает следующим раундом. Обновились также механизмы авторизации. Поэтому старый пример из книги и новый SDK нельзя считать совместимыми по умолчанию: в инспекторе проверяем версию протокола, поддерживаемые возможности и сценарий вызова целиком. Дату появления MCP не следует путать с версией, которую поддерживает конкретный сервер.

Память: чекпоинты вместо списка сообщений

История сообщений может включать результаты инструментов, но не заменяет сохранение состояния графа и точки продолжения работы.

LangGraph решает это чекпоинтами: снимок полного состояния графа после каждого узла. Один механизм закрывает три сценария. Многоходовой диалог: "а в том же городе?" разрешается, потому что поднято состояние прошлого хода. Восстановление после сбоя: продолжение с последнего снимка без повторного исполнения дорогих шагов. Human-in-the-loop: остановка на снимке для согласования с человеком и продолжение ровно с места остановки.

Механика: checkpointer снимает состояние, thread_id связывает снимки с сессией. Пользователь может иметь несколько тредов; передал старый thread_id - граф поднял последний снимок. Вручную это воспроизводится явно: получить историю снимков, взять нужный, перемотать граф вызовом с пустым входом и конфигурацией снимка. Это же открывает ветвление: из любого снимка строится альтернативная ветка диалога.

"Заметки на полях". В Hermes похожая возможность видна пользователю как ветвление сессии: /branch, с алиасом /fork, создаёт новую ветку с копией истории и отдельным идентификатором. Например, в одной ветке можно продолжить выбранный план, а в другой попробовать альтернативу. Возврат к более раннему сообщению, если его поддерживает интерфейс, меняет точку продолжения разговора; /undo удаляет последний обмен из истории. Это аналог по назначению, а не утверждение, что Hermes использует checkpointer LangGraph. Главное ограничение: откат разговора не отменяет уже отправленное письмо или изменение внешней системы. Такие последствия требуют отдельного обратного действия.

Разбор команд: ветвление сессии и отмена обмена в Hermes. Подробности включим в заключительный бонус о Hermes.

Хранилище по стадиям зрелости: InMemorySaver - разработка, SqliteSaver - локальная персистентность, PostgresSaver - прод с конкурентным доступом.

"Заметки на полях". Память у нас разъехалась на три слоя, что совпадает с книжным делением: сессия - краткосрочная (thread_id из книги), память профиля - долгосрочная пользовательская, база знаний - долгосрочная общая. Важное отличие: долгосрочная память ищется, а не поднимается целиком. Она не жмётся в контекст, и попытка протащить её через промпт - путь к затоплению контекста.

Разборы по ссылкам: state и поиск на живом агенте, как устроена система памяти Hermes, memvid: память в одном файле.

Две разные памяти: граф и провайдер

Не следует смешивать память приложения и продолжение разговора на стороне провайдера. Checkpointer сохраняет состояние графа. Параметр use_previous_response_id позволяет поддерживающей его обёртке продолжить цепочку ответов через OpenAI Responses API. Это отдельный режим, а не обязательное условие любой памяти LangGraph. Режим продолжения по идентификатору ответа нужно согласовать с тем, как приложение передаёт историю; ошибки конкретной интеграции нельзя переносить на все способы использования Responses API.

И побочный эффект, который книга упоминает вежливо: при отправке только идентификатора предыдущего ответа сырой контекст диалога хранится у OpenAI, а не в твоём процессе. Уменьшается объём пересылаемой истории, но это не обещание экономии оплачиваемых входных токенов. Для корпоративного контура это вопрос политики данных, а не деталь настройки.

Что забрать в работу

  1. MCP - разворот ответственности: обвязка живёт у поставщика. Не пиши свою, если есть сервер; публикуй свою, если твой сервис нужен другим.
  2. В асинхронном клиенте ожидайте вызовы через await; отдельно задавайте таймауты и обработку ошибок.
  3. Сервер проверяй в инспекторе до агента: сырой ответ и схему глазами потребителя.
  4. Описание MCP-инструмента читает модель. Слабое описание - и инструмент не используется.
  5. Чекпоинты - один механизм на три сценария. thread_id - ключ. Хранилище по зрелости: память - SQLite - PostgreSQL.
  6. Различайте сохранение состояния графа и историю на стороне провайдера. Проверяйте настройки хранения данных и совместимость используемых версий.

Продолжение - глава 14: память агента и guardrails - проверки запросов, ответов и действий, которые удерживают систему в заданных границах.

Книга: AI Agents and Applications (Roberto Infante, Manning, 2026), глава 13.

#AI_Agents_and_Applications #глава_7