Быстрое напоминание: что такое MCP

Прежде чем про мультиагентность — короткий рефреш (детали в модуле 02). MCP (Model Context Protocol) — открытый стандарт, по которому LLM-приложение подключает внешние возможности единообразно, без кастомной интеграции под каждый источник. Две стороны:

  • MCP-сервер — поставщик: выставляет tools (функции), resources (данные), prompts. Например, сервер файловой системы, БД, поисковика.
  • MCP-клиент — потребитель: живёт внутри агента, подключается к серверам, узнаёт список их инструментов и вызывает их.

В модуле 02 картина была простая: агент = клиент, инструменты = серверы. Стрелка одна: агент → инструмент. В мультиагентных системах эта картина складывается: агент оказывается одновременно по обе стороны стрелки.

ℹ️ MCP — про «руки» агента, не про общение агентов

Держи в голове границу: MCP отвечает на вопрос «как агент подключает инструменты и данные» (агент → возможность). Общение агентов как равных — это A2A. Но, как увидим, через паттерн «агент-как-MCP-сервер» MCP частично заходит и на территорию межагентного взаимодействия. В конце разберём, где чья зона.

Две роли агента в MCP

Ключевая идея урока: в мультиагентной системе один агент играет обе MCP-роли одновременно. Смотри на агента с двух сторон:

100%
колёсико — масштаб  ·  зажать и тянуть — перемещение
Агент-исследователь СЕРВЕР ← снаружи КЛИЕНТ → внутри одна программа, две роли Оркестратор (MCP-клиент) вызывает агента как tool call tool ① как MCP-СЕРВЕР: агент = инструмент для оркестратора MCP-сервер: Web Search tools: search() MCP-сервер: Files tools: read(), write() MCP-сервер: Database tools: query() ② как MCP-КЛИЕНТ: агент вызывает инструменты

① Агент как MCP-клиент (знакомая роль из модуля 02): внутри агент подключает MCP-серверы — поиск, файлы, БД — и вызывает их инструменты, чтобы выполнять работу.

② Агент как MCP-сервер (новая роль): агент оборачивает сам себя в MCP-сервер и выставляет одну-две «крупные» tools вроде research(topic). Для того, кто его вызывает (оркестратор или другой агент-клиент), он выглядит как обычный инструмент — но за этим инструментом стоит целый агент с собственным reasoning-циклом.

✅ «Агент-как-инструмент» — фрактальная композиция

Это и есть главная сила паттерна: с точки зрения вызывающего нет разницы между «простым инструментом» и «инструментом, внутри которого агент». Оркестратор просто видит tool в списке и вызывает его. Значит, из агентов можно собирать агентов — фрактально, слоями, переиспользуя единый механизм MCP-инструментов вместо кастомной интеграции.

Роль 1: агент как MCP-клиент

Это база из модуля 02, освежим в мультиагентном контексте. Каждый специализированный агент подключает свой набор MCP-серверов — те инструменты, что нужны именно его роли. Исследователю — поиск, аналитику — БД и калькулятор, писателю — доступ к файлам.

Агент подключает MCP-серверы как клиент (концептуально)
python
# Агент-исследователь = MCP-КЛИЕНТ: подключает инструменты под свою роль
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def research_agent(topic: str) -> str:
    # подключаемся к MCP-серверу веб-поиска
    params = StdioServerParameters(command="mcp-server-websearch")
    async with stdio_client(params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await session.list_tools()          # что умеет сервер
            result = await session.call_tool(            # вызываем инструмент
                "search", {"query": topic}
            )
    # ... агент прогоняет результат через LLM, суммаризирует ...
    return summarize(result)

Каждый агент изолированно решает, какие серверы ему нужны. Это даёт чистое разделение возможностей: у писателя нет доступа к продовой БД, потому что он к её MCP-серверу просто не подключён. Инструменты выдаются по ролям — привет принципу наименьших привилегий.

Роль 2: агент как MCP-сервер

А теперь новое. Возьмём того же исследователя и выставим его наружу как MCP-сервер с одним крупным инструментом research. Теперь любой MCP-совместимый оркестратор увидит его в списке tools и сможет вызвать — не зная, что внутри целый агент.

Оборачиваем агента в MCP-сервер (концептуально, FastMCP-стиль)
python
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("research-agent")

@mcp.tool()
async def research(topic: str) -> str:
    """Найти информацию по теме и вернуть структурированную выжимку.

    За этим 'инструментом' стоит ЦЕЛЫЙ агент: он сам ходит в веб-поиск,
    гоняет результаты через LLM, при нужде вызывает другие инструменты.
    Снаружи — обычный tool. Внутри — reasoning-цикл.
    """
    return await run_research_agent(topic)   # тут живёт агентная логика

if __name__ == "__main__":
    mcp.run()   # теперь агент доступен как MCP-сервер

Оркестратор при этом остаётся простым MCP-клиентом. Ему всё равно, что research — не однострочная функция, а автономный агент:

Оркестратор вызывает агента-как-инструмент
python
# Оркестратор = MCP-клиент. Для него research-agent — просто ещё один tool.
tools = await session.list_tools()
# → [research, write_report, analyze_numbers, ...]  (агенты вперемешку с обычными tools)

# LLM оркестратора сама решает вызвать research — как любой инструмент
result = await session.call_tool("research", {"topic": "рынок EV 2025"})
# внутри развернулся целый агент, но оркестратор видит только результат
🎯 Что это даёт на практике

Переиспользование: написал агента-исследователя один раз — подключаешь в любой оркестратор как tool. Инкапсуляция: сложность агента спрятана за простым интерфейсом инструмента. Единый механизм: оркестратор одинаково работает и с примитивными tools, и с агентами — не нужен отдельный «протокол делегирования». Слои: агент-как-сервер сам может быть клиентом других агентов-серверов — иерархия любой глубины.

MCP-как-делегирование vs A2A

Возникает законный вопрос: если через «агент-как-MCP-сервер» один агент уже вызывает другого — зачем тогда A2A? Оба ведь дают межагентное взаимодействие. Разница — в модели отношений.

MCP «агент-как-инструмент»A2A
Модель отношенийИерархия: вызывающий → подчинённый инструментРавные: агент ↔ агент
Кто главныйОркестратор рулит, агент-tool исполняетАвтономные пиры, каждый со своей волей
ВзаимодействиеВызов функции: запрос → результатЗадачи с жизненным циклом, диалог, уточнения
Обнаружениеlist_tools у известного сервераAgent Card, реестры
Когда уместноЧёткая иерархия, агент как «умная функция»Автономные сервисы разных вендоров, диалог

Грубо: MCP — «вызвать возможность» (в т.ч. если возможность = агент), отношения вертикальные. A2A — «поговорить с равным», отношения горизонтальные. Часто они сочетаются: агент — A2A-сервис снаружи для пиров и одновременно MCP-клиент внутри для своих инструментов.

✅ Мнемоника

MCP вниз, A2A вбок. Подключаешь возможность/подчинённого — вниз по иерархии — это MCP. Общаешься с равным автономным агентом — вбок — это A2A. Один агент может делать и то, и другое сразу.

Подводные камни

Композиция агентов через MCP соблазнительна, но у неё есть цена:

  • Скрытая стоимость и латентность. За «простым tool» research стоит целый LLM-агент: секунды работы, токены, деньги. Оркестратор этого не видит — легко недооценить бюджет.
  • Вложенные циклы reasoning. Агент внутри агента внутри агента — отладка усложняется, ошибки маскируются за интерфейсом инструмента. Нужна сквозная трассировка (модуль 03: LangSmith).
  • Потеря контекста. Инструментный вызов research(topic) отдаёт только результат — оркестратор не видит рассуждений агента внутри. Для диалога/уточнений это тесно (тут-то и нужен A2A).
  • Таймауты. Обычные tools быстрые, агенты — долгие. Клиент должен быть готов ждать (или стримить).
⚠️ Не оборачивай в MCP то, что должно быть диалогом

Паттерн «агент-как-инструмент» идеален, когда взаимодействие — «дай задачу, получи результат». Как только нужен диалог (агент уточняет, спорит, возвращается за данными по ходу) — интерфейс «вызов функции» становится тесным. Это сигнал перейти на A2A с его задачами и жизненным циклом. MCP — для делегирования, A2A — для разговора.

Шпаргалка

MCP в мультиагентах — всё в одном месте
text
MCP: сервер = ПОСТАВЩИК (tools/resources/prompts) · клиент = ПОТРЕБИТЕЛЬ (в агенте)

В МУЛЬТИАГЕНТАХ агент играет ОБЕ роли сразу:
  ① как MCP-КЛИЕНТ  → подключает инструменты под свою роль (поиск, БД, файлы)
  ② как MCP-СЕРВЕР  → оборачивает СЕБЯ в tool (research(topic)) для оркестратора

«АГЕНТ-КАК-ИНСТРУМЕНТ»:
  для вызывающего нет разницы «tool» vs «агент за tool»
  → фрактальная композиция: из агентов собираем агентов, слоями
  плюсы: переиспользование · инкапсуляция · единый механизм · иерархия

MCP vs A2A:
  MCP ВНИЗ  — вызвать возможность/подчинённого (иерархия, запрос→результат)
  A2A  ВБОК — поговорить с равным (пиры, задачи с lifecycle, диалог)
  часто вместе: A2A-сервис снаружи + MCP-клиент внутри

ГРАБЛИ:
  • скрытая цена/латентность за «простым» tool (внутри целый LLM-агент)
  • вложенные reasoning-циклы → нужна сквозная трассировка
  • инструментный вызов теряет контекст рассуждений (нет диалога → бери A2A)
  • таймауты: агенты долгие, готовь клиента ждать/стримить

ПРАВИЛО: «дай задачу → получи результат» = MCP · нужен диалог = A2A

Практическое задание

Задание: спроектируй композицию через MCP

  1. Возьми агента-аналитика данных. Опиши его как MCP-клиента: к каким MCP-серверам он подключается (БД, калькулятор, …) и почему именно к ним.
  2. Теперь оберни его как MCP-сервер: какой один крупный tool он выставит наружу? Напиши сигнатуру и docstring.
  3. Собери трёхслойную композицию: оркестратор → аналитик-как-tool → его внутренние инструменты. Нарисуй стрелки и подпиши, кто клиент, кто сервер на каждом стыке.
  4. Для двух сценариев выбери MCP или A2A и обоснуй: (а) «оркестратор делегирует: посчитай метрики и верни число»; (б) «два автономных агента разных команд согласуют бюджет, уточняя цифры друг у друга».
  5. Найди в своей композиции риск скрытой стоимости: где «простой вызов» на деле запускает дорогой LLM-цикл? Как это сделать видимым (трассировка/лимиты)?
  6. Со звёздочкой: подними FastMCP-сервер с одним tool, внутри которого мини-агент (пусть даже заглушка с LLM-вызовом), и вызови его из MCP-клиента. Замерь латентность.

Что дальше

И в A2A (skills в Agent Card), и в MCP (tools) агент декларирует, что он умеет, отдельными единицами возможностей. Следующий урок — про Skills: как правильно нарезать и описывать возможности агента, чтобы их находили и переиспользовали.