Головна / Статті

MCP для агентів LangGraph: поетапно — сервери, механізми передачі даних та місток-адаптер

MCP для агентів LangGraph, рівень за рівнем: ролі хоста, клієнта та сервера, сервер FastMCP, транспорти stdio та HTTP, langchain-mcp-adapters та поширені проблеми.

Видавець: REACTAPP.TOP17 хв читання3867 слів

Джерела: MCP for LangGraph Developers: From Basics to Production

Попередні вимоги є простими: необхідна осведомленість про структуру проекту LangGraph та про ідею функції, прикрашеної атрибутом @tool. Model Context Protocol є новою частиною інфраструктури, а не новим підходом до роботи з графами, тому пояснення починається з нуля з самого MCP, а до LangGraph повертається лише тоді, коли цей концепт стає зрозумілим.

Проблема масштабування зі звичайними інструментами

Інструмент у LangGraph зазвичай починається ось так:

@tool
def search_web(query: str) -> str:
    """Search the web for current information."""
    return f"Search results for: {query}"

Це нормально, поки не з’являється потреба у масштабуванні. Уявімо, що п’ять агентів у п’яти проєктах потребують інструменту „пошук у корпоративній базі даних“. За вищенаведеною схемою один і той самий інструмент доводиться писати п’ять разів, у п’яти кодових базах, можливо, навіть у п’яти мовах. Зміна схеми означає п’ять правок. Спільне використання цього інструменту з колегою, який створює інший тип додатку на основі ШІ, можливо, навіть не на LangGraph, повністю зазнає невдачі, оскільки функція @tool належить до світу Python у LangChain.

Ця проблема називається проблемою інтеграції N×M. N інструментів (бази даних, API, файлові системи) мають підключатися до M додатків ШІ (агент LangGraph, власний агент колеги, Claude Desktop, асистент IDE). Без спільного стандарту виникають індивідуальні інтеграції типу N×M.

Model Context Protocol (MCP) — це відкритий, універсальний стандарт для під’єднання штучних інтелектуальних додатків до інструментів та даних. Інструмент, створений як сервер MCP, може використовуватися будь-яким додатком, сумісним із MCP, чи то агентом LangGraph, Claude Desktop, Cursor чи власним агентом, без необхідності написання спеціального коду для інтеграції. Зазвичай це порівнюють із роз’ємом USB-C: один стандарт з’єднувача, будь-який сумісний пристрій з кожного боку.

Шлях від питання «що таке MCP» до сервера промислового рівня, підключеного до справжнього агента LangGraph, проходить через п’ять рівнів, кожен з яких додає нову ідею.

Рівень 1: що таке MCP

Почніть з зображення перед будь-яким кодом. Консьєрж готелю особисто не знає, як забронювати столик у ресторані, викликати таксі чи купити квитки в театр. Консьєрж тримає список надійних місцевих послуг, кожна з яких є спеціалістом у своїй галузі. Коли гість хоче забронювати вечерю, консьєрж підключається до спеціальної лінії до сервісу бронювання, формулює запит у форматі, зрозумілому обом сторонам, та передає відповідь назад.

MCP — це стандартна лінія та стандартний формат запиту. Програма на основі ШІ виступає в ролі консьєржа. Сервер MCP — це спеціалізований сервіс, такий як система бронювання ресторанів, компанія з таксі чи каса з продажу квитків. Сам MCP є спільною мовою та схемою з’єднання, тож будь-який консьєрж може спілкуватися з будь-яким сервісом, не потребуючи знань про те, як кожен з них працює.

Три ролі

Кожна система MCP має рівно трьох учасників, і все інше будується на їхній основі.

  • Хост. Це AI-додаток, який фактично використовує кінцевий користувач: тут це агент LangGraph, а в інших випадках — Claude Desktop, Cursor чи VS Code з copilotом. Він керує розмовою, вирішує, коли потрібен інструмент, та відображає результати.
  • Клієнт. Він знаходиться всередині хоста, причому кожен клієнт підтримує окреме один-до-одного з’єднання саме з одним сервером. Хост, підключений до трьох серверів, внутрішньо має три клієнти. Таке один-до-одного співвідношення є свідомим захисним механізмом, щоб клієнт сервера файлової системи випадково не витікнув дані на сервер бази даних.
  • Сервер. Це невелика, спеціалізована програма, яка надає певні можливості. Вона може обгортати базу даних, файлову систему, API для пошуку в Інтернеті чи внутрішню систему управління клієнтами. Варто зазначити, що він не знає та не цікавиться тим, який хост до нього звертається, тому той самий сервер може обслуговувати агента LangGraph сьогодні та інше застосунок завтра без жодних змін.
  • Формат передачі даних: JSON-RPC 2.0

    Повідомлення між клієнтом та сервером використовують формат JSON-RPC 2.0 — простий та добре усталений формат із трьома типами повідомлень.

    Запит — це прохання виконати певну дію, який містить унікальний id, щоб можна було ідентифікувати відповідь:

    {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "search_db", "arguments": {"query": "Q3 revenue"}}}
    

    Відповідь — це реакція на запит. Вона містить або результат у разі успіху, або помилку у разі невдачі, з тим самим id, що й у запиті:

    {"jsonrpc": "2.0", "id": 1, "result": {"content": [{"type": "text", "text": "Q3 revenue was $4.2M"}]}}
    

    Повідомлення — це однонаправлений повідомлення, яке не очікує відповіді, наприклад для інформування про зміни у списку доступних інструментів.

    У форматі JSON-RPC майже ніколи не пишуть вручну, оскільки цим займаються SDK. Проте розуміння його основ допомагає зрозуміти багато аспектів подальшої роботи, так само як знання HTTP робить людину кращим розробником REST, навіть якщо вона ніколи не пише коду у чистому форматі HTTP.

    Рівень 2: три примітиви

    Сервер пропонує свої можливості через саме три види примітивів, і майже кожне рішення щодо їхнього використання під час створення сервера є вибором між ними.

    Інструменти — це дії, які може виконувати модель. Інструмент — це функція, яку LLM може вирішити викликати під час міркувань, подібно до оформленої функції у звичайному LangGraph. Різниця полягає у місці її розташування: вона знаходиться всередині сервера MCP, а не у кодовій базі LangGraph, і її знаходять та викликають через протокол. Використовуйте інструмент кожного разу, коли потрібно щось зробити: виконати обчислення, здійснити запит до бази даних, надіслати електронний лист чи внести зміни до файлу.

    Ресурси надають лише контекст для читання. Додаток може отримати ресурс, щоб надати моделі додаткові матеріали, без необхідності для моделі самостійно вирішувати викликати його, як це робиться з інструментом. Ресурси адресуються за допомогою URI, так само, як веб-сторінки — за допомогою URL. Використовуйте їх для матеріалів, які можна лише читати, таких як файли конфігурації, документи чи списки джерел даних, про які модель може хотіти дізнатися перед тим, як вирішити, що шукати.

    Інструкції — це повторно використовувані шаблони. Інструкція — це заздалегідь написана структура, яка запускає певну робочу процедуру для користувача або хоста. На відміну від інструментів, інструкції зазвичай викликаються користувачем, а не моделлю, тому вони нагадують команди з слешем. Вони підходять для поширених, повторюваних завдань, таких як «підсумувати цей документ» або «перевірити цей код на наявність проблем з безпекою», де послідовні, добре спроєктовані інструкції кращі, ніж залишати формулювання на розсуд користувача.

    Якщо ви не впевнені, що використати, запитайте, чи щось змінюється, чи лише надається інформація. Якщо це створює, оновлює, видаляє, надсилає або виконує, це інструмент. Якщо це лише дані для читання, які модель може потребувати у фоновому режимі, це ресурс. Якщо це шаблон інструкції, який користувач явно запускає, це інструкція.

    Рівень 3: перший сервер з FastMCP

    FastMCP — це провідна Python-фреймворк для створення серверів MCP. Він перетворює складну інфраструктуру протоколу (обробку запитів, генерацію схем, життєвий цикл) на кілька декораторів, у тому ж дусі, що й @tool для функцій LangChain. Встановлення:

    pip install fastmcp
    

    Повний сервер із одним інструментом поміщається у невеликому файлі:

    # ── math_server.py ───────────────────────────────────────────
    from fastmcp import FastMCP
    
    # Create the server - this object is the container for everything below
    mcp = FastMCP(name="Math Server")
    @mcp.tool
    def add(a: int, b: int) -> int:
        """Add two numbers together."""
        return a + b
    @mcp.tool
    def multiply(a: int, b: int) -> int:
        """Multiply two numbers together."""
        return a * b
    if __name__ == "__main__":
        mcp.run()  # Defaults to stdio transport
    

    Це дійсний, працездатний сервер MCP. FastMCP читає підказки типів функції для створення схеми вхідних даних та читає документацію, щоб сформувати опис, який бачить LLM. Діє те саме правило, що й для звичайних інструментів, лише з більшими наслідками: нечітка документація змушує модель сумніватися, коли викликати інструмент, і ця нечіткість впливає на кожен додаток, який підключається, а не лише на одного агента.

    Для додавання ресурсу потрібен декоратор із бажаним URI:

    # ── Adding to math_server.py ─────────────────────────────────
    
    @mcp.resource("config://server-info")
    def server_info() -> dict:
        """Provides metadata about this server's capabilities."""
        return {"version": "1.0", "operations": ["add", "multiply"]}
    

    Коли клієнт запитує config://server-info, FastMCP викликає відповідну функцію та повертає результат. Вона виконується лише за запитом, що є лінивою оцінкою, тому не обчислюється нічого, чого модель ніколи не використовує.

    Іноді ресурс має залежати від певного аргумента, наприклад, від конкретної записі, а не від фіксованого блоку конфігурації:

    @mcp.resource("history://{operation_id}")
    def get_calculation(operation_id: str) -> dict:
        """Retrieve a past calculation by its ID."""
        # In a real server, this would look up a database record
        return {"id": operation_id, "result": "..."}
    

    Замінник {operation_id} у URI робить це шаблоном ресурсу. Запит на history://abc123 змушує FastMCP витягнути abc123 та автоматично передати його функції.

    Інструкція для виконання також визначається аналогічним чином:

    @mcp.prompt
    def explain_calculation(operation: str, result: str) -> str:
        """Generate a request to explain a calculation in plain English."""
        return f"Explain how the operation '{operation}' produced the result '{result}', in simple terms a beginner could follow."
    

    Щоб запустити сервер:

    python math_server.py
    

    Перш ніж під’єднувати справжнє AI-застосунок, перевірте його за допомогою MCP Inspector — інструменту для відлову помилок у браузері, який постачається разом із екосистемою. Він перелічує інструменти, викликає їх вручну та перевіряє ресурси без участі LLM:

    fastmcp dev math_server.py
    

    Це відкриває локальний веб-інтерфейс, зазвичай за адресою http://127.0.0.1:6274, де можна переходити між інструментами, вводити параметри тестування та спостерігати за повідомленнями JSON-RPC, які надсилаються туди-сюди. Спочатку протестуйте тут. Непрацюючий інструмент набагато складніше відлагодити через поведінку виклику інструментів ШІ, ніж безпосередньо в інспекторі.

    Рівень 4: транспорти

    До цього моменту сервер працював із стандартним транспортом. Вибір має значення, оскільки він визначає, як буде підключатися агент LangGraph.

    Розглядайте транспорт як фізичний кабель, а JSON-RPC — як мову, яка по ньому передається. Англійська мова працює як по телефону, так і по радіо: одна мова, два кабелі. Сервери MCP використовують ту саму версію JSON-RPC 2.0 незалежно від транспорту, але дані передаються по-різному.

    stdio, для локальних інструментів

    Це стандартний варіант, який використовується mcp.run(), коли його викликають без аргументів:

    if __name__ == "__main__":
        mcp.run()  # stdio is the default
    

    За допомогою stdio (стандартного введення та виведення) хост запускає сервер як підпроцес та взаємодіє з ним, записуючи дані у його stdin та читаючи їх з stdout. Мережа не використовується: це комунікація між процесами на одній машині. Цей підхід підходить для серверів, які працюють поруч із хостом, таких як інструменти файлової системи, виконувачи локальних скриптів чи персональні утиліти; це найпростіша та найпоширеніша конфігурація для розробки.

    Є одна важлива обмеження. У режимі stdio stdout сервера призначений виключно для протокольних повідомлень, тому випадкова команда print() для дебагування пошкоджує потік даних. Логи мають записуватися у stderr.

    Streamable HTTP для віддалених інструментів

    Для мережевого сервера необхідно явно вказати спосіб передачі даних:

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

    Тут сервер працює як самостійний веб-сервіс. Клієнти під’єднуються через мережу за допомогою запитів HTTP POST, з можливістю використання Server-Sent Events для стрімування відповідей назад. Це робить сервер справді віддаленим: він може знаходитися на іншій машині, у хмарі або за балансувальником навантаження, та одночасно обслуговувати кілька додатків. Використовуйте його тоді, коли сервер потрібно поділити між командою, розгорнути централізовано або отримати доступ до нього з інших машин, включаючи агента LangGraph, який працює на сервері та взаємодіє з сервером MCP для доступу до бази даних.

    Основне правило: stdio для локальних інструментів, з одним користувачем та простою налаштуванням, що є типовим для розробки та особистого використання; Streamable HTTP для спільних інструментів, з багатьма користувачами чи додатками, для розгортання в продакшені та задоволення потреб у автентифікації. Саме цей варіант потрібно вказати для кожного сервера в налаштуваннях LangGraph.

    Рівень 5: підключення до LangGraph

    Цей „міст“ — це пакет під назвою langchain-mcp-adapters, який підтримується командою LangChain для того, щоб інструменти MCP стали придатними для використання всередині агентів LangGraph. Він виконує для MCP ту саму функцію, що й декоратор @tool для звичайних функцій: він перетворює зовнішній інструмент MCP на об’єкт BaseTool, який можна без проблем вставити в ToolNode LangGraph без необхідності спеціального оброблення в графі. Після перетворення агент не знає та не цікавиться тим, чи інструмент походить з сервера MCP, чи був створений безпосередньо в процесі.

    Встановіть його за допомогою:

    pip install langchain-mcp-adapters langgraph "langchain[openai]"
    

    Центральним об’єктом є MultiServerMCPClient, який може одночасно під’єднуватися до кількох серверів MCP та вільно поєднувати різні способи передачі даних:

    # ── MODULE 1 (extended): MCP CLIENT CONFIGURATION ───────────
    from langchain_mcp_adapters.client import MultiServerMCPClient
    
    client = MultiServerMCPClient({
        # A local server, launched as a subprocess via stdio
        "math": {
            "command": "python",
            "args": ["/absolute/path/to/math_server.py"],
            "transport": "stdio",
        },
        # A remote server, already running, connected over HTTP
        "company_data": {
            "url": "http://localhost:8000/mcp",
            "transport": "http",
        },
    })
    

    Кожен запис у словнику — це окремий сервер. Ключ ("math" або "company_data") є лише міткою, яка допомагає внутрішньо організувати інструменти з різних серверів. Запис відображає рішення щодо способу передачі даних: сервери stdio приймають command та args, а сервери HTTP — url.

    Завантаження інструментів вимагає одного виклику:

    # This single call discovers every tool, on every configured server,
    # and converts each one into a LangChain-compatible BaseTool
    tools = await client.get_tools()
    
    print([t.name for t in tools])
    # ['add', 'multiply', 'search_company_db', ...]
    

    Це і є вся процедура інтеграції. client.get_tools() надсилає запит MCP tools/list до кожного налаштованого сервера, отримує повернуті схеми та обгортає кожну з них у об’єкт інструменту, який з точки зору графа є недоступним відмінністю від вручну написаної функції @tool.

    Решта конфігурації виглядає так само, як у будь-якому агенті LangGraph. MCP змінює джерело інструментів, але не впливає на спосіб побудови графа. Повний шаблон:

    # ============================================================
    # LANGGRAPH + MCP AGENT — COMPLETE TEMPLATE
    # Extends: Part 1 (core structure)
    # ============================================================
    
    # ── MODULE 1: IMPORTS & CONFIGURATION ───────────────────────
    import asyncio
    from langchain_mcp_adapters.client import MultiServerMCPClient
    from langchain.chat_models import init_chat_model
    from langchain_core.messages import HumanMessage
    from langgraph.graph import StateGraph, MessagesState, START, END
    from langgraph.prebuilt import ToolNode, tools_condition
    from langgraph.checkpoint.memory import MemorySaver
    llm = init_chat_model("openai:gpt-4o")
    client = MultiServerMCPClient({
        "math": {
            "command": "python",
            "args": ["./math_server.py"],
            "transport": "stdio",
        },
        "company_data": {
            "url": "http://localhost:8000/mcp",
            "transport": "http",
        },
    })
    
    # ── MODULE 2: STATE ──────────────────────────────────────────
    class State(MessagesState):
        pass
    
    # ── MODULE 4: NODES ──────────────────────────────────────────
    # (Module 3, Tools, is now sourced from MCP rather than defined here)
    def make_agent_node(llm_with_tools):
        """Factory pattern: tools are loaded asynchronously, so the node
        closure is built after the async tool-loading step completes."""
        def agent_node(state: State) -> dict:
            response = llm_with_tools.invoke(state["messages"])
            return {"messages": [response]}
        return agent_node
    
    # ── MODULE 6: GRAPH ASSEMBLY (inside an async function) ──────
    async def build_graph():
        tools = await client.get_tools()
        llm_with_tools = llm.bind_tools(tools)
    
        graph_builder = StateGraph(State)
        graph_builder.add_node("agent", make_agent_node(llm_with_tools))
        graph_builder.add_node("tools", ToolNode(tools))
    
        graph_builder.add_edge(START, "agent")
        graph_builder.add_conditional_edges("agent", tools_condition)
        graph_builder.add_edge("tools", "agent")
    
        return graph_builder.compile(checkpointer=MemorySaver())
    
    # ── MODULE 7: ENTRYPOINT ──────────────────────────────────────
    async def main():
        graph = await build_graph()
        config = {"configurable": {"thread_id": "session-001"}}
    
        response = await graph.ainvoke(
            {"messages": [HumanMessage(content="What's (3 + 5) times 12?")]},
            config=config
        )
        print(response["messages"][-1].content)
    if __name__ == "__main__":
        asyncio.run(main())
    

    Усе стає асинхронним

    MCP вносить лише одну суттєву зміну. Комунікація є за своєю природою асинхронною, оскільки кожен виклик інструменту є подорожжю через мережу чи підпроцес, навіть через stdio. Тому client.get_tools() необхідно очікувати, створення графа зазвичай відбувається у функції async def, а скомпільований граф ініціюється за допомогою ainvoke, а не invoke. Усе інше — StateGraph, MessagesState, tools_condition та MemorySaver — залишається без змін.

    Знову готовий маршрутизатор

    У цій шаблоні механізм маршрутизації фактично відсутній. Замість власного маршрутизатора використовується готовий tools_condition: якщо останнє повідомлення містить виклики інструментів, переходиться до "tools", інакше процес завершується. Маршрутизатор не може розрізнити інструменти MCP від ручно написаних, оскільки обидва у момент їх сприйняття графом є об’єктами типу BaseTool.

    Рівень 6: проблеми продакшну

    Є кілька факторів, які відрізняють працездатну демонстрацію від системи, готової до розгортання, і саме вони найчастіше виникають у реальних конфігураціях MCP та LangGraph.

    Зберігайте з’єднання з клієнтом активним. MultiServerMCPClient за замовчуванням є безстановим: кожен виклик інструменту відкриває нове з’єднання, виконує завдання та розриває його. Це підходить для однієї заявки. Однак у додатку, який обслуговує багато користувачів, відкриття підпроцесу чи HTTP-з’єднання з кожним викликом спричиняє значну затримку. У продакшені слід відкрити клієнта один раз під час запуску процесу та використовувати його протягом усього життєвого циклу додатку:

    # Hold the connection open across the application's lifetime,
    # rather than opening/closing per request
    async with MultiServerMCPClient({...}) as client:
        tools = await client.get_tools()
        graph = await build_graph_with(tools)
        # ... serve many requests using this same graph ...
    

    Уникайте використання stdio у веб-сервері. Stdio був розроблений для локальних сценаріїв з одним користувачем на одній машині, наприклад коли десктопний додаток запускає допоміжний процес. Коли агент LangGraph розгортається як веб-сервіс для багатьох користувачів, сервери stdio стають проблемою: за кожним запитом створюються підпроцеси, і не існує природного способу обміну станом чи масштабування. Для будь-якого розгортання з боку сервера краще використовувати Streamable HTTP та чесно оцінити, чи справді потрібен окремий процес MCP. Існують випадки, коли звичайна функція @tool, яка безпосередньо викликає внутрішню бібліотеку, є кращою за додатковий проходження через протокол як за простотою, так і за швидкістю.

    Додайте людське схвалення для конфіденційних інструментів. Інструменти MCP є звичайними інструментами після того, як потрапляють у граф, тому до них застосовуються всі існуючі правила. Якщо сервер відкриває доступ до чогось конфіденційного, наприклад до надсилання електронних листів, зміни бази даних чи витрачання грошей, необхідно обгорнути цю дію тим самим кроком перевірки interrupt(), який використовується для будь-якого іншого виклику інструменту. MCP забезпечує можливість виявлення та стандартизації, але за замовчуванням не гарантує безпеки. Це залишається завданням розробника.

    Сервери не можуть бачити стан графа. Сервери MCP працюють як окремі процеси. Вони не можуть отримати доступ до state LangGraph, до checkpointer чи будь-якого об’єкта Python у пам’яті. Коли потрібно адаптувати виклик, наприклад, з використанням збережених уподобань користувача, значення потрібно передати явно як аргумент інструменту або через інтерцептори — це розширений механізм, який надається бібліотекою langchain-mcp-adapters та дозволяє перевіряти та змінювати виклик перед його надсиланням з використанням контексту виконання графа. Передача значень як аргументів достатня для більшості агентів та є значно простішою.

    Рівень 7: MCP у багатоагентній системі

    MCP поєднується з паттерном supervisor. Кілька спеціалізованих агентів отримують свої інструменти з власних спеціалізованих серверів:

    # ── Specialist agents, each pulling tools from a DIFFERENT MCP server ──
    
    async def build_multi_agent_system():
        client = MultiServerMCPClient({
            "research": {"url": "http://localhost:8001/mcp", "transport": "http"},
            "code":     {"url": "http://localhost:8002/mcp", "transport": "http"},
        })
    
        research_tools = await client.get_tools(server_name="research")
        code_tools     = await client.get_tools(server_name="code")
    
        researcher_llm = llm.bind_tools(research_tools)
        coder_llm      = llm.bind_tools(code_tools)
    
        # From here, wire researcher_node, coder_node, and a supervisor_node
        # exactly as shown in Part 4 - the rest of the supervisor pattern
        # is completely unchanged.
        ...
    

    MCP не вводить тут жодної конкуруючої архітектури. Спеціаліст, якого підтримує сервер MCP, структурно ідентичний спеціалісту, якого підтримують ручно написані інструменти: супервізор направляє повідомлення так само, а спеціалісти надсилають звіти так само. MCP змінює лише місце зберігання визначень інструментів та кількість додатків, які можуть їх повторно використовувати.

    Швидкий посібник

    • Архітектура. Host — це додаток ШІ, з яким працює користувач (тут агент LangGraph). Client знаходиться в host, по одному на кожен підключений сервер, і керує один-до-одного сеансом. Server — це автономна програма, яка надає інструменти, ресурси та запити, не знаючи, до якого host підключається користувач. JSON-RPC 2.0 — це формат повідомлень у всіх обмінах: запитах, відповідях та сповіщеннях.
    • Примітиви. Інструмент — це виконувана дія, яку модель обирає для виклику та яка створюється за допомогою @mcp.tool. Ресурс — це лише для читання дані, до яких можна отримати доступ за URI, керовані програмою або користувачем, та які створюються за допомогою @mcp.resource("uri://..."). Запит — це шаблон інструкції, який можна використовувати багаторазово та який ініціюється користувачем, створюючись за допомогою @mcp.prompt.
    • FastMCP. FastMCP(name="...") створює сервер — контейнер для всього. @mcp.tool оголошує функцію, яка читає підказки щодо типів для схеми та документацію для опису. @mcp.resource("scheme://{param}") оголошує тільки для читання дані, причому {param} використовується для створення шаблону. @mcp.prompt оголошує шаблон. mcp.run() запускає сервер — за замовчуванням через стандартний вхід/вихід, або з transport="streamable-http" для використання в мережі. fastmcp dev server.py відкриває інструмент інспекції для тестування без використання LLM.
    • Транспортування даних. stdio базується на підпроцесах та працює локально, де хост запускає сервер, і результати дебагування ніколи не повинні потрапляти у stdout. streamable-http є мережевим, підтримує багато одночасних хостів та є стандартом для продакшн-серверів.
    • Інтеграція з LangGraph. MultiServerMCPClient({...}) з модуля langchain_mcp_adapters.client дозволяє під’єднатися до одного або кількох серверів із різними способами транспортування даних у одному словнику. await client.get_tools() знаходить усі інструменти та перетворює їх на BaseTool. tools_condition є заздалегідь створеним маршрутизатором, який працює однаково як для інструментів, написаних вручну, так і для тих, що походять від MCP. Усе відбувається асинхронно: get_tools(), створення графу та ainvoke — усі ці операції вимагають використання await.

    Чи потрібен тут MCP?

    • Один інструмент, один агент, одна база коду. MCP не потрібен. Звичайна функція @tool є простішою та не має додаткових витрат через протокол.
    • Інструмент, який використовується в різних агентах чи проектах, або ділиться з колегами в інших фреймворках. Створіть його як сервер MCP. У цьому полягає основна цінність.
    • Бажання використовувати сотні існуючих серверів спільноти (GitHub, Slack, Postgres, Google Drive, Stripe та інші) замість власного коду інтеграції. Підключіться через MultiServerMCPClient та уникніть написання коду інтеграції, що часто є найбільшою економією часу від MCP.
    • Інструмент на іншій машині, ніж агент, або який використовується кількома хостами одночасно. Використовуйте Streamable HTTP як окрему службу.
  • Інструмент, який працює лише локально разом із одним агентом для розробки чи особистого використання. stdio достатньо, і його легше налаштувати.
  • Стандарт, а не заміна

    Вивчення нового протоколу викликає занепокоєння щодо того, що він може витіснити вже відомі рішення. MCP цього не робить. Він залишає інструменти, вузли та графи LangGraph недоторканими. Змінюється лише походження інструментів та кількість додатків, які можуть ними користуватися. Після того, як інструмент MCP досягає ToolNode, він поводиться як будь-який вручну створений інструмент, схвалюється за допомогою тих самих шаблонів interrupt() та підходить до тих самих архітектур керування.

    Прогрес відбувався поступово, як сходинки: концепції та ролі, три примітиви, робочий сервер, вибір способу передачі даних, міст LangGraph, посилення функціоналу для продакшну та композиція з багатоагентними системами. Кожен етап додавав нову ідею до вже існуючої стабільної основи. У поєднанні з канонічною структурою графа, управлінням пам’яттю, захистом через участь людини, оркестрацією та пошуком даних багатьма агентами це охоплює майже все, що потрібно справжньому продакшн-застосунку на базі LangGraph, а MCP дозволяє цим інструментам частково масштабуватися за межі однієї кодової бази.

    Пов’язана література

  • LangGraph Human-in-the-Loop: interrupt(), State Edits and Time Travel — Чотири патерни LangGraph для людського контролю: схвалення викликів інструментів за допомогою interrupt(), механізми зворотного зв’язку, ручна зміна стану та „подорож у часі“, із необхідними ключовими словами.
  • Практичні нотатки: Cost-Engineered Agentic Coding: Створення продакшн-готового рішення — Детальний огляд Практичних нотаток: Cost-Engineered Agentic Coding: Створення продакшн-готового рішення: контракти, перевірки та готові фрагменти коду для команд, які впроваджують цей патерн.
  • Як MCP змінює спосіб підключення штучних інтелектуальних агентів до бізнес-програмного забезпечення — Як протокол Model Context Protocol з’єднує агентів із CRM, ERP та внутрішніми API, що потрібно захищати та як бізнесу варто починати з малого.
  • LlamaIndex Plus LangGraph: чиста схема для агентів RAG — Як створити базу знань за допомогою LlamaIndex та зробити її доступною для агента LangGraph як інструменту, з поясненням функцій зберігання даних, Chroma та режиму лише отримання інформації.
  • Підключення AI-агентів до GeoServer 2.28 за допомогою розширення MCP — Встановіть JAR-файл розширення GeoServer MCP, перевірте, чи воно завантажено, викличте кінцеву точку за допомогою curl, під’єднайте Claude Desktop або LangChain, а також обмежте доступ та створіть інструменти для роботи.