primo-rpa-mcp 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,13 +26,14 @@ description: Разработка и диагностика роботов Primo
26
26
  | Упаковать для передачи | `pack_project` с явным `dryRun=true`, затем `dryRun=false` |
27
27
  | Опубликовать в Оркестраторе | `orchestrator_login` при необходимости → `orchestrator_upload_project` |
28
28
  | Управлять проектами, роботами и выполнениями тестового API | [Методы управления](references/orchestrator.md); только `apiProfile=test-v1` по совпадающему контракту |
29
- | Получить статус/логи задания рабочего Оркестратора | `orchestrator_request` по подтверждённому Swagger текущего инстанса |
29
+ | Получить запуски, логи, версии и переменные | `orchestrator_list_launches`, `orchestrator_get_operation_events`, `orchestrator_list_project_versions`, `orchestrator_get_project_variables`; без test-v1, см. [контракт](references/orchestrator.md) |
30
+ | Найти другие маршруты API | `orchestrator_api_catalog` → `orchestrator_request` с подтверждёнными параметрами Swagger/веб-UI |
30
31
 
31
32
  ## Граница с Monitor и универсальными инструментами
32
33
 
33
34
  Запуск через `orchestrator_start_robot` поддержан только для явного тестового контракта `test-v1`. Запуск в локальной Studio, live-браузер и непрерывный мониторинг не предоставляются этим MCP. Не выдумывай `run_robot`, `monitor_job` и другие отсутствующие инструменты.
34
35
 
35
- Если задача — статус задания Primo, источником истины служит API соответствующего Оркестратора: используй `orchestrator_request`, когда известны метод, путь и идентификатор из Swagger/реального ответа. Не угадывай endpoint. Специализированные методы управления реализуют предоставленный mock OpenAPI (`test-v1`); не считай их маршруты подтверждёнными для настоящего Primo. Если схемы нет, найди её в доступных материалах либо запроси недостающую схему. Для повторного опроса заранее определи интервал, конечные статусы и ограничение времени; по таймауту сообщи последний наблюдавшийся статус. Не запускай задание повторно для проверки статуса.
36
+ Если задача — статус задания Primo, источником истины служит API соответствующего Оркестратора: используй диагностические инструменты выше либо `orchestrator_request`, когда известны метод, путь и идентификатор из Swagger/веб-UI/реального ответа. Не угадывай endpoint. Специализированные методы управления реализуют предоставленный mock OpenAPI (`test-v1`); не считай их маршруты подтверждёнными для настоящего Primo. Если схемы нет, найди её в доступных материалах либо запроси недостающую схему. Для повторного опроса заранее определи интервал, конечные статусы и ограничение времени; по таймауту сообщи последний наблюдавшийся статус. Не запускай задание повторно для проверки статуса.
36
37
 
37
38
  Если доступный клиентский `Monitor` умеет ждать локальный процесс или следить за файлом логов, он допустим именно для этой функции. Он не заменяет запрос статуса удалённого задания. Сначала проверь фактическое описание такого инструмента — не делай вывод о его возможностях по имени.
38
39
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Локальный Оркестратор через VPN
4
4
 
5
- Команда `primo-rpa-mcp-hybrid`, запущенная через `npx`, — тот же гибридный режим. Примеры распространения: `examples/claude-code/mcp.hybrid.npx.json` (после публикации npm-пакета) и `mcp.hybrid.archive.json` (готовый `.tgz` в корне проекта). Эти варианты не требуют персонального абсолютного пути или сборки пользователем; нужен Node.js >= 22. До публикации не предлагай запуск по имени как уже работающий способ. Skill копируется отдельно в `.claude/skills/primo-rpa` проекта.
5
+ Команда `primo-rpa-mcp-hybrid`, запущенная через `npx`, — тот же гибридный режим. Примеры распространения: `examples/claude-code/mcp.hybrid.npx.json` (опубликованный npm-пакет версии 0.2.0) и `mcp.hybrid.archive.json` (готовый `.tgz` в корне проекта). Эти варианты не требуют персонального абсолютного пути или сборки пользователем; нужен Node.js >= 22. Skill копируется отдельно в `.claude/skills/primo-rpa` проекта.
6
6
 
7
7
  Если `.mcp.json` запускает `build/hybrid.js` через `type:"stdio"`, все `orchestrator_*` выполняются на компьютере клиента, остальные инструменты — на VPS. Реквизиты Оркестратора остаются локально в `env.PRIMO_ORCHESTRATOR_CONNECTIONS` (строка JSON с именованными подключениями); на VPS передаётся только MCP-токен из `PRIMO_MCP_REMOTE_TOKEN`. Адрес VPS задаёт `PRIMO_MCP_REMOTE_URL`. В инструменты передавай `connection:"production"`, не пароль.
8
8
 
@@ -6,6 +6,19 @@
6
6
 
7
7
  Предоставленный OpenAPI явно обозначен как mock с условными маршрутами. Девять методов ниже реализуют именно его и требуют `apiProfile:"test-v1"`. Для настоящего Primo используй `orchestrator_request` с методом, `apiPath` и телом из Swagger целевой версии; не подставляй тестовые пути автоматически. Если пользователь просит управление настоящим Primo, а его контракт неизвестен, получи Swagger до вызова мутации.
8
8
 
9
+ ## Диагностика по маршрутам веб-UI
10
+
11
+ Снимок веб-UI от 2026-10-08 встроен в `orchestrator_api_catalog`: 488 маршрутов, поиск по `search`, `section`, `method`, пагинация `offset`/`limit`. Неполные шаблоны не являются готовыми запросами; не угадывай параметры и схемы тел.
12
+
13
+ Для чтения используй специализированные инструменты **без test-v1**:
14
+
15
+ - `orchestrator_list_launches({connection:"production", pageNumber:0, pageSize:20})` — запуски, исходная структура ответа.
16
+ - `orchestrator_get_operation_events({connection:"production", operationKey:"KEY_FROM_RESPONSE", pageNumber:0, pageSize:100})` — лог запуска.
17
+ - `orchestrator_list_project_versions({connection:"production", rootId:26})` — `noactiveversions`; 26 — указанный пользователем корень arshin_rpa.
18
+ - `orchestrator_get_project_variables({connection:"production", projectId:VERSION_ID})` — переменные версии из ответа списка версий, а не ID корня.
19
+
20
+ Сначала прочитай фактический ответ, затем возьми operationKey или ID версии; не придумывай поля. Пагинация с нуля, размер страницы по умолчанию 100, максимум MCP 1000. Инструменты не запускают роботов. Для остальных методов `orchestrator_request` принимает подтверждённые пути Swagger/веб-UI; каталог не доказывает совместимость других версий API.
21
+
9
22
  ## Подключение и авторизация
10
23
 
11
24
  Предпочитай личное именованное подключение из `X-Primo-Orchestrator-Connections` в `.mcp.json`. Заголовок содержит читаемую JSON-строку либо Base64/Base64url от UTF-8 JSON той же формы, что `PRIMO_ORCHESTRATOR_CONNECTIONS`. Реквизиты можно редактировать прямо в `.mcp.json`; отдельный файл и helper необязательны. Значение `headers["X-Primo-Orchestrator-Connections"]` должно быть строкой, не объектом. Внутренние кавычки и обратные слеши экранируй по правилам JSON. Для Unicode используй JSON escapes или Base64; прямой заголовок принимает ASCII. Его параметры действуют только для этого запроса и не меняют окружение VPS. Персональная карта полностью заменяет серверную: неизвестное имя не переключает клиента на учётные данные владельца.
package/README.md CHANGED
@@ -4,7 +4,7 @@ MCP-сервер для разработки роботов **Primo RPA на Jav
4
4
 
5
5
  ## Установка и подключение
6
6
 
7
- Для Оркестратора через корпоративный VPN используйте локальный гибридный клиент: команда `primo-rpa-mcp-hybrid` направляет все `orchestrator_*` с компьютера пользователя, остальные инструменты — на VPS. Готовые конфиги без персональных путей и инструкции по передаче архива/публикации в npm: [распространение клиента](docs/distribution.md). Нужен Node.js >= 22. Пример через npm заработает после публикации пакета; до неё используйте вариант с `.tgz`.
7
+ Для Оркестратора через корпоративный VPN используйте локальный гибридный клиент: команда `primo-rpa-mcp-hybrid` направляет все `orchestrator_*` с компьютера пользователя, остальные инструменты — на VPS. Готовые конфиги без персональных путей и инструкции по передаче архива/публикации в npm: [распространение клиента](docs/distribution.md). Нужен Node.js >= 22. Конфигурация для версии `primo-rpa-mcp@0.2.1`: используйте пример с `npx`; вариант с `.tgz` также доступен.
8
8
 
9
9
  Ниже описан отдельный режим полностью локального MCP с файловыми путями:
10
10
 
@@ -89,7 +89,12 @@ Node.js >= 22. Сервер работает через stdio; диагност
89
89
  | `diagnose_error` | Поиск источников по сообщению ошибки; возвращает кандидаты, не подтверждённый диагноз |
90
90
  | `orchestrator_login` | Авторизация; поддерживает именованные подключения |
91
91
  | `orchestrator_upload_project` | Загрузка ZIP и публикация проекта |
92
- | `orchestrator_request` | Запрос к API по пути из Swagger вашего Оркестратора |
92
+ | `orchestrator_request` | Запрос по подтверждённому пути из Swagger или веб-UI |
93
+ | `orchestrator_api_catalog` | Поиск в 488 маршрутах из снимка веб-UI |
94
+ | `orchestrator_list_launches` | Последние запуски с пагинацией с нуля |
95
+ | `orchestrator_get_operation_events` | Лог запуска по operationKey |
96
+ | `orchestrator_list_project_versions` | Версии по ID корня проекта (noactiveversions) |
97
+ | `orchestrator_get_project_variables` | Переменные конкретной версии проекта |
93
98
 
94
99
  ## Подбор CSS-селекторов по сохранённой странице
95
100
 
@@ -263,9 +268,22 @@ Helper сохраняет другие MCP-серверы и заголовок
263
268
 
264
269
  ## Управление Оркестратором по тестовому OpenAPI
265
270
 
271
+ Диагностические инструменты используют пути из предоставленного снимка веб-UI от 2026-10-08 и **не требуют `apiProfile:test-v1`**. Подключение и вход остаются прежними; схемы ответов не были предоставлены, поэтому возвращается исходная структура `data` с маскированием учётных данных. Совместимость с другими версиями инстанса требует проверки.
272
+
273
+ ```js
274
+ orchestrator_list_launches({connection:"production", pageNumber:0, pageSize:20})
275
+ orchestrator_get_operation_events({connection:"production", operationKey:"KEY_FROM_LAUNCH", pageNumber:0, pageSize:100})
276
+ orchestrator_list_project_versions({connection:"production", rootId:26})
277
+ orchestrator_get_project_variables({connection:"production", projectId:VERSION_ID_FROM_RESPONSE})
278
+ ```
279
+
280
+ Для `arshin_rpa` пользователь указал ID корня 26; он не зашит в инструмент и не заменяет ID версии. Номер страницы начинается с 0; по умолчанию 100 записей, максимум MCP 1000 (целевой API может иметь меньший лимит). Сортировка последних запусков определяется сервером; MCP не пересортировывает ответ и не придумывает поля ответа.
281
+
282
+ `orchestrator_api_catalog({section:"RobotLogs", search:"OperationEvents", method:"GET"})` ищет по встроенному каталогу всех 488 путей. `limit` (1–100, по умолчанию 30) и `offset` позволяют листать результаты; `nextOffset` указывает следующую страницу. Пути уже включают `/api`. Шаблоны `{param}`, `//`, `${...}` сохранены как в исходнике: каталог не даёт схем тел и не восстанавливает потерянные параметры. Для прочих запросов нужны реальные параметры и тело из целевого API; каталог сам ничего не вызывает. Маршруты из файла доступны через существующий `orchestrator_request` после заполнения подтверждённых параметров.
283
+
266
284
  Добавлены `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`.
267
285
 
268
- Предоставленный OpenAPI явно помечен как mock с условными маршрутами. Эти инструменты требуют `apiProfile: "test-v1"` и явное подключение (`connection` либо `baseUrl` и `bearerToken`). Совместимость с настоящим Primo Оркестратором не подтверждена. Его методы вызывайте по проверенному Swagger через `orchestrator_request`.
286
+ Предоставленный OpenAPI явно помечен как mock с условными маршрутами. Эти инструменты требуют `apiProfile: "test-v1"` и явное подключение (`connection` либо `baseUrl` и `bearerToken`). Совместимость с настоящим Primo Оркестратором не подтверждена. Для чтения запусков, логов, версий и переменных используйте диагностические инструменты ниже; остальные методы вызывайте через `orchestrator_request` по проверенному Swagger или фактическим запросам веб-UI.
269
287
 
270
288
  Для входа в тестовый API передайте `orchestrator_login` профиль `test-v1`: `userName` преобразуется в поле `login`, запрос идёт на `/api/Account`, токен именованного подключения берётся из `token` (либо настроенного `tokenField`). Прежняя авторизация `/api/account` сохраняется по умолчанию (`official-upload`).
271
289
 
package/build/hybrid.js CHANGED
@@ -11,8 +11,8 @@ async function main() {
11
11
  if (url.protocol !== 'https:' || url.username || url.password || url.hash || !token || /[\r\n\0]/.test(token))
12
12
  throw new Error('Invalid remote configuration');
13
13
  const localServer = createPrimoServer({ fileMode: 'content' });
14
- const local = new Client({ name: 'primo-local-orchestrator', version: '0.2.0' });
15
- const remote = new Client({ name: 'primo-remote-tools', version: '0.2.0' });
14
+ const local = new Client({ name: 'primo-local-orchestrator', version: '0.2.1' });
15
+ const remote = new Client({ name: 'primo-remote-tools', version: '0.2.1' });
16
16
  const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
17
17
  let bridge;
18
18
  const close = async () => {
@@ -10,7 +10,7 @@ export async function createHybridServer(local, remote) {
10
10
  const remoteTools = remoteList.tools.filter(tool => !tool.name.startsWith('orchestrator_'));
11
11
  const localNames = new Set(localTools.map(tool => tool.name));
12
12
  const remoteNames = new Set(remoteTools.map(tool => tool.name));
13
- const server = new Server({ name: 'primo-rpa-mcp', version: '0.2.0' }, {
13
+ const server = new Server({ name: 'primo-rpa-mcp', version: '0.2.1' }, {
14
14
  capabilities: { tools: {} },
15
15
  instructions: CONTENT_INSTRUCTIONS
16
16
  .replace('This MCP runs remotely.', 'This MCP uses a local stdio bridge to a hosted MCP.')
package/build/server.js CHANGED
@@ -6,6 +6,7 @@ import { registerExtractSchema } from "./tools/extractSchema.js";
6
6
  import { registerPackProject } from "./tools/packProject.js";
7
7
  import { registerDocsSearch } from "./tools/docsSearch.js";
8
8
  import { registerOrchestratorManagement } from "./tools/orchestratorManagement.js";
9
+ import { registerOrchestratorCatalog } from "./tools/orchestratorCatalog.js";
9
10
  import { registerOrchestrator } from "./tools/orchestrator.js";
10
11
  import { registerValidateProject } from "./tools/validateProject.js";
11
12
  import { registerAnalyzeProject } from "./tools/analyzeProject.js";
@@ -13,13 +14,14 @@ import { registerProcessEditing } from "./tools/processEditing.js";
13
14
  import { registerSuggestSelectors } from "./tools/suggestSelectors.js";
14
15
  import { registerContentTools } from "./tools/contentTools.js";
15
16
  import { installAccessGate } from "./access/mcp.js";
16
- export const CONTENT_INSTRUCTIONS = "This MCP runs remotely. Projects stay on the client computer. Read local files with Claude Code local tools and send explicit files snapshots {path: relative POSIX path, content, encoding: utf8 or base64}. Paths are labels within the snapshot, never local absolute paths or server filesystem access. File tools return fileChanges; they never save to the client. Before saving locally, compare the current exact-byte SHA-256 to expectedHash; null requires the file to be absent. Verify saved bytes match sha256. On conflict reread and preview again. patch_process apply=true only prepares replacement content; applied=false and localFilesWritten=false remain true until the client saves. Validate using a fresh snapshot of the saved local files. Only upload files required for the task; never include credentials or .git. analyze_project requires an analyzer installed on this server. Structural checks never execute robots. Personal named Orchestrator connections come from the authenticated request X-Primo-Orchestrator-Connections header; use their connection name in tools instead of passing credentials as tool arguments. Dedicated Orchestrator management tools require apiProfile=test-v1 and implement an illustrative test contract. Verify target Swagger before use; production routes must be confirmed.";
17
+ export const CONTENT_INSTRUCTIONS = "This MCP runs remotely. Projects stay on the client computer. Read local files with Claude Code local tools and send explicit files snapshots {path: relative POSIX path, content, encoding: utf8 or base64}. Paths are labels within the snapshot, never local absolute paths or server filesystem access. File tools return fileChanges; they never save to the client. Before saving locally, compare the current exact-byte SHA-256 to expectedHash; null requires the file to be absent. Verify saved bytes match sha256. On conflict reread and preview again. patch_process apply=true only prepares replacement content; applied=false and localFilesWritten=false remain true until the client saves. Validate using a fresh snapshot of the saved local files. Only upload files required for the task; never include credentials or .git. analyze_project requires an analyzer installed on this server. Structural checks never execute robots. Personal named Orchestrator connections come from the authenticated request X-Primo-Orchestrator-Connections header; use their connection name in tools instead of passing credentials as tool arguments. Legacy Orchestrator management tools require apiProfile=test-v1 and implement an illustrative test contract. Diagnostic tools (list_launches, get_operation_events, list_project_versions, get_project_variables) use user-supplied UI routes without test-v1. orchestrator_api_catalog searches the full UI route snapshot; incomplete templates require actual parameters and body schemas before orchestrator_request. Compatibility depends on the target version.";
17
18
  export function createPrimoServer(options = {}) {
18
19
  const contentMode = options.fileMode === "content";
19
- const server = new McpServer({ name: "primo-rpa-mcp", version: "0.2.0" }, contentMode ? { instructions: CONTENT_INSTRUCTIONS } : {});
20
+ const server = new McpServer({ name: "primo-rpa-mcp", version: "0.2.1" }, contentMode ? { instructions: CONTENT_INSTRUCTIONS } : {});
20
21
  if (options.access)
21
22
  installAccessGate(server, options.access);
22
23
  registerOrchestratorManagement(server);
24
+ registerOrchestratorCatalog(server);
23
25
  if (contentMode) {
24
26
  registerContentTools(server);
25
27
  registerDocsSearch(server);
@@ -3,7 +3,7 @@ import { readFile } from "node:fs/promises";
3
3
  import { OrchestratorClient, resolveConnection, rememberToken } from "../orchestrator/client.js";
4
4
  /** Publication uses the official UploadProjectWithOrchApi contract.
5
5
  * The explicit test-v1 login profile uses the user-supplied mock OpenAPI.
6
- * Other production routes must be confirmed by the target installation's Swagger.
6
+ * Other production routes must be confirmed by Swagger or evidence from the target UI.
7
7
  */
8
8
  async function parseJsonSafe(res) {
9
9
  const text = await res.text();
@@ -195,16 +195,15 @@ export function registerOrchestrator(server) {
195
195
  server.registerTool("orchestrator_request", {
196
196
  title: "Произвольный запрос к API Оркестратора",
197
197
  description: "Generic-клиент для эндпоинтов Оркестратора, которых нет среди готовых инструментов " +
198
- "(например управление роботами/заданиями/очередями). ВАЖНО: полный список таких " +
199
- "эндпоинтов не публикуется — используйте только пути, которые вы сами нашли в " +
200
- "Swagger вашего инстанса Оркестратора (руководство «Открытие Swagger» из комплекта " +
201
- "поставки). Не угадывайте пути.",
198
+ "(например управление роботами/заданиями/очередями). Используйте orchestrator_api_catalog " +
199
+ "для поиска путей из снимка веб-UI либо Swagger вашего инстанса. Шаблоны каталога " +
200
+ "могут быть неполными: нужны фактические параметры и схема тела. Не угадывайте их.",
202
201
  inputSchema: {
203
202
  connection: z.string().optional().describe("Имя персонального подключения из HTTP-заголовка либо серверного PRIMO_ORCHESTRATOR_CONNECTIONS"),
204
203
  baseUrl: z.string().optional(),
205
204
  bearerToken: z.string().optional(),
206
205
  method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
207
- apiPath: z.string().describe('Путь, начиная с "/api/...", как в вашем Swagger'),
206
+ apiPath: z.string().describe('Путь, начиная с "/api/...", по Swagger или подтверждённому запросу веб-UI'),
208
207
  jsonBody: z.record(z.string(), z.unknown()).optional(),
209
208
  },
210
209
  }, async (params, extra) => {
@@ -0,0 +1,36 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { z } from 'zod';
3
+ export function registerOrchestratorCatalog(server) {
4
+ server.registerTool('orchestrator_api_catalog', {
5
+ title: 'Каталог API Оркестратора из веб-UI',
6
+ description: 'Поиск путей в пользовательском снимке веб-UI от 2026-10-08. Не делает HTTP-запросов. Пути уже включают /api. Шаблоны с {param}, //, ${...} могут быть неполными; это справочник маршрутов, а не схем тел или ответов. Для вызова нужны фактические параметры целевого инстанса.',
7
+ inputSchema: {
8
+ search: z.string().max(512).optional().describe('Подстрока пути, раздела или функции UI; без учёта регистра'),
9
+ section: z.string().max(100).optional().describe('Точное имя раздела без учёта регистра, например RobotLogs'),
10
+ method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional(),
11
+ offset: z.number().int().safe().min(0).default(0),
12
+ limit: z.number().int().min(1).max(100).default(30),
13
+ },
14
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
15
+ }, async ({ search, section, method, offset, limit }) => {
16
+ try {
17
+ const catalog = JSON.parse(await readFile(new URL('../../data/orchestrator-api-paths.json', import.meta.url), 'utf8'));
18
+ const query = search?.trim().toLowerCase();
19
+ const entries = catalog.entries.filter(entry => (!section || entry.section.toLowerCase() === section.toLowerCase())
20
+ && (!method || entry.method === method)
21
+ && (!query || `${entry.section} ${entry.pathTemplate} ${entry.uiFunction}`.toLowerCase().includes(query)));
22
+ const end = offset + limit;
23
+ const structuredContent = {
24
+ source: catalog.source, sourceDate: catalog.sourceDate, totalRoutes: catalog.entries.length,
25
+ sections: [...new Set(catalog.entries.map(entry => entry.section))],
26
+ matchedRoutes: entries.length, offset, nextOffset: end < entries.length ? end : null,
27
+ notice: 'Извлечение из UI, без схем тел и ответов; неполные шаблоны нельзя вызывать буквально. Совместимость зависит от версии инстанса.',
28
+ entries: entries.slice(offset, end),
29
+ };
30
+ return { content: [{ type: 'text', text: JSON.stringify(structuredContent, null, 2) }], structuredContent };
31
+ }
32
+ catch {
33
+ return { content: [{ type: 'text', text: 'Не удалось загрузить встроенный каталог API Оркестратора' }], isError: true };
34
+ }
35
+ });
36
+ }
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { OrchestratorClient, resolveConnection } from '../orchestrator/client.js';
3
- // Routes below implement the supplied illustrative test-v1 OpenAPI contract,
4
- // not a claim about the production Swagger of a Primo installation.
3
+ // Legacy management routes use the illustrative test-v1 contract.
4
+ // Diagnostic GET routes come from the user-supplied Orchestrator UI extraction.
5
5
  const MIN_INT64 = -(1n << 63n);
6
6
  const MAX_INT64 = (1n << 63n) - 1n;
7
7
  const safeInteger = z.number().int().safe('Нужен безопасный целый JavaScript; значение потеряет точность');
@@ -43,11 +43,12 @@ function redactData(value, secrets) {
43
43
  return value;
44
44
  }
45
45
  export function registerOrchestratorManagement(server) {
46
- function register(name, title, method, fields, request) {
46
+ function register(name, title, method, fields, request, source = 'test-v1') {
47
+ const connectionFields = { connection: common.connection, baseUrl: common.baseUrl, bearerToken: common.bearerToken };
47
48
  server.registerTool(name, {
48
49
  title,
49
- description: `${title}. Только apiProfile=test-v1: маршрут из предоставленного иллюстративного OpenAPI; совместимость с рабочим Оркестратором требует проверки его Swagger. ${method === 'GET' ? '' : 'Изменяет состояние Оркестратора; вызывайте только по запросу пользователя. Автоматических повторов нет.'}`,
50
- inputSchema: { ...common, ...fields },
50
+ description: `${title}. ${source === 'test-v1' ? 'Только apiProfile=test-v1: маршрут из предоставленного иллюстративного OpenAPI; совместимость с рабочим Оркестратором требует проверки его Swagger.' : 'Маршрут из веб-UI Оркестратора (снимок 2026-10-08); возвращает исходную структуру ответа с маскированием учётных данных. Совместимость зависит от версии инстанса.'} ${method === 'GET' ? '' : 'Изменяет состояние Оркестратора; вызывайте только по запросу пользователя. Автоматических повторов нет.'}`,
51
+ inputSchema: { ...(source === 'test-v1' ? common : connectionFields), ...fields },
51
52
  annotations: { readOnlyHint: method === 'GET', destructiveHint: method === 'DELETE', idempotentHint: method !== 'POST', openWorldHint: true },
52
53
  }, async (params, extra) => {
53
54
  let client;
@@ -74,7 +75,7 @@ export function registerOrchestratorManagement(server) {
74
75
  }
75
76
  }
76
77
  const structuredContent = {
77
- apiProfile: 'test-v1', testContract: true, method, apiPath: path,
78
+ ...(source === 'test-v1' ? { apiProfile: 'test-v1', testContract: true } : { routeSource: 'ui-extracted', sourceDate: '2026-10-08', testContract: false }), method, apiPath: path,
78
79
  status: response.status, data: redactData(data, secrets),
79
80
  };
80
81
  return { content: [{ type: 'text', text: JSON.stringify(structuredContent, null, 2) }], structuredContent, isError: !response.ok };
@@ -104,4 +105,27 @@ export function registerOrchestratorManagement(server) {
104
105
  }, ({ robotId, projectId, version, arguments: args }) => ({ path: `/api/Robots/${id(robotId)}`, body: { projectId, ...(version !== undefined ? { version } : {}), ...(args !== undefined ? { arguments: args } : {}) } }));
105
106
  register('orchestrator_get_execution', 'Прочитать статус выполнения', 'GET', { executionId: pathId }, params => ({ path: `/api/Executions/${id(params.executionId)}` }));
106
107
  register('orchestrator_stop_execution', 'Остановить выполнение', 'DELETE', { executionId: pathId }, params => ({ path: `/api/Executions/${id(params.executionId)}` }));
108
+ const pagination = {
109
+ pageNumber: safeInteger.min(0).default(0).describe('Номер страницы с нуля'),
110
+ pageSize: safeInteger.min(1).max(1000).default(100).describe('Размер страницы; лимит MCP 1000, сервер может ограничивать сильнее'),
111
+ };
112
+ const projectId = pathId.refine(value => { try {
113
+ return BigInt(value) > 0n;
114
+ }
115
+ catch {
116
+ return false;
117
+ } }, 'Нужен положительный ID проекта');
118
+ register('orchestrator_list_launches', 'Последние запуски проектов', 'GET', pagination, params => ({ path: `/api/rpaprojectlaunches/all?pageNumber=${params.pageNumber}&pageSize=${params.pageSize}` }), 'ui-extracted');
119
+ register('orchestrator_get_operation_events', 'Лог запуска по operationKey', 'GET', {
120
+ operationKey: z.string().min(1).max(512)
121
+ .refine(value => value.trim() === value && !/[\u0000-\u001f\u007f]/.test(value) && value !== '.' && value !== '..', 'Нужен непустой operationKey без пробелов по краям и управляющих символов')
122
+ .describe('operationKey из ответа списка запусков; идентификатор передаётся как один кодированный сегмент пути'),
123
+ ...pagination,
124
+ }, params => ({ path: `/api/robotlogs/OperationEvents/${id(params.operationKey)}?pageNumber=${params.pageNumber}&pageSize=${params.pageSize}` }), 'ui-extracted');
125
+ register('orchestrator_list_project_versions', 'Версии проекта (noactiveversions)', 'GET', {
126
+ rootId: projectId.describe('ID корня проекта, а не версии; для arshin_rpa пользователь указал 26'),
127
+ }, params => ({ path: `/api/rpaprojects/${id(params.rootId)}/noactiveversions` }), 'ui-extracted');
128
+ register('orchestrator_get_project_variables', 'Переменные версии проекта', 'GET', {
129
+ projectId: projectId.describe('ID конкретной версии из ответа списка версий; не подставляйте ID корня автоматически'),
130
+ }, params => ({ path: `/api/rpaprojectvariables/project/${id(params.projectId)}` }), 'ui-extracted');
107
131
  }