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.
- package/.claude/skills/primo-rpa/SKILL.md +3 -2
- package/.claude/skills/primo-rpa/references/connection.md +1 -1
- package/.claude/skills/primo-rpa/references/orchestrator.md +13 -0
- package/README.md +21 -3
- package/build/hybrid.js +2 -2
- package/build/hybridServer.js +1 -1
- package/build/server.js +4 -2
- package/build/tools/orchestrator.js +5 -6
- package/build/tools/orchestratorCatalog.js +36 -0
- package/build/tools/orchestratorManagement.js +30 -6
- package/data/orchestrator-api-paths.json +2935 -0
- package/docs/distribution.md +9 -9
- package/examples/claude-code/mcp.hybrid.archive.json +2 -2
- package/examples/claude-code/mcp.hybrid.npx.json +2 -2
- package/package.json +2 -1
|
@@ -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
|
-
| Получить
|
|
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` (
|
|
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.
|
|
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` | Запрос
|
|
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 Оркестратором не подтверждена.
|
|
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.
|
|
15
|
-
const remote = new Client({ name: 'primo-remote-tools', version: '0.2.
|
|
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 () => {
|
package/build/hybridServer.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
"
|
|
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/...",
|
|
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
|
-
//
|
|
4
|
-
//
|
|
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
|
}
|