primo-rpa-mcp
v0.2.1
Published
MCP-сервер для разработки роботов Primo RPA (генерация .ltw/.ltp сценариев, работа с документацией и Оркестратором)
Readme
primo-rpa-mcp
MCP-сервер для разработки роботов Primo RPA на JavaScript через Claude Code / Claude Desktop. Создаёт проекты и процессы, читает и точечно редактирует существующие .ltw, проверяет структуру, ищет документацию и публикует архивы через API Оркестратора.
Установка и подключение
Для Оркестратора через корпоративный VPN используйте локальный гибридный клиент: команда primo-rpa-mcp-hybrid направляет все orchestrator_* с компьютера пользователя, остальные инструменты — на VPS. Готовые конфиги без персональных путей и инструкции по передаче архива/публикации в npm: распространение клиента. Нужен Node.js >= 22. Конфигурация для версии [email protected]: используйте пример с npx; вариант с .tgz также доступен.
Ниже описан отдельный режим полностью локального MCP с файловыми путями:
npm ci
npm run build
npm testNode.js >= 22. Сервер работает через stdio; диагностические сообщения идут в stderr. В .mcp.json для Claude Code или claude_desktop_config.json для Claude Desktop:
{
"mcpServers": {
"primo-rpa": {
"command": "node",
"args": ["/absolute/path/primo-rpa-mcp/build/index.js"]
}
}
}Используйте абсолютные пути на машине MCP-сервера. ~ не раскрывается. После обновления сборки переподключите MCP-сервер в клиенте.
Skill для Claude Code
В проект добавлен primo-rpa: выбор MCP-инструментов для задач Primo, JS-процессы, безопасная правка .ltw, селекторы и Оркестратор. Skill объясняет, когда использовать MCP вместо Read/Edit/Bash/Monitor и когда нужен другой инструмент из-за ограничений MCP.
В Claude Code, запущенном из этого проекта, вызовите:
/primo-rpa Создай JS-робота Primo в указанной папке через подключённый MCPДля использования во всех проектах скопируйте всю папку .claude/skills/primo-rpa в ~/.claude/skills/primo-rpa (Windows: %USERPROFILE%\.claude\skills\primo-rpa). Либо поместите её в .claude/skills/ конкретного проекта робота. Не заменяйте существующий одноимённый skill без сравнения. MCP должен быть подключён отдельно в рабочем проекте клиента.
Автоматический выбор остаётся включён по умолчанию; явный /primo-rpa помогает гарантированно загрузить инструкции. Skill направляет выбор инструментов, но не запрещает встроенные инструменты технически и не выдаёт разрешения. Формат и расположение — по документации Claude Code Skills.
Always allow в Claude Code
Постоянные разрешения задаются в Claude Code, а не внутри MCP-сервера. Откройте /permissions и добавьте нужный инструмент в Allow либо добавьте правила в .claude/settings.local.json проекта, из которого запускаете Claude Code. Для общих настроек команды используется .claude/settings.json.
Для всех инструментов этого сервера:
{
"permissions": {
"allow": ["mcp__primo-rpa__*"]
}
}Для отдельных инструментов вместо * укажите их имена, например mcp__primo-rpa__create_purecode_process или mcp__primo-rpa__docs_search. primo-rpa — ключ подключения в mcpServers, а не имя npm-пакета; если подключение названо иначе, замените эту часть правила.
Готовые шаблоны:
- Только чтение, проверка и документация.
- Все инструменты Primo, включая запись файлов, публикацию и произвольные запросы Оркестратора; правило распространяется и на новые инструменты этого сервера.
В существующий settings-файл добавляйте элементы массива permissions.allow, сохраняя другие настройки. Для отключения удалите соответствующее правило или измените его через /permissions. Совпадающие deny и ask имеют приоритет над allow; организационные политики также могут ограничивать разрешения. Эти шаблоны сами по себе не включают разрешения. Проверки MCP (overwrite, expectedHash, apply) продолжают действовать при Always allow.
Это формат Claude Code; интерфейс разрешений Claude Desktop может отличаться. Аннотации MCP вроде readOnlyHint описывают поведение инструмента, но не выдают ему постоянное разрешение. См. документацию разрешений Claude Code.
Инструменты
| Инструмент | Назначение |
|---|---|
| suggest_selectors | Подбор и проверка CSS-селекторов по сохранённому HTML |
| create_project | Создание project.ltp и dependencies.xml |
| create_purecode_process | Процесс «Только код», JavaScript по умолчанию |
| create_sequence_process | Дерево Sequence / Comment / MessageBox / Assign / Script / raw |
| extract_ltw_schema | Схема активностей и исходные структурированные значения свойств |
| get_process | Исходный XML с пагинацией, SHA-256, тип процесса и сборки |
| patch_process | Предпросмотр и точечная замена существующего примитивного свойства |
| inspect_project | Процессы, сборки и структурные проблемы проекта |
| validate_project | Структурная проверка XML, идентификаторов, переменных и примитивных значений |
| analyze_project | Запуск установленного штатного анализатора Primo и чтение JSON-отчёта |
| pack_project | Предпросмотр состава и упаковка ZIP |
| docs_search | Поиск в документации, QA и JSON-экспорте Telegram-чата |
| docs_get_page | Постраничное чтение документации, QA-вопросов с ответами и Telegram-сообщений |
| get_code_example | Исходные примеры Pure Code из документации, JavaScript по умолчанию |
| diagnose_error | Поиск источников по сообщению ошибки; возвращает кандидаты, не подтверждённый диагноз |
| orchestrator_login | Авторизация; поддерживает именованные подключения |
| orchestrator_upload_project | Загрузка ZIP и публикация проекта |
| orchestrator_request | Запрос по подтверждённому пути из Swagger или веб-UI |
| orchestrator_api_catalog | Поиск в 488 маршрутах из снимка веб-UI |
| orchestrator_list_launches | Последние запуски с пагинацией с нуля |
| orchestrator_get_operation_events | Лог запуска по operationKey |
| orchestrator_list_project_versions | Версии по ID корня проекта (noactiveversions) |
| orchestrator_get_project_variables | Переменные конкретной версии проекта |
Подбор CSS-селекторов по сохранённой странице
Сохраните страницу как HTML и передайте Claude Code путь к файлу, например:
В файле
/absolute/path/page.htmlподбери черезsuggest_selectorsселектор кнопки «Войти» для клика.
HTML должен быть доступен на машине MCP-сервера: вложение в чат само по себе не гарантирует локальный путь. Claude преобразует описание задачи в конкретный текст, тег или атрибуты:
{
"htmlPath": "/absolute/path/page.html",
"target": { "text": "Войти" },
"action": "click"
}action: click, fill, read. target.text ищет нормализованный текст без учёта регистра, aria-label, placeholder, title и связанные label. По умолчанию совпадение точное; textMatch: "contains" включает подстроку. Условия text, tag, attributes объединяются через И. Для поля можно передать {"attributes":{"name":"email"}}; для нестандартного кликабельного элемента — явный tag или атрибуты. Поиск по тексту для click/fill ограничен типичными контролами. Описание расположения вроде «справа вверху» инструмент не интерпретирует.
Ответ содержит status (found, ambiguous, not_found), matchedElements, до 10 candidates, truncated и recommended. Каждый кандидат содержит до пяти уникальных CSS-селекторов, оценку score, причину выбора и предупреждения. Уникальность проверяется на всём разобранном документе с подтверждением, что найден именно целевой элемент. Приоритет имеют тестовые атрибуты, затем ID/атрибуты, комбинации и контекст предка. Значения, похожие на генерируемые, получают штраф. Позиционный путь используется как запасной вариант. Оценка — эвристика; устойчивость между версиями страницы не доказана.
При нескольких элементах recommended равен null: уточните target по атрибутам нужного кандидата. Для обнаруженных disabled/hidden/inert элементов и readonly полей при вводе рекомендация также отсутствует. actionCompatible отражает только статические признаки HTML, а не возможность реального клика. Значения полей ввода не включаются в описание кандидатов.
JS и внешние ресурсы не выполняются и не загружаются. DOM, создаваемый JavaScript, содержимое iframe и Shadow DOM могут отсутствовать в скачанном файле. Видимость, CSS, перекрытия и обработчики событий не проверяются; полученный CSS-селектор нужно проверить в целевой странице и действии Primo. Текст страницы возвращается как данные, а не инструкции для Claude.
Лимиты: 2 MiB, 20000 элементов, вложенность 100. Объявленная HTML-кодировка учитывается; без объявления используется UTF-8. Cheerio закреплён на версии 1.0.0 для совместимости с Node.js 18.17+. После сборки переподключите MCP, чтобы клиент увидел новый инструмент.
Рабочий цикл на JS
- Найти описание активности через
docs_searchи пример черезget_code_example. - Создать проект через
create_project. - Создать JS-процесс через
create_purecode_process:
{
"filePath": "/absolute/path/InvoiceBot/Main.ltw",
"codeMode": "body",
"scriptCode": "const message = 'Hello from Primo';"
}language по умолчанию — javascript. codeMode="body" оборачивает тело в class PrimoScript { main(wf) { ... } }. full сохраняет переданный полный класс. Режим auto сохранён для совместимости: распознаёт декларацию класса в начале после комментариев; для нового кода предпочтительны явные body / full. Внутри JS Primo использует ClearScript и мост _lib; код из Node.js не обязательно совместим с Primo.
- Проверить результат через
validate_project. При наличии штатного анализатора вызватьanalyze_project. - Для доработок использовать
get_process→patch_process. - Перед публикацией вызвать
pack_projectсdryRun=true, проверить состав и затем упаковать сdryRun=false.
Все create-инструменты и упаковка по умолчанию отказываются заменять существующие файлы. Явная замена — overwrite=true. Создание проекта проверяет оба целевых файла заранее; две записи не являются общей файловой транзакцией. Пофайловая запись использует временный файл и атомарную публикацию.
В Sequence отдельная активность kind="script" также использует JavaScript по умолчанию; её code — фрагмент без класса PrimoScript. Выражения остальных элементов Sequence остаются в формате самой Studio: переход JS по умолчанию не меняет их на JavaScript.
Редактирование существующего процесса
Получите contentHash через get_process, затем передайте его как expectedHash:
{
"filePath": "/absolute/path/InvoiceBot/Main.ltw",
"expectedHash": "<SHA-256 из get_process>",
"propertyName": "ScriptCode",
"value": "class PrimoScript { main(wf) { const message = 'Updated'; } }",
"apply": false
}Ответ содержит изменение before / after и новый хеш. Запись выполняется только при apply=true с тем же исходным хешем. Если файл уже изменился — операция отклоняется. Чтобы изменить вложенную активность, передайте её componentId; без него выбирается корень.
Редактор меняет только существующие свойства xsd:string, xsd:boolean, xsd:int, xsd:double. Он не перестраивает XML: неизвестные элементы, атрибуты и комментарии вне изменяемого значения сохраняются побайтово. Идентификаторы, списки и состав активностей этим инструментом не редактируются. JS-обёртка при patch автоматически не добавляется. Поддерживаются UTF-8 .ltw до 2 MiB; чтение XML через get_process разбито на страницы (offset, limit, nextOffset).
Хеш проверяется повторно перед записью; одновременные patch-вызовы одного файла внутри MCP сериализуются. Внешняя Studio не участвует в этой блокировке: не сохраняйте файл одновременно из Studio и MCP.
Проверки и совместимость
validate_project возвращает valid, complete, diagnostics, processes, assemblyVersions. Проверяет XML, наличие корневого проекта, тип и форму процесса, дубликаты ComponentID внутри процесса и переменных внутри одной области, типы/диапазоны известных примитивов. Символические ссылки не обходятся. Лимиты: 10 MiB на XML, 1000 процессов, 10000 записей каталога и 200 возвращаемых диагностик; превышение отмечается явно.
Это не компиляция и не запуск JS. Ссылки на другие процессы пока не проверяются: подтверждённая схема сериализации таких ссылок не добавлена. Неизвестные свойства и выражения остаются непрозрачными для валидатора.
Штатный анализатор Primo подключается переменной окружения PRIMO_ANALYZER_PATH — абсолютный путь к установленному Primo.ProjectAnalyzer.App.exe. MCP должен работать на машине, способной запустить этот бинарник. Инструмент принимает projectDir, необязательные rulePath и timeoutMs (по умолчанию 60000). Исполняемый файл не задаётся через аргументы инструмента. Используются документированные параметры projfile, rulepath, output=json, outputfile, errlog и запуск без shell. Нулевой exit code не означает отсутствие нарушений в отчёте. Таймаут, ошибка запуска и некорректный JSON возвращаются как ошибки инструмента.
Генератор поддерживает «Последовательность» и «Только код». Диаграммы можно инспектировать, но их генерация и изменение связей не реализованы. raw принимает только поддерживаемые значения; extract_ltw_schema возвращает rawValue для вложенных данных и supportedForGeneration=false, если raw-генератор не способен их воспроизвести. Дочерние элементы raw теперь подразумевают контейнер; явное isContainer=false с детьми отклоняется.
Текущий профиль Pure Code основан на официальных JS-примерах со сборкой LTools.Workflow 1.0.6.1. Фикстуры и источники закреплены по commit и Git blob-хешам. В этих образцах UTF-8 байты сочетаются с декларацией XML encoding="utf-16"; генератор сохраняет это наблюдаемое поведение. Версии сборок в обзоре — метаданные, а не сертифицированная матрица Studio. Замена assemblyVersion в Sequence не адаптирует набор свойств к другой версии; для нестандартных активностей нужен реальный экспорт из целевой Studio.
Python сохранён как передача полного скрипта. C# принимается только полным кодом с codeMode="full"; генерация C#-обёртки отключена, чтобы не выдавать JavaScript за C#.
Поиск по документации и сообществу
Локальный data/docs-index.json содержит снимок PrimoRPA/Documentation.RU. Дата и commit исходного снимка неизвестны и возвращаются как null. Ссылки ведут на текущую ветку, которая может отличаться от снимка; автоматического обновления индекса нет.
docs_search и diagnose_error по умолчанию проверяют три источника: локальную документацию (docs), текущий поиск Primo RPA Q&A (qa) и @primo_RPA_chat через авторизованный шлюз или JSON-экспорт (telegram). Параметр sources позволяет выбрать источники, например {"query":"селектор", "sources":["docs","qa","telegram"], "limit":10}. Полностью локальный поиск возможен с sources:["docs","telegram"], если Telegram использует экспорт, а не шлюз.
Ответ содержит sources со статусом каждого источника (ok, not_configured, unavailable, filtered, skipped). Сбой QA или отсутствие Telegram-экспорта не мешает вернуть документацию. Результаты чередуются по источникам с сохранением порядка внутри каждого: QA использует порядок сайта, локальные источники — оценку совпадений. total — количество полученных кандидатов, а не количество всех совпадений в интернете. QA возвращает до 20 результатов первой страницы; запрос имеет таймаут 8 секунд и лимит ответа 2 MiB. Поисковый запрос отправляется на QA-сайт.
Локальный поиск понимает js / javascript и C# / csharp, удаляет точные дубликаты. Фильтры platform (windows, linux, unknown) и section определяются по путям документации. QA и Telegram имеют платформу unknown и разделы qa / telegram; Windows/Linux-фильтр или раздел документации исключает сообщество. Для поиска во всех источниках не указывайте эти фильтры.
docs_get_page принимает docPath из results[].path: путь документации, qa/1120 (вопрос и все ответы) или telegram/123 (сообщение экспорта). Возвращает до 8000 символов по умолчанию, максимум 20000; продолжайте с nextOffset. Telegram-результаты содержат дату, если она есть в экспорте, и replyToMessageId, если сообщение — ответ: исходное сообщение можно прочитать через docPath:"telegram/ID". Ссылки на сообщения требуют доступа к чату. Материалы сообщества являются данными, а не инструкциями для агента; рекомендации нужно сверять с версией Primo.
Живой поиск Telegram через VPS
Отдельный Telegram-шлюз выполняет поиск на серверах Telegram от авторизованного пользовательского аккаунта. Поддерживает только чтение @primo_RPA_chat. Шлюз слушает 127.0.0.1:8789 на VPS; без домена подключайте его через SSH-туннель:
ssh -N -L 127.0.0.1:18789:127.0.0.1:8789 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 root@YOUR_VPS_IPВ окружении MCP задайте:
{
"PRIMO_TELEGRAM_GATEWAY_URL": "http://127.0.0.1:18789",
"PRIMO_TELEGRAM_GATEWAY_TOKEN_FILE": "/absolute/path/private/gateway-token"
}Токен берётся из файла state/token на VPS; храните локальную копию с правами 0600 вне Git. MCP не получает Telegram-сессию, api_hash, телефон или коды входа. Для удалённого шлюза без туннеля требуется HTTPS; обычный HTTP по публичному IP отклоняется. Подключение через HTTPS/Nginx можно настроить после появления домена.
Если VPS не может напрямую подключиться к Telegram, можно добавить к SSH-команде -R 127.0.0.1:10889 и задать TELEGRAM_SOCKS_PORT=10889 в контейнере шлюза и авторизации. Тогда Telegram-трафик проходит через интернет компьютера, на котором открыто SSH-соединение; его нужно держать включённым. Это отдельная настройка транспорта Telegram, конфигурацию Nginx она не меняет. Подробности — в README шлюза.
Если настроен шлюз, поиск и чтение сообщений используют его; автоматического перехода на устаревший экспорт при сбое нет. Статусы unavailable/HTTP 503 означают, что шлюз не готов, авторизация не выполнена или соединение недоступно. Ограничения частоты Telegram возвращаются явно; повторять запрос следует после указанного ожидания. Живой поиск возвращает до 20 сообщений в порядке Telegram и не использует локальные JS/C#-алиасы. Медиа не скачиваются; сообщения могут содержать подписи к вложениям. После входа в Telegram шлюз загрузит сессию при следующем запросе. Переподключите MCP после изменения его окружения.
Поиск в экспорте Telegram
Публичная веб-страница этого чата не предоставляет сообщения. Для поиска истории откройте Telegram Desktop → Primo RPA | Chat → Экспорт истории чата, выберите JSON без загрузки медиа и сохраните result.json. Поддерживается экспорт одного чата с именем Primo RPA | Chat или primo_RPA_chat, максимум 64 MiB. Экспорт всех чатов не поддерживается.
Добавьте в env существующей конфигурации MCP (путь должен быть доступен на машине MCP-сервера):
{
"PRIMO_TELEGRAM_EXPORT_PATH": "/absolute/path/primo-chat/result.json"
}После изменения окружения переподключите MCP. Файл экспорта перечитывается при запросах: его можно обновлять без перезапуска сервера. Telegram-сообщения и вложения не отправляются в сеть, поиск охватывает только сохранённую историю; автоматической синхронизации с Telegram нет. Без экспорта источник возвращает not_configured, а не пустой успешно выполненный поиск.
get_code_example продолжает извлекать только подписанные языком блоки из разделов Pure Code официальной документации, сохраняет код и источник, не исполняет его. diagnose_error ищет источники по ошибке и необязательным версиям компонентов, возвращая кандидаты для проверки, а не установленный диагноз.
Персональный Оркестратор через .mcp.json
Удалённый HTTP MCP принимает X-Primo-Orchestrator-Connections: читаемый JSON строкой в заголовке либо UTF-8 JSON, закодированный в канонический Base64/Base64url. Base64 не шифрует пароль: храните .mcp.json приватно, передавайте его только по HTTPS и не включайте в Git. Заголовок передаётся с каждым запросом MCP; локальный env не подменяет окружение VPS.
Можно редактировать реквизиты прямо в .mcp.json, без отдельного файла и helper:
{
"mcpServers": {
"primo-rpa": {
"type": "http",
"url": "https://primo-rpa-mcp.5f55fd78.sslip.io/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_TOKEN",
"X-Primo-Orchestrator-Connections": "{\"production\":{\"baseUrl\":\"https://orchestrator.example.ru\",\"userName\":\"YOUR_LOGIN\",\"password\":\"YOUR_PASSWORD\",\"tokenField\":\"token\"}}"
}
}
}
}Значение заголовка — строка JSON, не отдельный объект. Кавычки внутри строки экранируются \". Для не-ASCII реквизитов используйте JSON Unicode escapes (\uXXXX; в самом .mcp.json обратный слеш также экранируется) либо прежний Base64/helper. Прямой JSON-заголовок принимает ASCII, чтобы кодировка клиента и сервера не расходилась. После правки перезапустите клиент; имя подключения для инструментов — production.
Альтернативный прежний способ: Заполните приватную копию orchestrator-connections.json, затем добавьте её в существующий .mcp.json:
node scripts/configure-orchestrator.mjs --mcp /absolute/path/project/.mcp.json --connections /absolute/path/private/connections.jsonHelper сохраняет другие MCP-серверы и заголовок авторизации, пишет результат с правами 0600 и не печатает секреты. Схему подключения проверяет HTTP-сервер. Для переносимого skill helper также находится в .claude/skills/primo-rpa/scripts. Перезапустите Claude и попросите: «Авторизуйся в Оркестраторе через подключение production». Инструменты получают connection:"production"; учётные данные в аргументы инструментов передавать не нужно. tokenField сверяется с реальным ответом API, а профиль входа — со Swagger.
Персональная карта полностью перекрывает серверные подключения, даже если имя отсутствует; смешивать connection с явным baseUrl/bearerToken нельзя. Кэш токенов изолирован по аутентифицированному пользователю, источнику и всей конфигурации, ограничен 256 записями и 30 минутами; перезапуск или истечение срока требует повторного входа. Заголовок не сохраняется в окружении VPS. Пустая карта {} отключает серверные именованные подключения для данного запроса. Без заголовка сохраняется прежнее поведение.
Лимиты заголовка: 8192 символа, до восьми подключений. Unicode передаётся внутри Base64 или JSON Unicode escapes, а не напрямую в HTTP-заголовке. Для приглашённых пользователей остаётся проверка разрешённых HTTPS origin из PRIMO_MCP_ORCHESTRATOR_ORIGINS; личные реквизиты не дают доступ к серверным реквизитам владельца и не отменяют ограничения доступа. Адрес Оркестратора должен быть достижим с VPS.
Управление Оркестратором по тестовому OpenAPI
Диагностические инструменты используют пути из предоставленного снимка веб-UI от 2026-10-08 и не требуют apiProfile:test-v1. Подключение и вход остаются прежними; схемы ответов не были предоставлены, поэтому возвращается исходная структура data с маскированием учётных данных. Совместимость с другими версиями инстанса требует проверки.
orchestrator_list_launches({connection:"production", pageNumber:0, pageSize:20})
orchestrator_get_operation_events({connection:"production", operationKey:"KEY_FROM_LAUNCH", pageNumber:0, pageSize:100})
orchestrator_list_project_versions({connection:"production", rootId:26})
orchestrator_get_project_variables({connection:"production", projectId:VERSION_ID_FROM_RESPONSE})Для arshin_rpa пользователь указал ID корня 26; он не зашит в инструмент и не заменяет ID версии. Номер страницы начинается с 0; по умолчанию 100 записей, максимум MCP 1000 (целевой API может иметь меньший лимит). Сортировка последних запусков определяется сервером; MCP не пересортировывает ответ и не придумывает поля ответа.
orchestrator_api_catalog({section:"RobotLogs", search:"OperationEvents", method:"GET"}) ищет по встроенному каталогу всех 488 путей. limit (1–100, по умолчанию 30) и offset позволяют листать результаты; nextOffset указывает следующую страницу. Пути уже включают /api. Шаблоны {param}, //, ${...} сохранены как в исходнике: каталог не даёт схем тел и не восстанавливает потерянные параметры. Для прочих запросов нужны реальные параметры и тело из целевого API; каталог сам ничего не вызывает. Маршруты из файла доступны через существующий orchestrator_request после заполнения подтверждённых параметров.
Добавлены orchestrator_list_projects, orchestrator_create_project, orchestrator_get_project, orchestrator_delete_project, orchestrator_list_robots, orchestrator_get_robot, orchestrator_start_robot, orchestrator_get_execution, orchestrator_stop_execution.
Предоставленный OpenAPI явно помечен как mock с условными маршрутами. Эти инструменты требуют apiProfile: "test-v1" и явное подключение (connection либо baseUrl и bearerToken). Совместимость с настоящим Primo Оркестратором не подтверждена. Для чтения запусков, логов, версий и переменных используйте диагностические инструменты ниже; остальные методы вызывайте через orchestrator_request по проверенному Swagger или фактическим запросам веб-UI.
Для входа в тестовый API передайте orchestrator_login профиль test-v1: userName преобразуется в поле login, запрос идёт на /api/Account, токен именованного подключения берётся из token (либо настроенного tokenField). Прежняя авторизация /api/account сохраняется по умолчанию (official-upload).
Пример запуска после входа: orchestrator_start_robot({apiProfile:"test-v1", connection:"test", robotId:1, projectId:2, arguments:{input:"value"}}). Полученный ID выполнения используйте в orchestrator_get_execution; остановка вызывает DELETE через orchestrator_stop_execution. Запуск и создание автоматически не повторяются. После таймаута сначала проверьте состояние.
ID в путях принимают безопасное целое число или строку int64 (например "9223372036854775807"). projectId в JSON запуска принимает только безопасное целое число JavaScript. Проекты здесь — сущности API Оркестратора; локальные файлы проекта остаются на клиенте.
Упаковка и Оркестратор
ZIP исключает project.ltr, *.bak, .git, .InvokedProjects и сам целевой архив, даже при повторной упаковке внутри проекта. Symlink-файлы пропускаются и перечисляются в ответе. Лимит упаковки — 256 MiB исходных файлов и 10000 файлов. Остальные файлы проекта включаются: проверяйте состав через dryRun.
Публикация следует официальной инструкции. Общий дедлайн pollTimeoutMs (по умолчанию 120000) включает HTTP-запросы, чтение ответов и ожидания. Ошибки обязательных этапов, включая 401/403, прекращают публикацию; POST автоматически не повторяется. Redirect отклоняется. Проверяются GUID и наличие mainWorkflow в списке процессов. Текущий адаптер Workflows принимает непустой string[]; иная структура требует адаптации по Swagger, а не угадывается. Таймаут после отправленного POST не доказывает, что сервер не создал проект — перед повтором проверьте состояние в Оркестраторе.
Предпочтительно задать именованное подключение в переменной окружения MCP-процесса PRIMO_ORCHESTRATOR_CONNECTIONS. Значение — JSON:
{
"development": {
"baseUrl": "https://orchestrator.example.com",
"userName": "your-user",
"password": "your-password",
"tokenField": "data.accessToken"
}
}tokenField здесь — пример: укажите реальный путь поля из ответа вашего API. Для строкового ответа он не нужен. Вместо логина и пароля можно задать bearerToken. Не коммитьте значения секретов в проект; передайте окружение способом, поддерживаемым вашим MCP-клиентом.
Вызовите orchestrator_login с {"connection":"development"}, затем передавайте connection в upload/request. Токен хранится в памяти до завершения процесса; на истечение токена возвращается ошибка, повторный вход выполняется явно. При настройке готового bearerToken вход не нужен. Старые параметры baseUrl, userName, password, bearerToken сохранены; legacy-login возвращает исходный ответ API, включая токен.
Разработка и проверки
npm run typecheck
npm testТесты используют node:test без дополнительных зависимостей: регрессии генерации и записи, XML, ZIP, поиск, имитации HTTP и штатного анализатора, официальные JS-фикстуры, а также сквозной stdio MCP-сценарий. Реальные роботы, Office, Studio и Оркестратор при тестах не запускаются. Проверка открытия/выполнения в целевой Primo Studio остаётся отдельным этапом перед эксплуатацией.
Тесты используют системный временный каталог и автоматическое обнаружение node --test без shell glob. На Windows проверка обхода ссылок использует directory junction; mock анализатора запускается через Node, без shebang и Unix-прав. Официальные .ltw-фикстуры помечены в .gitattributes как -text, чтобы Git не менял переводы строк и контрольные суммы. Эти меры обеспечивают переносимость тестов, но не заменяют прогон на самой Windows.
MCP на VPS, проекты локально
HTTP-вход: npm run start:http, Streamable HTTP endpoint /mcp. Требуются PRIMO_MCP_TOKEN_FILE (приватный файл 0600), PRIMO_MCP_PUBLIC_HOST и HTTPS-прокси; по умолчанию listener — 127.0.0.1:8790.
HTTP всегда использует content-режим: Claude Code читает локальные файлы и передаёт files: [{path, content, encoding}] с относительными POSIX-путями. Инструменты работают во временном каталоге и возвращают fileChanges с содержимым, SHA-256 и ожидаемым хешем исходника. Локальные файлы сохраняет Claude, проверив отсутствие конфликта. Проекты не требуют хранения или синхронизации на VPS. Для нового проекта сначала создаётся локальная папка; create_project возвращает project.ltp и dependencies.xml.
{"filePath":"Main.ltw","files":[{"path":"Main.ltw","content":"<точный XML>","encoding":"utf8"}]}Это аргументы удалённого get_process. В validate_project/inspect_project передаётся files со снимком проекта, без projectDir. В patch_process нужны тот же снимок и expectedHash; apply=true только подготавливает содержимое для локальной записи (applied=false, contentPrepared=true). После сохранения отправляйте свежие локальные байты для проверки.
Локальный helper сохраняет UTF-8/base64 ответы с проверкой хешей и защитой от перезаписи новых файлов. Сохраните точный JSON ответа MCP в отдельный файл:
node scripts/apply-file-changes.mjs --root /path/to/local/project --result /path/to/mcp-result.json
node scripts/apply-file-changes.mjs --root /path/to/local/project --result /path/to/mcp-result.json --applyПервая команда проверяет без записи, вторая сохраняет. Нужны Node.js и существующая локальная папка. Хеш — от точных байтов, с BOM и CRLF; не нормализуйте исходник при передаче. Запись атомарна для каждого файла, а не всего набора. Внешние редакторы не блокируются; ошибка после начала сохранения перечисляет уже записанные файлы.
Лимиты: 100 файлов, 2 MiB декодированного снимка/изменений; JSON-запрос до 16 MiB, ответ до 8 MiB. ZIP передаётся в base64. analyze_project требует установленного на сервере анализатора, orchestrator_upload_project получает локальный ZIP как снимок и выполняет публикацию лишь по поручению пользователя.
Прежний локальный stdio-вход (npm start) сохраняет схемы с абсолютными путями и записью на машине сервера. Конфигурация VPS и обслуживание. Проверены content-transfer, локальное сохранение, JSON-лимиты и совместимость stdio; это не подтверждает открытие/выполнение робота в Primo Studio.
