Перейти к содержанию

Ассистенты (MCP)

Пайплайн — это JSON, а JSON языковая модель писать умеет. Чего она не умеет — знать, примет ли написанный граф ваш бэкенд: стадии ваши, типы узлов — у вашего ядра, а потолки принадлежат тому, кто вызывает.

stageflow-mcp — эта недостающая половина: MCP-сервер, который говорит на тех же семи эндпоинтах, что и редактор, так что ассистент может проверить граф на настоящем бэкенде, запустить его и прочитать, что вышло.

Вашему бэкенду менять ничего не нужно. Это второй клиент контракта, который вы уже обслуживаете, и он работает против развёртывания, сделанного раньше, чем он появился.

Как подключить

claude mcp add stageflow -- uvx stageflow-mcp --backend https://ваш-бэкенд

Адрес — тот же, что вводится на экране подключения редактора, и читается так же: localhost:8765 и …/api означают один бэкенд. Голому имени хоста подставляется https://, кроме loopback.

Проверить до того, как привязывать ассистента:

$ stageflow-mcp --backend https://ваш-бэкенд --check
backend      https://ваш-бэкенд
credential   none sent
stages       23
core         0.13.0
plan         demo (open)
node types   condition, entry, map, parallel, stage, subpipeline, switch, terminal, try
limits       {"counters": {"seconds": 30, "steps": 300, …}}

Ключ, если бэкенд его хочет

Это тот же ключ, что носит редактор, в том же заголовке, и выдаёт его не этот инструмент: ядро не знает, что такое токен (Чей это запрос), так что как он выглядит — решаете вы.

stageflow-mcp --backend https://… --token "$TOKEN"
stageflow-mcp --backend https://… --token "$TOKEN" --auth-header X-Api-Key

Без ключа вызывающий — то, что ваш бэкенд называет анонимным посетителем.

Если --backend не указан вовсе, первый же инструмент, которому нужен адрес, спросит его через собственный запрос MCP-клиента и запомнит ответ. Ключ никуда не записывается, и инструмента, принимающего ключ, намеренно нет: аргумент инструмента пишет модель, а значит он попадает в переписку и в логи клиента.

Что получает ассистент

Инструмент
validate_pipeline все нарушения разом — схема, граф, объявленные типы и то, что запрещает план вызывающего. Прогона не стоит.
run_pipeline запускает и отдаёт кадр переменных в конце, счётчики против ваших потолков и путь, которым прогон прошёл
stop_run останавливает идущий прогон
Ресурс
stageflow://guide как пишется граф: кадр, типы узлов, выражения
stageflow://stages ваши стадии, по строке на каждую
stageflow://stages/{name} одна стадия целиком — типы, необязательность, что значит каждый аргумент
stageflow://capabilities типы узлов, план и потолки, из /api/meta
stageflow://schema JSON Schema пайплайна, с вашими именами стадий и типами узлов в виде enum

Порядок работы, которого просит сервер: написать, позвать validate_pipeline, починить всё, что он перечислил, повторить — и только потом запускать. Проверка бесплатна, так что тратить прогон на выяснение опечатки в имени поля незачем.

Почему проверка не стоит прогона

Эндпоинта /api/validate в контракте нет, и он не требуется. POST /api/run с mode: "step" разбирает граф и проверяет его политикой вызывающего до того, как допустит прогон, — оба референсных бэкенда делают это именно в таком порядке, раньше, чем появятся поток, слот и id. Негодный граф отклоняется бесплатно; годный встаёт перед первым узлом, не исполнив ничего, и сразу гасится.

То есть проверка на мгновение занимает один слот прогонов вызывающего и не исполняет ничего. Если ваш бэкенд допускает прогон раньше проверки — об этом стоит знать и по другим причинам.

Что с этим можно сделать

Обязательного — ничего. Две вещи того стоят.

Отвечать на языке вызывающего. Ассистент передаёт Accept-Language; без этого собственные сообщения ядра приходят на том языке, на котором написаны (Локализация):

from stageflow import i18n

asked = request.headers.get("accept-language", "")
with i18n.use_locale(i18n.negotiate(i18n.parse_accept_language(asked))):
    ...

Держать ядро свежим. Отказ называет узел, к которому относится, и перечисляет все нарушения разом (Ошибки), а это разница между списком, который ассистент проходит по пунктам, и фразой, которую он вынужден разгадывать:

guard.except[0]: 'next' is a required property;
risky.arguments: Additional properties are not allowed ('oops' was unexpected)

Мост к открытому редактору

stageflow-mcp --backend https://… --bridge

печатает ссылку. Откройте её — и редактор смотрит на тот же граф, что и ассистент: что он рисует, попадает на холст, что вы меняете там, читается обратно. Приходящий граф сохраняет вашу камеру и положение всех карточек, которые вы перетащили, помечает тронутое и ждёт, пока его оставят или вернут.

Мост — это loopback-сокет на машине ассистента, под токеном, и ваш бэкенд в нём не участвует: разве что origin редактора должен быть разрешён, а он уже разрешён, если редактором кто-то пользуется. Одно правило браузера знать стоит: страница из интернета, стучащаяся на 127.0.0.1, у нынешнего Chrome проходит через разрешение пользователя. Разрешите — либо отдавайте редактор с той же машины (--editor http://127.0.0.1:8080/), и тогда ничего никуда не пересекает.

Чего он не делает

  • Ввод. Стадия в ядре умеет ждать ввода, но в HTTP-контракте канала для него нет — у редактора тоже, — так что ждущий граф отвалится по таймауту (Управление сессией).
  • Пошаговую отладку. Шаг существует, чтобы человек смотрел, как идёт граф; ассистенту, который не смотрит, он только держал бы слот.
  • Ничего локально. В этом процессе ничего не проверяется и не исполняется. Семантика живёт в ядре, которое крутит ваш бэкенд, а второе мнение было бы вторым воплощением, которому предстоит с ним разойтись.