Урок курса

MCP Client Tool: SSE и Selected tools

Продвинутый n8n: production-автоматизации и AI-агенты

В предыдущем уроке мы физически ограничили набор tools, подключённых к агенту: только нужные read-only операции попадали в его контекст. Теперь этот принцип реализуется через стандартизированный протокол — MCP. Вместо прямого wire-up каждого инструмента агент подключается к MCP-серверу как к единой точке, а уже там решается, какие именно инструменты видны.

Подключение MCP Client Tool к SSE Endpoint

MCP Client Tool — это sub-node, который добавляется в tool-вход AI Agent вместо отдельных HTTP Request или Function Item узлов. Его задача: установить соединение с MCP-сервером, получить манифест доступных инструментов и предоставить их агенту как единый пул.

В этом уроке используется один транспорт — SSE (Server-Sent Events). Поставляемый workflow export фиксирует учебный SSE Endpoint http://127.0.0.1:8765/mcp/v1/sse, а stub_server.py обслуживает именно этот маршрут во время локального прогона. Это значение берётся из параметра sseEndpoint ноды MCP Client Tool, а не из manifest.json. Сегмент v1 относится к учебному HTTP-маршруту; фактическая версия MCP server stub приходит в ответе initialize.serverInfo.

Поле Authentication в MCP Client Tool поддерживает значение None — выберите его, если поставляемый stub не требует аутентификации. Если же манифест stub документирует конкретный тип аутентификации (Bearer, Header или OAuth2), настройте соответствующий credential согласно документации stub. Не добавляйте credential «на всякий случай»: тип аутентификации определяется тем, что требует сервер, а не умолчаниями n8n.

Версию server stub берите из наблюдаемого initialize.serverInfo, а Selected allowlist — из параметров workflow export. agent-test-report.json содержит поле observation_receipt с существующим content-addressed файлом вида evidence/observations-<sha256>.json. В этом receipt лежат raw Agent responses, MCP wire, server invocations, counters и state hashes: для разрешённого lookup_ticket наблюдается один read call, а для исключённого delete_ticket отсутствует tools/call и состояние не меняется. Отдельных разрозненных JSONL-журналов этот pack не создаёт.

Наблюдаемый ответ tools/list объявляет lookup_ticket и delete_ticket, но workflow сразу фиксирует Tools to Include=Selected и выбирает только lookup_ticket. Наличие обоих имён в ответе discovery не означает, что оба раскрыты Agent: acceptance сравнивает exposed list с ['lookup_ticket'].

Tools to Include = Selected: allowlist и execution evidence для allowed/denied tool

Параметр Tools to Include = Selected задаёт allowlist прямо в workflow: includeTools=["lookup_ticket"]. Engine не знает этот список заранее — он читает его из MCP Client Tool node. Клиент выполняет полный цикл legacy SSE transport: initialize, затем notification notifications/initialized, затем tools/list. Из ответа сервера оставляются только имена из workflow config.

Получив lookup_ticket, Agent model stub возвращает raw tool_call; после этого клиент отправляет tools/call, а server log фиксирует read effect. Для запроса delete_ticket Agent получает список, где такого имени нет, и raw model response содержит refusal="tool_not_exposed". Engine переносит наблюдаемый refusal в отчёт, но не сочиняет его сам. В denied execution server не получает tools/call, delete_count остаётся нулём, business-state hash не меняется.

MCP wire, model transcripts и server invocations включают case/execution IDs и сохраняются единым content-addressed observation receipt. Повтор с тем же содержимым переиспользует тот же hash; runner не обнуляет канонические evidence-файлы.

Граница проверки. Поставляемый runner использует локальный интерпретатор поддерживаемого подмножества workflow и localhost stubs. Он не запускает настоящий n8n 2.39.9 и Redis (n8n_executed=false, redis_executed=false), поэтому его evidence подтверждает только разобранные nodes, connections, параметры, локальные ответы и эффекты. Импорт и поведение live n8n, Redis TTL/persistence и реального MCP Client Tool требуют отдельного integration run.

Задача 1

Как ограничить MCP Client Tool одним разрешённым инструментом?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 2

Как называется единственный разрешённый MCP tool?

Без регистрации · результат не сохраняется

Задача 3

MCP SSE allowlist: allowed и denied effects

Импортируйте основной export и выполните лабораторию «MCP SSE allowlist: allowed и denied effects». Сначала привяжите только выданные credential placeholders и замените REPLACE_WITH_* идентификаторы после импорта связанных workflows. Практическое изменение: Выберите Selected и оставьте в MCP allowlist только lookup_ticket; затем запросите разрешённый lookup и запрещённый delete. Запустите все сценарии fixture, сохраните workflow/execution evidence и локальный receipt. Contract runner проверяет export, topology и детерминированные локальные эффекты; живой запуск n8n подтверждается отдельно в интерфейсе или execution API.

Файлы лабораторной

Скачайте из блока «Файлы шага» n8n_lab_25_setup.py и n8n_lab_25_README.md. Setup-скрипт восстановит весь пакет с workflow exports; точные файлы для импорта и команду runner смотрите в README.

Зафиксированная среда

  • n8n 2.39.9; цель: self_hosted. Источник фиксации: Version lock курса n8n 2.39.9; type/typeVersion взяты из точного импортируемого workflow export и сверены с принятым module pack.

  • n8n-nodes-base.manualTrigger typeVersion 1 — Узел export manualTrigger в лаборатории lesson_25

  • @n8n/n8n-nodes-langchain.agent typeVersion 1 — Узел export agent в лаборатории lesson_25

  • @n8n/n8n-nodes-langchain.lmChatOpenAi typeVersion 1 — Узел export lmChatOpenAi в лаборатории lesson_25

  • @n8n/n8n-nodes-langchain.mcpClientTool typeVersion 1 — Узел export mcpClientTool в лаборатории lesson_25

  • n8n-nodes-base.set typeVersion 1 — Узел export set в лаборатории lesson_25

Подготовка

  1. Импортировать export и привязать зависимости. Импортируйте все workflow exports из выданного пакета. Создайте credentials вручную, замените REPLACE_WITH_* на реальные workflow IDs и не сохраняйте secrets в export.
    Ожидаемое наблюдение: Все узлы импортированы в n8n 2.39.9, credential placeholders разрешены, workflow остаётся неопубликованным до smoke-проверки.

Запуск

  1. Внести изменение и диагностировать обе ветки. Выберите Selected и оставьте в MCP allowlist только lookup_ticket; затем запросите разрешённый lookup и запрещённый delete.
    Ожидаемое наблюдение: Discovery может содержать оба tool, но Agent видит только lookup_ticket; denied case не создаёт tools/call и не меняет server state hash.

  2. Выполнить fixture matrix и получить receipt. Из корня пакета выполните python n8n_workflow_labs/lesson_25/assets/runner.py, затем повторите те же acceptance-сценарии в изменённом workflow и сохраните реальные execution IDs.
    Ожидаемое наблюдение: Локальный runner печатает receipt N8N-LAB-L25-PASS-274542abd4148591; observations содержат 2 case rows и n8n_executed=false.

Матрица приёмки

  • Сценарий allowed_lookup из versioned fixture после практического изменения. Выполните изменение: Выберите Selected и оставьте в MCP allowlist только lookup_ticket; затем запросите разрешённый lookup и запрещённый delete. Затем запустите case allowed_lookup через contract runner и соответствующую ветку импортированного workflow. Наблюдения: Discovery может содержать оба tool, но Agent видит только lookup_ticket; denied case не создаёт tools/call и не меняет server state hash.; Case отмечен pass только после появления actual observation.; В evidence сохранены workflow SHA-256, case result и граница n8n_executed.. Зафиксируйте: receipt, workflow_sha256, observation_sha256, case_results, n8n_executed.

  • Сценарий denied_delete из versioned fixture после практического изменения. Выполните изменение: Выберите Selected и оставьте в MCP allowlist только lookup_ticket; затем запросите разрешённый lookup и запрещённый delete. Затем запустите case denied_delete через contract runner и соответствующую ветку импортированного workflow. Наблюдения: Discovery может содержать оба tool, но Agent видит только lookup_ticket; denied case не создаёт tools/call и не меняет server state hash.; Case отмечен pass только после появления actual observation.; В evidence сохранены workflow SHA-256, case result и граница n8n_executed.. Зафиксируйте: receipt, workflow_sha256, observation_sha256, case_results, n8n_executed.

Сброс

  1. Очистить локальные evidence-файлы. Выполните python n8n_workflow_labs/lesson_25/assets/reset.py; перед повторным прогоном сбросьте также state выданного fixture/stub.
    Ожидаемое наблюдение: Локальные observations и receipt удалены; новый run создаёт их заново из fixture inputs.

Что отправить

Отправьте receipt из evidence_receipt.json вместе с workflow SHA-256, observation SHA-256, case results и отметкой n8n_executed. Для зачёта живого n8n-прогона приложите реальные execution IDs отдельно; локальный receipt их не подменяет.

Обязательные поля: receipt, workflow_sha256, observation_sha256, case_results, n8n_executed.

В поле ответа вставьте значение Локальный contract receipt из отчёта runner.

Границы проверки

  • Локальный contract runner исполняет поддержанное подмножество графовых контрактов и stubs; он не запускает настоящий n8n, поэтому evidence фиксирует n8n_executed=false.

  • Credential store, publish state, Redis persistence/TTL, реальные provider model calls и live MCP transport проверяются отдельным integration run в n8n 2.39.9.

  • REPLACE_WITH_* identifiers и credential placeholders нужно связать после clean import; секреты не входят в exports.

  • Тестовый localhost/host.docker.internal endpoint не является production HTTPS endpoint и не доказывает production security или reliability.

Без регистрации · результат не сохраняется

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку