npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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 test

Node.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-пакета; если подключение названо иначе, замените эту часть правила.

Готовые шаблоны:

В существующий 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

  1. Найти описание активности через docs_search и пример через get_code_example.
  2. Создать проект через create_project.
  3. Создать 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.

  1. Проверить результат через validate_project. При наличии штатного анализатора вызвать analyze_project.
  2. Для доработок использовать get_process → patch_process.
  3. Перед публикацией вызвать 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.json

Helper сохраняет другие 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.