mlspace-plugin 0.3.1__tar.gz → 0.3.3__tar.gz
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.
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/.env.example +3 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/INSTALL.md +2 -2
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/INSTALL_AGENT.md +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/PKG-INFO +28 -8
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/README.md +27 -7
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/RELEASE.md +5 -5
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/.claude-plugin/plugin.json +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/.codex-plugin/plugin.json +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/.mcp.json +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/mcp.json +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/plugin.json +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-diagnose-data-transfer/SKILL.md +20 -2
- mlspace_plugin-0.3.3/plugin/skills/mlspace-stage-s3-to-nfs/SKILL.md +68 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/pyproject.toml +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/__init__.py +2 -1
- mlspace_plugin-0.3.3/src/mlspace_mcp/__main__.py +125 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/client_setup.py +32 -32
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/config.py +4 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/formatting.py +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/init_cli.py +81 -66
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/native_plugins.py +15 -15
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/registry.py +47 -3
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/server.py +40 -2
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/setup_conflicts.py +14 -14
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/setup_ui.py +4 -4
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/setup_verification.py +10 -10
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tls.py +7 -6
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/data_transfer.py +35 -15
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/docker_registry.py +11 -3
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/workspaces.py +6 -2
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_client_setup.py +7 -7
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_formatting.py +11 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_init_cli.py +3 -3
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_native_plugins.py +1 -1
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_onboarding_init.py +9 -9
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_opencode_journey.py +4 -4
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_registry.py +2 -1
- mlspace_plugin-0.3.3/tests/test_secret_disclosure.py +91 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_setup_conflicts.py +4 -4
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_setup_native_journey.py +4 -4
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_setup_verification.py +3 -3
- mlspace_plugin-0.3.3/tests/test_user_agent.py +59 -0
- mlspace_plugin-0.3.1/plugin/skills/mlspace-stage-s3-to-nfs/SKILL.md +0 -45
- mlspace_plugin-0.3.1/src/mlspace_mcp/__main__.py +0 -125
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/.agents/plugins/marketplace.json +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/.claude-plugin/marketplace.json +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/.gitignore +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/AGENTS.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/CONTRIBUTING.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/LICENSE +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/README.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-call-deployed-model-predict/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-deploy-inference-service/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-diagnose-failed-training-job/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-diagnose-job-launch-rejection/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-diagnose-unhealthy-inference/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-discover-launchable-resources/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-launch-training-job/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-list-running-jobs/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-resume-notebook-and-set-autoshutdown/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-transfer-compute-node/SKILL.md +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/scripts/build_plugin.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/scripts/demo_multi_workspace.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/scripts/gen_body_schemas.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/scripts/gen_plugin.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/scripts/mcp_call.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/scripts/serve_stdio.sh +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/scripts/serve_stdio_dryrun.sh +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/_status.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/auth.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/bodyspec.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/client.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/errors.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/job_hooks.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/jsonc.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/overview.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/resource_refs.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/spec/body_schemas.json +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/spec/openapi.json +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/__init__.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/allocations.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/async_inference.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/build_image.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/dalle.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/inference.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/jobs.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/notebooks.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/queues.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/resources.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/tools/tensorboards.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/src/mlspace_mcp/workspace_context.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/conftest.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/specutil.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_allocations.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_artifact_sync.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_async_inference.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_auth.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_autofill.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_bodyspec.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_build_image.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_client.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_configs_shrink.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_credential_pointer.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_dalle.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_data_transfer.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_docker_registry.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_drift.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_dry_run.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_dry_run_fidelity.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_env_file.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_errors.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_false_success.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_integration.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_job_status.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_jobs.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_log_normalisation.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_mcp_error_contract.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_native_cli_integration.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_notebooks.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_onboarding_tls.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_overview.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_plugin_bundle.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_plugin_cli.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_plugin_release.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_preflight.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_queue_scope.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_queues.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_resource_refs.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_resources.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_route_confusion.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_setup_ui.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_skills.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_tensorboards.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_workspace_context.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_workspaces.py +0 -0
- {mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/tests/test_wrapper_hardening.py +0 -0
|
@@ -30,6 +30,9 @@ MLSPACE_BASE_URL=https://api.ai.cloud.ru
|
|
|
30
30
|
MLSPACE_READONLY=false # true hides and blocks all 58 write actions
|
|
31
31
|
# when writes are enabled, destructive actions
|
|
32
32
|
# additionally require confirm=true
|
|
33
|
+
# Account-wide password rotation is blocked unless the operator explicitly opts in.
|
|
34
|
+
# Enable only for an approved rotation, then disable and restart the MCP server.
|
|
35
|
+
# MLSPACE_ALLOW_REGISTRY_PASSWORD_ROTATION=false
|
|
33
36
|
MLSPACE_TRANSPORT=streamable-http # streamable-http | stdio
|
|
34
37
|
MLSPACE_HOST=127.0.0.1 # loopback only (no server-side auth in v1)
|
|
35
38
|
MLSPACE_PORT=8000
|
|
@@ -21,7 +21,7 @@ mlspace-plugin setup
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Если пакет уже установлен: `uv tool install --force .`.
|
|
24
|
-
При установке из wheel: `uv tool install /путь/к/mlspace_plugin-0.3.
|
|
24
|
+
При установке из wheel: `uv tool install /путь/к/mlspace_plugin-0.3.3-py3-none-any.whl`.
|
|
25
25
|
Не используйте editable-установку из `/tmp` для постоянной работы.
|
|
26
26
|
Далее команды показаны для PyPI. После установки исходников или wheel через
|
|
27
27
|
`uv tool install` заменяйте `uvx mlspace-plugin@latest` на `mlspace-plugin`,
|
|
@@ -43,7 +43,7 @@ mlspace-plugin setup
|
|
|
43
43
|
|
|
44
44
|
Если настройка клиента не завершилась, проверенные ключи остаются сохранёнными.
|
|
45
45
|
Мастер перечислит установленные клиенты; устраните причину и выполните напечатанную
|
|
46
|
-
команду
|
|
46
|
+
команду после «Повторите команду». Она сохраняет выбор клиентов, включая незавершённые подключения.
|
|
47
47
|
|
|
48
48
|
Откройте новую сессию выбранного клиента; если MCP не появился, перезапустите клиент.
|
|
49
49
|
Сервер запускается клиентом автоматически. Первый запрос:
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
запустить ту же команду без `--non-interactive`, сохранив endpoint, путь и выбор клиентов.
|
|
42
42
|
Для конфликта нативного плагина Claude/Codex разберите указанный несекретный путь;
|
|
43
43
|
не удаляйте чужую интеграцию автоматически.
|
|
44
|
-
При частичном успехе сообщите, какие этапы завершены, и используйте команду
|
|
44
|
+
При частичном успехе сообщите, какие этапы завершены, и используйте команду после «Повторите команду»
|
|
45
45
|
из ошибки: она сохраняет выбор незавершённых подключений. Для автоматизации
|
|
46
46
|
добавьте прежние `--non-interactive` и `--workspace`.
|
|
47
47
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mlspace-plugin
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Cloud.ru MLSpace plugin: MCP server, agent skills and setup
|
|
5
5
|
Project-URL: Repository, https://github.com/noesskeetit/mlspace-plugin
|
|
6
6
|
Project-URL: Issues, https://github.com/noesskeetit/mlspace-plugin/issues
|
|
@@ -290,15 +290,21 @@ write-запросов подаются параметром `body: dict`; об
|
|
|
290
290
|
Для других агентов предусмотрены Agent Plugins 1.0, Agent Skills и обычное
|
|
291
291
|
MCP-подключение; поддержку конкретного загрузчика нужно проверять отдельно.
|
|
292
292
|
Пошаговые сценарии поставляются только скиллами плагина; сервер отдаёт общие правила
|
|
293
|
-
в instructions.
|
|
293
|
+
в instructions. Ключевые правила подачи ответа также включены в описания инструментов
|
|
294
|
+
для клиентов, которые не передают модели instructions сервера.
|
|
295
|
+
`tests/test_skills.py` сверяет скиллы с реальными инструментами.
|
|
294
296
|
|
|
295
297
|
---
|
|
296
298
|
|
|
297
299
|
## Безопасность
|
|
298
300
|
|
|
299
301
|
- **Гейт подтверждения**: 16 необратимых действий (удаления, отзыв доступа,
|
|
300
|
-
отмена переноса, ротация пароля реестра) требуют `confirm=true`.
|
|
301
|
-
|
|
302
|
+
отмена переноса, ротация пароля реестра) требуют `confirm=true`.
|
|
303
|
+
- **Смена пароля Registry выключена по умолчанию**, поскольку затрагивает личный
|
|
304
|
+
аккаунт и уже работающие подключения. После согласования ротации оператор может
|
|
305
|
+
задать `MLSPACE_ALLOW_REGISTRY_PASSWORD_ROTATION=true` в конфигурации сервера и
|
|
306
|
+
перезапустить MCP. `setup` не включает этот параметр. После операции выключите его
|
|
307
|
+
и снова перезапустите MCP. Флаг инструмента `confirm=true` не обходит этот запрет.
|
|
302
308
|
- **Режим read-only** (`MLSPACE_READONLY=true`): все 58 write-действий исчезают
|
|
303
309
|
из `action`-перечня — модель их не видит — и блокируются в рантайме как
|
|
304
310
|
страховка. По умолчанию **выключен**: сервер задуман как рабочий инструмент, а
|
|
@@ -313,13 +319,27 @@ MCP-подключение; поддержку конкретного загру
|
|
|
313
319
|
общего сервера. Жизненный цикл воркспейса — только через консоль.
|
|
314
320
|
- **Сеть**: HTTP-транспорт отказывается слушать не-loopback адрес (в v1 нет
|
|
315
321
|
серверной аутентификации).
|
|
316
|
-
- **Секреты в ответах** (пароль
|
|
322
|
+
- **Секреты в ответах** (пароль Registry, API key воркспейса) по умолчанию
|
|
323
|
+
маскируются. Для задачи, которой нужно реальное значение, действия
|
|
324
|
+
`mlspace_docker_registry(action="generate_password")` и
|
|
325
|
+
`mlspace_workspaces(action="get_api_key")` принимают `reveal_secret=true`
|
|
326
|
+
вместе с `confirm=true`. Это раскрывает секрет в результате инструмента:
|
|
327
|
+
он становится доступен модели и может сохраниться в истории MCP-клиента.
|
|
328
|
+
Флаг действует только на эти операции, а не отключает маскирование глобально.
|
|
329
|
+
`generate_password` меняет пароль; агент должен получить разрешение на ротацию
|
|
330
|
+
и передать `reveal_secret=true` сразу, если новый пароль нужен для `docker login`.
|
|
331
|
+
Для входа используйте `--password-stdin`; не помещайте пароль в обычный ответ,
|
|
332
|
+
документацию или репозиторий. Обычным MCP-запросам ручное получение ключа не нужно.
|
|
317
333
|
|
|
318
334
|
> Важно про `confirm`: этот флаг ставит **сам агент** в том же вызове. Это защита от
|
|
319
335
|
> случайного действия, а **не** human-in-the-loop. Подтверждение человеком обеспечивает
|
|
320
|
-
>
|
|
321
|
-
>
|
|
322
|
-
>
|
|
336
|
+
> клиент, если в нём настроено согласование операций; `destructiveHint` — лишь подсказка.
|
|
337
|
+
> `reveal_secret` также является явным запросом агента, а не отдельным окном согласия.
|
|
338
|
+
> `MLSPACE_READONLY=true` блокирует изменения, включая ротацию пароля, но не чтение
|
|
339
|
+
> workspace API key с явным раскрытием. Это не режим запрета экспорта секретов.
|
|
340
|
+
> Агент с доступом к изменению конфигурации сервера способен изменить и его ограничения;
|
|
341
|
+
> настройки MCP не заменяют права доступа в API и клиенте. После явного раскрытия секрета
|
|
342
|
+
> сервер не может гарантировать, что модель не повторит его в своём ответе.
|
|
323
343
|
|
|
324
344
|
---
|
|
325
345
|
|
|
@@ -239,15 +239,21 @@ write-запросов подаются параметром `body: dict`; об
|
|
|
239
239
|
Для других агентов предусмотрены Agent Plugins 1.0, Agent Skills и обычное
|
|
240
240
|
MCP-подключение; поддержку конкретного загрузчика нужно проверять отдельно.
|
|
241
241
|
Пошаговые сценарии поставляются только скиллами плагина; сервер отдаёт общие правила
|
|
242
|
-
в instructions.
|
|
242
|
+
в instructions. Ключевые правила подачи ответа также включены в описания инструментов
|
|
243
|
+
для клиентов, которые не передают модели instructions сервера.
|
|
244
|
+
`tests/test_skills.py` сверяет скиллы с реальными инструментами.
|
|
243
245
|
|
|
244
246
|
---
|
|
245
247
|
|
|
246
248
|
## Безопасность
|
|
247
249
|
|
|
248
250
|
- **Гейт подтверждения**: 16 необратимых действий (удаления, отзыв доступа,
|
|
249
|
-
отмена переноса, ротация пароля реестра) требуют `confirm=true`.
|
|
250
|
-
|
|
251
|
+
отмена переноса, ротация пароля реестра) требуют `confirm=true`.
|
|
252
|
+
- **Смена пароля Registry выключена по умолчанию**, поскольку затрагивает личный
|
|
253
|
+
аккаунт и уже работающие подключения. После согласования ротации оператор может
|
|
254
|
+
задать `MLSPACE_ALLOW_REGISTRY_PASSWORD_ROTATION=true` в конфигурации сервера и
|
|
255
|
+
перезапустить MCP. `setup` не включает этот параметр. После операции выключите его
|
|
256
|
+
и снова перезапустите MCP. Флаг инструмента `confirm=true` не обходит этот запрет.
|
|
251
257
|
- **Режим read-only** (`MLSPACE_READONLY=true`): все 58 write-действий исчезают
|
|
252
258
|
из `action`-перечня — модель их не видит — и блокируются в рантайме как
|
|
253
259
|
страховка. По умолчанию **выключен**: сервер задуман как рабочий инструмент, а
|
|
@@ -262,13 +268,27 @@ MCP-подключение; поддержку конкретного загру
|
|
|
262
268
|
общего сервера. Жизненный цикл воркспейса — только через консоль.
|
|
263
269
|
- **Сеть**: HTTP-транспорт отказывается слушать не-loopback адрес (в v1 нет
|
|
264
270
|
серверной аутентификации).
|
|
265
|
-
- **Секреты в ответах** (пароль
|
|
271
|
+
- **Секреты в ответах** (пароль Registry, API key воркспейса) по умолчанию
|
|
272
|
+
маскируются. Для задачи, которой нужно реальное значение, действия
|
|
273
|
+
`mlspace_docker_registry(action="generate_password")` и
|
|
274
|
+
`mlspace_workspaces(action="get_api_key")` принимают `reveal_secret=true`
|
|
275
|
+
вместе с `confirm=true`. Это раскрывает секрет в результате инструмента:
|
|
276
|
+
он становится доступен модели и может сохраниться в истории MCP-клиента.
|
|
277
|
+
Флаг действует только на эти операции, а не отключает маскирование глобально.
|
|
278
|
+
`generate_password` меняет пароль; агент должен получить разрешение на ротацию
|
|
279
|
+
и передать `reveal_secret=true` сразу, если новый пароль нужен для `docker login`.
|
|
280
|
+
Для входа используйте `--password-stdin`; не помещайте пароль в обычный ответ,
|
|
281
|
+
документацию или репозиторий. Обычным MCP-запросам ручное получение ключа не нужно.
|
|
266
282
|
|
|
267
283
|
> Важно про `confirm`: этот флаг ставит **сам агент** в том же вызове. Это защита от
|
|
268
284
|
> случайного действия, а **не** human-in-the-loop. Подтверждение человеком обеспечивает
|
|
269
|
-
>
|
|
270
|
-
>
|
|
271
|
-
>
|
|
285
|
+
> клиент, если в нём настроено согласование операций; `destructiveHint` — лишь подсказка.
|
|
286
|
+
> `reveal_secret` также является явным запросом агента, а не отдельным окном согласия.
|
|
287
|
+
> `MLSPACE_READONLY=true` блокирует изменения, включая ротацию пароля, но не чтение
|
|
288
|
+
> workspace API key с явным раскрытием. Это не режим запрета экспорта секретов.
|
|
289
|
+
> Агент с доступом к изменению конфигурации сервера способен изменить и его ограничения;
|
|
290
|
+
> настройки MCP не заменяют права доступа в API и клиенте. После явного раскрытия секрета
|
|
291
|
+
> сервер не может гарантировать, что модель не повторит его в своём ответе.
|
|
272
292
|
|
|
273
293
|
---
|
|
274
294
|
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
`uv lock` и `uv run python scripts/gen_plugin.py`. Обновите примеры имён wheel/ZIP
|
|
8
8
|
в инструкциях, если версия присутствует в имени файла.
|
|
9
9
|
2. Выполните проверки из `CONTRIBUTING.md` на Linux и macOS.
|
|
10
|
-
3. Соберите пакет (в командах ниже замените 0.3.
|
|
10
|
+
3. Соберите пакет (в командах ниже замените 0.3.3 на выпускаемую версию):
|
|
11
11
|
|
|
12
12
|
```sh
|
|
13
|
-
uv build --out-dir dist/release-0.3.
|
|
14
|
-
uv run python scripts/build_plugin.py --output dist/plugin-release-0.3.
|
|
13
|
+
uv build --out-dir dist/release-0.3.3
|
|
14
|
+
uv run python scripts/build_plugin.py --output dist/plugin-release-0.3.3
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
4. Просмотрите содержимое wheel, sdist и ZIP. В них не должно быть credentials,
|
|
@@ -23,11 +23,11 @@ uv run python scripts/build_plugin.py --output dist/plugin-release-0.3.1
|
|
|
23
23
|
`UV_PUBLISH_TOKEN` средствами вашего хранилища секретов, не аргументом команды:
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
|
-
uv publish --trusted-publishing never dist/release-0.3.
|
|
26
|
+
uv publish --trusted-publishing never dist/release-0.3.3/mlspace_plugin-0.3.3-py3-none-any.whl dist/release-0.3.3/mlspace_plugin-0.3.3.tar.gz
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
6. Проверьте версию и SHA256 обоих файлов через PyPI JSON API; проверьте установку
|
|
30
|
-
`uvx --from mlspace-plugin==0.3.
|
|
30
|
+
`uvx --from mlspace-plugin==0.3.3 mlspace-plugin --version` из нового кеша.
|
|
31
31
|
7. Только после проверки точной версии в PyPI обновите рабочую ветку GitHub
|
|
32
32
|
marketplace и создайте тег релиза. До этого проверяйте изменения на отдельной
|
|
33
33
|
release-ветке или локальном Git marketplace: main не должен ссылаться на
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "mlspace",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.3",
|
|
5
5
|
"description": "Cloud.ru MLSpace: training jobs, inference, notebooks, data transfer, registry and compute catalog — an MCP server plus skills.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Cloud.ru"
|
{mlspace_plugin-0.3.1 → mlspace_plugin-0.3.3}/plugin/skills/mlspace-diagnose-data-transfer/SKILL.md
RENAMED
|
@@ -33,9 +33,27 @@ Goal: determine whether a data transfer truly failed / was partial, and why.
|
|
|
33
33
|
(in_progress|success|failed|cancelled).
|
|
34
34
|
4. If failed/cancelled, data_transfer get_event_logs (history_id, offset=0, limit=50,
|
|
35
35
|
as_enum_resolved=true) for the decoded reason.
|
|
36
|
+
If events are empty, retain the failed/cancelled status and inspect the matching
|
|
37
|
+
history entry and existing connector logs. Do not call try_connector merely to
|
|
38
|
+
read logs: it can activate the connector. Treat a value such as not_found as an
|
|
39
|
+
observation, not proof of a missing SQL table; that cause needs supporting logs
|
|
40
|
+
or a separate authorized check. Never invent the reason for failure.
|
|
36
41
|
5. Compare rows_count/size_bytes vs the user's expectation to judge "partial".
|
|
42
|
+
These are reported counters, not an audit of source/destination contents.
|
|
43
|
+
Even zero bytes/rows/progress does not prove the run never started, identify
|
|
44
|
+
its failure phase, or prove data was unchanged. Do not claim any of those
|
|
45
|
+
without independent evidence. Distinguish "this diagnostic made no changes"
|
|
46
|
+
from "the earlier transfer made no changes". A connector's saved success
|
|
47
|
+
status is not a fresh connection test and does not establish current health.
|
|
37
48
|
Output: status + hard numbers (rows/bytes/progress) + completeness verdict + decoded
|
|
38
49
|
event reasons; separate "genuinely failed" from "clean exit / fewer rows than expected".
|
|
50
|
+
When failure logs are empty, conclude that the cause and data impact are unknown.
|
|
51
|
+
Report the counters as observations; do not turn them into a narrative about which
|
|
52
|
+
execution phase failed. Suggest the next read-only check instead of inventing a cause.
|
|
53
|
+
If no evidence identifies a failure phase, do not list speculative phases as the
|
|
54
|
+
diagnosis. Rerunning is a write that may change destination data: never include it
|
|
55
|
+
in a list of read-only checks or propose it when the user asked for read-only diagnosis.
|
|
39
56
|
Only if act=true: rerun_history (body={history_id}) for a failed run, after confirming.
|
|
40
|
-
|
|
41
|
-
the numbers, not a dedicated field.
|
|
57
|
+
For reasoning: status is only a 4-value enum; "finished but data looks wrong" is
|
|
58
|
+
inferred from the numbers, not a dedicated field. In the answer, explain only the
|
|
59
|
+
evidence and remaining uncertainty relevant to this run, not a general API audit.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mlspace-stage-s3-to-nfs
|
|
3
|
+
description: "Stage S3 data to NFS (one-off or nightly) on Cloud.ru MLSpace. Copy/sync S3 -> NFS for a GPU job, optionally on a schedule. Write action. Uses the mlspace_data_transfer tools."
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires the `mlspace` MCP server from this plugin (Cloud.ru MLSpace credentials needed).
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Stage S3 data to NFS (one-off or nightly)
|
|
9
|
+
|
|
10
|
+
Copy/sync S3 -> NFS for a GPU job, optionally on a schedule. Write action.
|
|
11
|
+
|
|
12
|
+
This skill drives the `mlspace` MCP server shipped in the same plugin. If its
|
|
13
|
+
tools are not connected, say so instead of guessing — none of these steps can be
|
|
14
|
+
carried out any other way.
|
|
15
|
+
|
|
16
|
+
## Arguments
|
|
17
|
+
|
|
18
|
+
- `source_hint` — Which S3 connector/bucket.
|
|
19
|
+
- `destination_hint` — Which NFS/cluster connector.
|
|
20
|
+
- `source_path` — Path within the source.
|
|
21
|
+
- `destination_path` — Path within the NFS share.
|
|
22
|
+
- `schedule` — Desired recurrence, start time and timezone, or a verified CronViewModel object.
|
|
23
|
+
- `transfer_name` — Name for the transfer.
|
|
24
|
+
- `cluster_name` — Target cluster name (required, not auto-derivable).
|
|
25
|
+
- `target` — Connected workspace ID or unambiguous name, if scoped.
|
|
26
|
+
|
|
27
|
+
## Procedure
|
|
28
|
+
|
|
29
|
+
Goal: copy/sync S3 -> NFS, optionally on a nightly schedule (write actions;
|
|
30
|
+
refused under MLSPACE_READONLY=true).
|
|
31
|
+
1. data_transfer list_connectors with page=1, page_size=20; continue as needed to
|
|
32
|
+
locate the requested connectors. SOURCE: an object-storage connector (s3amazon/
|
|
33
|
+
s3custom/s3google). DEST: an NFS/cluster connector. Capture both connector ids.
|
|
34
|
+
Reuse existing system connectors rather than attempting to create them. A system
|
|
35
|
+
NFS connector may be absent from list output. For the selected destination
|
|
36
|
+
workspace, its workspace ID can be tested as a candidate via get_connector
|
|
37
|
+
(connector_type="nfs", id_=workspace ID); use it only after verifying the returned
|
|
38
|
+
connector belongs to the intended destination. Do not probe unrelated workspaces.
|
|
39
|
+
2. cluster_name is required. Use a verified value from task context or consult the
|
|
40
|
+
configured endpoint's /public/v2/openapi.json, components.schemas.TransferClusterEnum
|
|
41
|
+
and TransferMultiClusterEnum. These describe accepted names, not current reachability
|
|
42
|
+
or access rights. Do not infer API names from UI labels or construct routes by
|
|
43
|
+
concatenating cluster names. If the requested route is absent, explain that the
|
|
44
|
+
direct route is not established; do not launch a multi-hop transfer without an
|
|
45
|
+
agreed intermediate destination and confirmation of both supported legs.
|
|
46
|
+
If names or destination remain ambiguous, ask the user.
|
|
47
|
+
3. (optional, S3 only) try_connector to pre-check connectivity (+ its /try/logs).
|
|
48
|
+
4. Ensure source_path + destination_path are known (ask if absent). Choose the
|
|
49
|
+
strategy from the user's overwrite/append/sync intent; recurrence alone does
|
|
50
|
+
not determine it. For a schedule, confirm the time and timezone and build
|
|
51
|
+
crontab as a CronViewModel JSON object (start_at, time, weekdays, monthdays,
|
|
52
|
+
period as applicable), never a cron-expression string. Verify the service's
|
|
53
|
+
field semantics before converting the requested recurrence; the schema alone
|
|
54
|
+
does not establish period units or timezone behavior. Do not guess fractional
|
|
55
|
+
periods or silently substitute a different interval. Read back the saved
|
|
56
|
+
schedule and compare it with the requested one before claiming success.
|
|
57
|
+
For a one-off run omit crontab; creation starts the transfer immediately.
|
|
58
|
+
5. list_transfers; if one matches this source->dest and the user means "edit", capture
|
|
59
|
+
its id for update instead of create.
|
|
60
|
+
6. create_transfer (body=TransferInputViewModelV5: name, connector ids, paths,
|
|
61
|
+
cluster_name, strategy, optional crontab) OR update_transfer(id_, full body).
|
|
62
|
+
To just enable/disable: switch_transfer(id_, body={"active": true|false}).
|
|
63
|
+
7. Verify: list_history(transfer_id) -> latest run id + status; get_history_status.
|
|
64
|
+
Output: source and destination, the created/updated transfer id, schedule with
|
|
65
|
+
timezone, and verified run status. A future scheduled run has not succeeded yet.
|
|
66
|
+
Before writing, summarize the destination, strategy and schedule for the user;
|
|
67
|
+
do not dump the request body or connector credentials. Report any unverified
|
|
68
|
+
schedule or incomplete result plainly; include API details only for diagnosis.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""CLI entry point for mlspace-plugin."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import logging
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from . import __version__
|
|
12
|
+
from .config import load_settings, user_config_file
|
|
13
|
+
from .server import build_server
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _configure_logging() -> None:
|
|
17
|
+
"""Basic stderr logging so the server's logger.warning/exception emit in prod.
|
|
18
|
+
Level via MLSPACE_LOG_LEVEL (default INFO). stderr keeps stdout clean for stdio MCP.
|
|
19
|
+
"""
|
|
20
|
+
level = os.environ.get("MLSPACE_LOG_LEVEL", "INFO").upper()
|
|
21
|
+
logging.basicConfig(
|
|
22
|
+
level=getattr(logging, level, logging.INFO),
|
|
23
|
+
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
24
|
+
stream=sys.stderr,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def main(argv: list[str] | None = None) -> int:
|
|
29
|
+
parser = argparse.ArgumentParser(
|
|
30
|
+
prog="mlspace-plugin",
|
|
31
|
+
description="MCP-сервер для публичного API v2 Cloud.ru MLSpace.",
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument("--version", action="version", version=f"mlspace-plugin {__version__}")
|
|
34
|
+
parser.add_argument(
|
|
35
|
+
"--transport",
|
|
36
|
+
choices=["streamable-http", "stdio"],
|
|
37
|
+
help="Использовать этот транспорт вместо MLSPACE_TRANSPORT.",
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--list-tools",
|
|
41
|
+
action="store_true",
|
|
42
|
+
help="Показать доступные инструменты и завершить работу (ключи не нужны).",
|
|
43
|
+
)
|
|
44
|
+
# Optional subcommand: with none given the CLI serves, as it always has.
|
|
45
|
+
sub = parser.add_subparsers(dest="command")
|
|
46
|
+
setup = sub.add_parser(
|
|
47
|
+
"setup",
|
|
48
|
+
help="Настроить ключи доступа, воркспейсы, MCP-клиенты и skills.",
|
|
49
|
+
description=(
|
|
50
|
+
"Введите Cloud.ru Key ID и Cloud.ru Key Secret, выберите доступные воркспейсы MLSpace. Настройки сохраняются в "
|
|
51
|
+
f"{user_config_file()} с правами 0600 (доступ только вашему пользователю). Ввод выполняется в вашем терминале: ключи "
|
|
52
|
+
"не передаются модели. Оба поля скрыты звёздочками. Затем подключаются MCP и skills выбранных клиентов."
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
setup.add_argument("--path", type=Path, help="Сохранить ключи и воркспейсы в указанный файл вместо стандартного файла настроек.")
|
|
56
|
+
setup.add_argument("--force", action="store_true", help="Повторить настройку существующего файла с сохранёнными ключами. Конфликты пользовательских skills требуют отдельного выбора.")
|
|
57
|
+
setup.add_argument(
|
|
58
|
+
"--base-url",
|
|
59
|
+
help="Сохранить этот HTTPS-адрес API MLSpace; по умолчанию используется адрес из файла или production.",
|
|
60
|
+
)
|
|
61
|
+
setup.add_argument(
|
|
62
|
+
"--no-verify", action="store_true", help="Сохранить настройки без проверки API; нужны --config-only и --workspace. Клиенты не подключаются."
|
|
63
|
+
)
|
|
64
|
+
setup.add_argument("--client", dest="clients", action="append", choices=["claude-code", "codex", "opencode"], help="Подключить этот клиент; повторите флаг для нескольких. По умолчанию клиенты определяются автоматически.")
|
|
65
|
+
setup.add_argument("--client-path", dest="client_paths", action="append", metavar="CLIENT=PATH", help="Путь к исполняемому файлу клиента, если он отсутствует в PATH: например codex=/usr/local/bin/codex.")
|
|
66
|
+
setup.add_argument("--config-only", action="store_true", help="Сохранить только ключи и воркспейсы. Для подключения клиентов позже повторите setup --force --client CLIENT.")
|
|
67
|
+
setup.add_argument("--non-interactive", action="store_true", help="Без вопросов в терминале: укажите ID через --workspace и источник ключей либо используйте сохранённые ключи.")
|
|
68
|
+
setup.add_argument("--from-env", action="store_true", help="Прочитать ключи из переменных MLSPACE_CLIENT_ID / MLSPACE_CLIENT_SECRET.")
|
|
69
|
+
setup.add_argument("--credentials-file", type=Path, help="Прочитать ключи из существующего dotenv-файла без вывода их значений.")
|
|
70
|
+
setup.add_argument("--replace-credentials", action="store_true", help="Запросить новые ключи вместо сохранённых; для существующего файла также нужен --force.")
|
|
71
|
+
setup.add_argument("--workspace", dest="workspace_ids", action="append", help="Выбрать воркспейс по точному ID; повторите флаг для нескольких.")
|
|
72
|
+
setup.add_argument("--ca-file", type=Path, help="Файл доверенного CA в формате PEM от администратора. Копия сохраняется для следующих запусков MCP; проверка TLS включена.")
|
|
73
|
+
setup.add_argument("--list-workspaces", action="store_true", help="Вывести страницу доступных воркспейсов в JSON без сохранения и установки.")
|
|
74
|
+
setup.add_argument("--search", default="", help="Фильтровать JSON воркспейсов по названию, проекту или ID (с --list-workspaces).")
|
|
75
|
+
setup.add_argument("--offset", type=int, default=0, help="Пропустить это число результатов JSON; не меньше 0, по умолчанию 0.")
|
|
76
|
+
setup.add_argument("--limit", type=int, default=20, help="Число воркспейсов на странице JSON: 1–100, по умолчанию 20.")
|
|
77
|
+
args = parser.parse_args(argv)
|
|
78
|
+
|
|
79
|
+
if args.command == "setup":
|
|
80
|
+
from .init_cli import run_init
|
|
81
|
+
|
|
82
|
+
return run_init(
|
|
83
|
+
args.path,
|
|
84
|
+
force=args.force,
|
|
85
|
+
verify=not args.no_verify,
|
|
86
|
+
base_url=args.base_url,
|
|
87
|
+
config_only=args.config_only, non_interactive=args.non_interactive,
|
|
88
|
+
from_env=args.from_env, credentials_file=args.credentials_file,
|
|
89
|
+
workspace_ids=args.workspace_ids, clients=args.clients, client_paths=args.client_paths,
|
|
90
|
+
ca_file=args.ca_file, replace_credentials=args.replace_credentials,
|
|
91
|
+
list_workspaces=args.list_workspaces, search=args.search, offset=args.offset, limit=args.limit,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
_configure_logging()
|
|
95
|
+
settings = load_settings()
|
|
96
|
+
if args.transport:
|
|
97
|
+
settings.transport = args.transport
|
|
98
|
+
|
|
99
|
+
if args.list_tools:
|
|
100
|
+
mcp = build_server(settings)
|
|
101
|
+
tools = mcp._tool_manager.list_tools()
|
|
102
|
+
mode = "read-only" if settings.readonly else "read-write"
|
|
103
|
+
print(f"mlspace-plugin {__version__} — {len(tools)} инструментов ({mode}):")
|
|
104
|
+
for tool in sorted(tools, key=lambda t: t.name):
|
|
105
|
+
print(f" {tool.name}")
|
|
106
|
+
return 0
|
|
107
|
+
|
|
108
|
+
settings.validate_bind()
|
|
109
|
+
settings.require_credentials()
|
|
110
|
+
mcp = build_server(settings)
|
|
111
|
+
|
|
112
|
+
if settings.transport == "stdio":
|
|
113
|
+
mcp.run(transport="stdio")
|
|
114
|
+
else:
|
|
115
|
+
print(
|
|
116
|
+
f"mlspace-plugin: сервер streamable-HTTP запущен на "
|
|
117
|
+
f"http://{settings.host}:{settings.port}/mcp",
|
|
118
|
+
file=sys.stderr,
|
|
119
|
+
)
|
|
120
|
+
mcp.run(transport="streamable-http")
|
|
121
|
+
return 0
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
if __name__ == "__main__":
|
|
125
|
+
raise SystemExit(main())
|