MCP + LangGraph: гайд по интеграции агентов | 2026 | AiManual
AiManual Logo Ai / Manual.
15 Июн 2026 Гайд

Как навести порядок в агентной архитектуре с MCP: полный гайд по интеграции с LangGraph

Полный гайд по интеграции MCP протокола с LangGraph. Настройка MCP сервера, выбор stdio или HTTP, Human-in-the-loop для масштабирования агентов.

Реклама
cliv1

Агентный бедлам: почему без MCP вы тонете в инструментальном хаосе

Давайте честно: кто из вас не видел этого? Вы пишете третьего по счёту агента для внутренних нужд. У каждого свой способ дёргать API, своя обёртка для вызова функций, свой встроенный curl. Один агент стучится в Slack через готовый SDK, второй — напрямую к PostgreSQL через psycopg2, третий колотит в Redis по сырому TCP. А когда эти агенты начинают общаться друг с другом, начинается ад.

В итоге — дублирование кода, раздутый контекст, и каждое изменение внешнего сервиса требует правки десятка мест. Это не архитектура, это свалка инструментов. И вот тут появляется MCP (Model Context Protocol). Не панацея, но очень жирная заплатка.

MCP как санитар кода: что это и как работает

MCP — это протокол, который стандартизирует то, как LLM-агенты общаются с инструментами. Вместо того чтобы каждый раз писать свой велосипед, вы определяете сервер, который предоставляет список инструментов и их схемы вызова. Агент просто говорит: «эй, мне нужно отправить сообщение в Slack», а MCP сервер делает всю грязную работу.

Ключевые понятия:

  • Transport: как агент и сервер общаются — через stdio (подпроцесс) или HTTP (сетевой вызов).
  • Tools: список доступных функций с JSON-схемами входных параметров.
  • Resources: статические данные, которые сервер может отдавать агенту (например, документация).
  • Prompts: готовые шаблоны запросов, которые помогают LLM правильно использовать инструменты.

На декабрь 2025 MCP уже вошёл в продакшн у десятков компаний. Arcade.dev и LangSmith Fleet предлагают единый gateway к 7500+ инструментам — это серьёзно упрощает жизнь.

LangGraph: дирижёр оркестра, а не просто граф

LangGraph — это фреймворк для построения stateful графов состояний. Вы описываете узлы (nodes) — действия агента, и рёбра (edges) — переходы между ними. Но в отличие от простого pipeline, LangGraph позволяет реализовать циклы, параллельные ветки и, что для нас критично, Human-in-the-loop.

Если вы ещё не развернули LangGraph Server — загляните в построение графовой инфраструктуры LLM с LangGraph Server и LangSmith. Там подробно описано, как поднять сервер для локальных моделей.

А если хотите упаковать агента в Docker — LangGraph Deploy CLI развернёт продакшн одной командой.

Стыковка: как подружить MCP и LangGraph

Теперь к сути. Допустим, у нас есть MCP сервер, который предоставляет инструменты для работы с Jira и Slack. Мы хотим, чтобы LangGraph агент сам решал, какой инструмент вызвать. Для этого нам нужно:

  1. Поднять MCP сервер (stdio или HTTP).
  2. В LangGraph узле инициализировать клиент MCP.
  3. Получить список инструментов, передать их LLM.
  4. При вызове инструмента — выполнить запрос к MCP серверу.
  5. Результат вернуть в граф.

1 Пишем MCP сервер (stdio)

Самый простой способ — стартовать с stdio. Сервер запускается как подпроцесс, общается через stdin/stdout. Это удобно для локальной разработки.

# mcp_server.py
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
import mcp.server.stdio
from mcp.types import Tool, TextContent

async def serve() -> None:
    server = Server("demo-tools")

    @server.list_tools()
    async def list_tools() -> list[Tool]:
        return [
            Tool(
                name="say_hello",
                description="Поздороваться с пользователем",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"}
                    },
                    "required": ["name"]
                }
            )
        ]

    @server.call_tool()
    async def call_tool(name: str, arguments: dict) -> list[TextContent]:
        if name == "say_hello":
            return [TextContent(type="text", text=f"Привет, {arguments['name']}!")]
        raise ValueError(f"Unknown tool: {name}")

    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            InitializationOptions(
                server_name="demo-tools",
                server_version="0.1.0"
            )
        )

if __name__ == "__main__":
    import asyncio
    asyncio.run(serve())

2 А как же HTTP?

Stdio — круто, пока у вас один агент на одной машине. Как только появляется распределённая система или несколько реплик, вам нужен HTTP. MCP для HTTP использует SSE (Server-Sent Events). Сервер слушает порт, агент подключается.

Когда выбирать stdio: разработка, однопоточные агенты, изоляция. Когда HTTP: продакшн, микросервисы, единый gateway для множества агентов.

Пример HTTP сервера с использованием mcp.server.fastmcp:

# http_server.py
from mcp.server.fastmcp import FastMCP
import uvicorn

mcp = FastMCP("demo-http")

@mcp.tool()
def say_hello(name: str) -> str:
    return f"Здравствуй, {name}!"

if __name__ == "__main__":
    mcp.run(transport="http", port=8000)

Запускаем: python http_server.py. Теперь любой агент может стучаться через HTTP.

3 Интеграция с LangGraph

Создадим граф, который использует MCP-инструменты. Для этого нам нужен клиент MCP внутри узла.

# langgraph_mcp_agent.py
import asyncio
from langgraph.graph import StateGraph, END
from typing import TypedDict, Any
from mcp.client.stdio import stdio_client
from mcp.client import ClientSession

class AgentState(TypedDict):
    messages: list
    next_node: str

def create_agent() -> StateGraph:
    workflow = StateGraph(AgentState)

    async def call_mcp(state: AgentState) -> dict:
        # Подключаемся к MCP серверу через stdio
        server_params = {
            "command": "python",
            "args": ["mcp_server.py"],
            "env": {}
        }
        async with stdio_client(server_params) as (read, write):
            async with ClientSession(read, write) as session:
                await session.initialize()
                tools = await session.list_tools()
                # Прокидываем инструменты LLM — тут вызов нужной модели
                # ... пропускаем выбор инструмента, считается что LLM вернула tool_call
                result = await session.call_tool("say_hello", {"name": "DevOps"})
                state["messages"].append({"role": "tool", "content": result.content[0].text})
        return state

    workflow.add_node("mcp_node", call_mcp)
    workflow.set_entry_point("mcp_node")
    workflow.add_edge("mcp_node", END)
    return workflow.compile()

if __name__ == "__main__":
    graph = create_agent()
    initial = {"messages": [], "next_node": ""}
    result = asyncio.run(graph.ainvoke(initial))
    print(result["messages"])

Это упрощённый пример. В реальности вам нужно будет передавать LLM список инструментов, обрабатывать её выбор и выполнять вызов. Но принцип именно такой: MCP даёт единый интерфейс, а LangGraph — оркестрацию.

Human-in-the-loop: когда агент просит разрешения

Самая страшная вещь в агентах — автономные действия с непредсказуемыми последствиями. MCP + LangGraph позволяют легко вставить точку принятия решения человеком. В LangGraph это называется interrupt.

Представьте: агент хочет отправить сообщение в Slack. Мы помещаем узел, который перед вызовом MCP инструмента прерывает выполнение и ждёт подтверждения от человека. После подтверждения — продолжает.

from langgraph.checkpoint import MemorySaver

workflow = StateGraph(AgentState)
# ... добавляем узлы

# Перед вызовом инструмента ставим interrupt
@workflow.node("ask_human")
def ask_human(state: AgentState) -> dict:
    print("Агент хочет выполнить действие. Подтвердите (y/n):")
    answer = input()  # в продакшене — через вебхук или Telegram
    if answer.lower() != "y":
        state["messages"].append({"role": "system", "content": "Действие отменено пользователем"})
        return {"next_node": "end"}
    return {"next_node": "mcp_call"}

workflow.add_conditional_edges("ask_human", lambda s: s["next_node"])

memory = MemorySaver()
graph = workflow.compile(checkpointer=memory)

Важно: Не используйте input() в продакшене. Реальный Human-in-the-loop требует асинхронного ожидания через каналы связи. Хорошая практика — ставить задачу в очередь и ждать ответа из внешнего event-брокера.

Как НЕ надо: типичные грабли

  1. Не кладите всё в один MCP сервер. Разделяйте инструменты по доменам: отдельный сервер для базы данных, отдельный для Slack. Иначе конфигурация превращается в монстра.
  2. Не забывайте про таймауты. LLM может долго думать, а MCP сервер — ждать. Ставьте hard timeout на вызов инструмента, иначе граф зависнет.
  3. Не игнорируйте ошибки MCP. Если сервер упал, агент должен либо повторить, либо уведомить человека. В LangGraph для этого есть add_node с fallback.
  4. Не используйте stdio в Kubernetes. Контейнер с MCP сервером должен жить в том же pod'е, иначе stdio не пробросить. В K8s лучше HTTP.

Пример из реального кейса: мы строили агента для код-ревью на LangGraph. Изначально всё работало, но после масштабирования до 50+ инструментов начался хаос. Полный разбор ошибок читайте в отдельной статье — там много болевых точек, которые стоит знать заранее.

Бонус: самоподдерживающаяся база знаний через MCP

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

Вместо заключения: прогноз

К концу 2026 года MCP станет настолько же стандартным, как REST в микросервисах. LangGraph уже сейчас — лучший способ строить production-агенты. Их комбинация даёт то, чего так не хватало индустрии: порядок. Если ваш проект ещё не на MCP — вы отстаёте, но исправить легко. Начните с одного сервера, подцепите к одному графу, и вы увидите, как хаос уходит.

И помните: лучший способ предсказать будущее — сделать его стандартизированным. MCP — ваш инструмент для этого.

Подписаться на канал