mlspace-plugin
Установка: инструкция человеку · инструкция агенту. Агенту, получившему ссылку на репозиторий для установки: сначала прочитайте INSTALL_AGENT.md.
MCP-сервер для публичного API Cloud.ru MLSpace v2 (https://api.ai.cloud.ru/public/v2).
Открывает операции MLSpace, не помеченные deprecated в поставляемой схеме OpenAPI, — обучение, инференс,
ноутбуки, TensorBoard'ы, воркспейсы, аллокации, очереди, Docker Registry,
перенос данных и каталог ресурсов — LLM-агентам в виде 17
инструментов, каждый с параметром action. Под капотом — 126 операций,
описанных в поставляемой схеме OpenAPI и сгруппированных для работы LLM-агента.
Одна учётная запись, несколько выбранных workspace; stdio и локальный streamable-HTTP. Запись доступна по умолчанию; необратимые действия — за гейтом
confirm=true.
Что это и зачем
MLSpace отдаёт большой REST-API (142 пути, 185 операций в OpenAPI v2.8.1). Дёргать его «голым» из LLM-агента неудобно: разнобой в пагинации, статусах, версиях путей, часть параметров обязательны только в рантайме и т.п. Этот сервер прячет всю механику (аутентификация, заголовки, шаблоны путей, кодирование query, тела запросов, обработка ошибок) и выставляет наружу компактный, предсказуемый, дружелюбный к модели интерфейс:
- 17 инструментов вместо 185 «тонких» — модель не тонет в списке тулов; каждый
инструмент = один домен, конкретное действие выбирается через
action. (Автогенерация по спеке дала бы 185 инструментов с именами по 66 символов видаcreate_notebook_workspace_autoshutdown_rule_v2_public_v2_notebooks_v2_….) - Подсказки прямо в описании — для каждого
actionуказаны обязательные параметры и форма тела (required/optional/enum-поля), вытянутые из спеки. - Ступени защиты — гейт
confirm=trueна необратимые операции, dry-run для проверки write-запроса без отправки, режим read-only для наблюдательных сценариев. - Чистый контекст — компактный JSON, обрезка длинных списков и логов, удаление k8s-шума, редактирование секретов в ответах.
Установка и настройка
Python 3.10+, macOS или Linux. Установка из PyPI:
uvx mlspace-plugin@latest setup
Из каталога скачанного репозитория:
uv tool install .
mlspace-plugin setup
Мастер обнаруживает Claude Code, Codex и OpenCode, просит только Key ID и Key Secret
с маской *****, предлагает поиск воркспейсов по имени/проекту/ID и множественный
выбор. Проверяет API, сохраняет credentials в пользовательский .env с правами
0600. Для Claude Code и Codex мастер добавляет marketplace этого репозитория
и устанавливает нативный плагин с MCP и скиллами. OpenCode получает MCP и скиллы
в собственном каталоге. Мастер проверяет запуск MCP; затем откройте новую сессию
клиента — сервер запускается автоматически.
TLS использует системные доверенные CA. Для корпоративного PEM есть --ca-file:
мастер сохраняет копию для последующих запусков. Ошибка TLS/сети останавливает
настройку без перезаписи прежнего файла и без запроса ручного x-api-key.
Повторная настройка — uvx mlspace-plugin@latest setup --force: сохранённые ключи на прежнем
endpoint переиспользуются. Для замены ключей добавьте --replace-credentials.
Для stage укажите --base-url https://mlspace-stage.example.com.
Только credentials без подключения клиентов — --config-only.
Уже установленный нативный плагин из этого репозитория переиспользуется.
Подробнее: установка, SSH, сертификаты и повторная настройка.
Для разработки: uv sync --extra dev и uv run pytest.
Порядок поиска кредов — от общего к частному, побеждает более конкретное:
- Файл, сохранённый
setup(по умолчанию~/.config/mlspace-plugin/.env) - файл из
MLSPACE_ENV_FILE— выбран явно - настоящие переменные окружения — бьют любой файл
Файл .env из текущего каталога автоматически не читается. Для разработки
укажите его явно через MLSPACE_ENV_FILE, чтобы чужой репозиторий не мог
подменить адрес API при использовании сохранённых ключей.
~/.config/mlspace-plugin/credentials-path.json хранит только путь к выбранному
файлу: настройка через --path или XDG_CONFIG_HOME работает и после перезапуска
клиента с другим окружением. Повреждённый указатель или отсутствующий целевой файл
дают ошибку; другой аккаунт молча не подставляется.
| Переменная | Обяз. | По умолчанию | Назначение |
|---|---|---|---|
MLSPACE_CLIENT_ID |
✅ | — | Cloud.ru Key ID (личный или сервисного аккаунта) |
MLSPACE_CLIENT_SECRET |
✅ | — | Cloud.ru Key Secret |
MLSPACE_API_KEY |
— | x-api-key одного воркспейса; без него сервер получает ключ сам |
|
MLSPACE_WORKSPACE_ID |
Для legacy singleton | — | ID единственного воркспейса |
MLSPACE_WORKSPACES |
Вместо legacy пары | [] |
Сохранённый JSON-каталог выбранных workspace: id, name, project_name, опциональный api_key; пишет мастер |
MLSPACE_ENV_FILE |
— | Явный путь к файлу с кредами; имеет приоритет над пользовательским конфигом | |
MLSPACE_CA_FILE |
системные CA | Дополнительный доверенный PEM; setup сохраняет копию | |
MLSPACE_BASE_URL |
https://api.ai.cloud.ru |
Хост API | |
MLSPACE_READONLY |
false |
true убирает все 58 write-действий из перечня action |
|
MLSPACE_DRY_RUN |
false |
Валидировать write, но не отправлять (вернуть превью) | |
MLSPACE_TRANSPORT |
streamable-http |
streamable-http или stdio |
|
MLSPACE_HOST / MLSPACE_PORT |
127.0.0.1 / 8000 |
Привязка HTTP (только loopback) | |
MLSPACE_ENABLED_DOMAINS |
(все) | Список через запятую — ограничить набор инструментов | |
MLSPACE_TIMEOUT |
60 |
Таймаут запроса, сек | |
MLSPACE_NAMESPACE |
(из workspace_id) | Закрепить k8s-namespace воркспейса; пусто = резолвится автоматически | |
MLSPACE_LIST_DEFAULT_LIMIT / MLSPACE_LIST_MAX_LIMIT |
50 / 200 |
Размер списков по умолчанию / максимум | |
MLSPACE_LOG_TAIL_LINES |
200 |
Сколько последних строк лога показывать |
Обмен service_auth (токен с TTL 1ч) выполняется внутри — это не инструмент.
Подключённые воркспейсы и адресация
mlspace_contexts возвращает сохранённый набор, endpoint и окружение без секретов
и сетевого обхода. Один, три или десять воркспейсов равноправны: основного/текущего
нет. mlspace_workspaces list показывает доступность учётных данных и не расширяет
набор. Legacy-конфигурация остаётся одним подключением.
Адресные действия принимают target (ID или однозначное название) и, для найденных
jobs/notebooks, resource_ref. Ссылка содержит окружение, workspace, тип и адрес
объекта; конфликтующие аргументы отклоняются. Диагностика и перезапуск сохраняют
адрес выбранного объекта, а успешный перезапуск получает новую ссылку, когда API
вернул распознаваемое новое имя. Контекст запроса не доказывает владельца общей очереди.
При одном workspace выбор не нужен. Явная работа в A сохраняет A для её шагов, а
отдельное чтение B этого не меняет. Общий запрос «теперь покажи задачи» снова охватывает
подключённый набор. Делегированное «в любом из A/B с подходящим GPU» позволяет выбрать
место по проверенным условиям без повторного вопроса; реальная неоднозначность требует
уточнения. Образец ноутбука сам по себе не определяет место создания.
| Read-only helper | Параметры и результат |
|---|---|
mlspace_jobs_overview |
targets, author, status; динамически обнаруживает MT-регионы и читает страницы jobs |
mlspace_notebooks_overview |
targets; читает страницы notebooks, включая paused |
mlspace_queue_inspect |
queue_id, target исходной очереди, candidate_nodes, targets областей наблюдения; проверяет доступные jobs/notebooks/pods, все приоритеты pending и факты/нагрузку узлов |
У helpers общий набор бюджетов: page_size=100, max_pages=50 на поток,
max_requests=200 на логические inventory GET, max_items=200 на вывод.
Авторизация, получение ключа и возможный 401 retry — дополнительные транспортные
запросы. targets по умолчанию — весь выбранный набор; эти helpers доступны при
включённом соответствующем домене. Фильтра region у jobs overview нет: для узкого
регионального чтения доступен mlspace_jobs list с пагинацией.
Ответ показывает requested_scope, checked_scope, failures, observed_at и
полноту; строки items содержат source (тип наблюдения), data, provenance и
при распознанном адресе resource_ref. complete требует успешного полного чтения
и отсутствия усечения вывода. observed_count — число наблюдений, не полный итог
при частичном чтении и не сумма уникальной общей мощности. Частичный поиск не
доказывает уникальность имени; «все» после сокращённого списка требует понятного
множества. Явный фильтр author можно повторно использовать как настройку пользователя,
но он не доказывает identity: задачи коллег нельзя называть «моими» по членству в workspace.
Перед переносом вычислительного узла используйте transfer_compute_node: сначала
mlspace_queue_inspect, затем при запросе на выполнение mlspace_queues add_nodes
в целевую очередь с {nodes, force_withdrawal:false}. Узел отличается от Jupyter
сервера. Настройки GPU у paused notebook не означают занятую мощность; pending —
ожидающая потребность, а не работающая нагрузка. Даже полное чтение не гарантирует
видимость всех чужих workload общей аллокации: cross_workspace_coverage остаётся
unknown. Не обещайте перенос без влияния по такому обзору. Существующие правила
подтверждения операций сохраняются; отдельного подтверждения workspace нет.
Запуск
mlspace-plugin # streamable HTTP на 127.0.0.1:8000
MLSPACE_TRANSPORT=stdio mlspace-plugin # stdio
Подключение из MCP-клиента
Streamable HTTP (по умолчанию): запустите mlspace-plugin, направьте клиента на
http://127.0.0.1:8000/mcp.
stdio (Claude Desktop / Cursor / Codex) — пример для claude_desktop_config.json:
{
"mcpServers": {
"mlspace": {
"command": "mlspace-plugin",
"env": {
"MLSPACE_TRANSPORT": "stdio",
"MLSPACE_ENV_FILE": "/absolute/path/to/mlspace-plugin/.env"
}
}
}
}
Инструменты
Каждый инструмент принимает action + параметры этого действия. Полный список
действий с подсказками по телу виден в описании инструмента у клиента. [w] —
write-операция (скрыта из action-перечня при MLSPACE_READONLY=true).
| Инструмент | Назначение | Действия |
|---|---|---|
mlspace_jobs |
Задачи обучения | list, get, logs, list_nodes, list_pods, get_params, get_preemptors, run[w], restart[w], delete[w] |
mlspace_build_image |
Сборка кастомных образов | list, run[w], get, get_logs, get_pods, delete[w] |
mlspace_notebooks |
Jupyter-серверы | list, get, autoshutdown_get, create[w], delete[w], users_list, users_set[w], users_revoke[w], pause[w], resume[w], modify[w], autoshutdown_set[w], autoshutdown_delete[w] |
mlspace_tensorboards |
TensorBoard-инстансы | list, get, create[w], modify[w], pause[w], resume[w], delete[w] |
mlspace_inference |
Сервисы инференса | list, get, predict, create[w], update[w], delete[w] |
mlspace_async_inference |
Асинхронный инференс | list, predict, get_result, get_status |
mlspace_dalle |
DALL-E (async) | predict, result |
mlspace_workspaces |
Воркспейсы | get_api_key, status, users, list, get, allocations, allocation_queues |
mlspace_allocations |
Аллокации ресурсов | list, list_defaults, get, list_assignments, list_instance_types, get_nodes, set_default[w], unset_default[w] |
mlspace_queues |
Очереди аллокаций / shared-кластер | list, get, defaults, instance_types, jobs, notebooks, pods, awaiting_launch_resources, queue_defaults, assign_workspace[w], delete[w], create[w], update[w], assign[w], unassign[w], set_default[w], unset_default[w], add_nodes[w], assign_shared[w], unassign_shared[w] |
mlspace_docker_registry |
Docker Registry | current_registry, list_repos, get_repo, update_repo[w], delete_repos[w], repo_fav[w], list_images, get_image, delete_images[w], list_tags, create_tag[w], update_tag[w], delete_tags[w], generate_password[w] |
mlspace_data_transfer |
Коннекторы / переносы / история | list_connectors, get_connector, create_connector[w], update_connector[w], fav_connector[w], halt_connector[w], try_connector[w], get_connector_logs, delete_connectors[w], list_sources, list_transfers, get_transfer, create_transfer[w], update_transfer[w], fav_transfer[w], switch_transfer[w], delete_transfers[w], list_history, get_history_status, get_event_logs, cancel_history[w], rerun_history[w], fav_history[w], delete_history[w] |
mlspace_resources |
Каталог вычислений | configs, instance_types, nodes, nodes_load, rate_limits |
Волатильные значения (region, статус задачи, connector_type, …) — это обычные
строки, не фиксированные enum'ы: их известные значения перечислены в описании
параметра, но новые значения, которые API добавит позже, тоже принимаются. Тела
write-запросов подаются параметром body: dict; обязательные/вложенные/enum-поля
вынесены в описание действия. Локальная валидация тела (lint) fail-open —
ловит только явные структурные ошибки (нет обязательного поля, явное несовпадение
типа) до похода в сеть и никогда не отклонит тело, которое API бы принял.
Плагин: Codex, Claude Code и совместимые агенты
Поставка MLSpace объединяет MCP-сервер и 12 скиллов.
Обычная установка — uvx mlspace-plugin@latest setup: marketplace подключается
автоматически. Нативные клиенты управляют плагином mlspace@mlspace сами.
Манифест фиксирует точную версию runtime из PyPI вместе со скиллами.
Ключи и CA остаются в пользовательском конфиге вне кеша плагина.
Повторный setup --force обновляет сохранившиеся подключения мастера.
Собственного фонового обновления нет; политики автообновления клиентов мастер
не меняет. ZIP релиза содержит те же манифесты и скиллы, без вложенного wheel.
Для других агентов предусмотрены Agent Plugins 1.0, Agent Skills и обычное
MCP-подключение; поддержку конкретного загрузчика нужно проверять отдельно.
Пошаговые сценарии поставляются только скиллами плагина; сервер отдаёт общие правила
в instructions. tests/test_skills.py сверяет скиллы с реальными инструментами.
Безопасность
- Гейт подтверждения: 16 необратимых действий (удаления, отзыв доступа,
отмена переноса, ротация пароля реестра) требуют
confirm=true. Это основной рубеж в конфигурации по умолчанию. - Режим read-only (
MLSPACE_READONLY=true): все 58 write-действий исчезают изaction-перечня — модель их не видит — и блокируются в рантайме как страховка. По умолчанию выключен: сервер задуман как рабочий инструмент, а не смотровое окно. Включайте для наблюдательных сценариев, общих стендов и всего, где агенту незачем ничего менять. - Dry-run (
MLSPACE_DRY_RUN=true): write-запрос полностью валидируется (lint тела, шаблон пути, гейт confirm), но не отправляется — возвращается превью запроса, который ушёл бы в API. Удобно дать модели собрать и проверить write до реального применения. - Снос воркспейса не выставлен:
POST/DELETE /workspaces/v3/(bootstrap / debootstrap) намеренно не реализованы — слишком большой радиус поражения для общего сервера. Жизненный цикл воркспейса — только через консоль. - Сеть: HTTP-транспорт отказывается слушать не-loopback адрес (в v1 нет серверной аутентификации).
- Секреты в ответах (пароль registry, api-key воркспейса) редактируются.
Важно про
confirm: этот флаг ставит сам агент в том же вызове. Это защита от случайного действия, а не human-in-the-loop. Подтверждение человеком обеспечивает окно вашего MCP-клиента, которому мы помогаем аннотациейdestructiveHint. Единственный рубеж, который агент обойти не может, —MLSPACE_READONLY=true; в конфигурации по умолчанию его нет, и решение остаётся за клиентом.
Разработка
pytest # юнит- + drift/контракт-тесты (моки HTTP, живые креды не нужны)
ruff check .
mypy src
Сервер сверяется с небольшим сгенерированным артефактом
(src/mlspace_mcp/spec/body_schemas.json) ради подсказок по телу запроса и
мягкого lint'а; полный openapi.json нужен только для сборки/тестов.
Обновление спеки (после смены версии API)
- Перевыкачать
src/mlspace_mcp/spec/openapi.jsonс OpenAPI-эндпоинта MLSpace. - Перегенерировать схемы тел:
python scripts/gen_body_schemas.py. - Прогнать
pytest— drift/контракт-тест поймает любое действие, чьё(method, path)исчезло или стало deprecated; поправить соответствующийtools/<domain>.py.
После правки скилла
Правьте plugin/skills/<name>/SKILL.md и запустите pytest tests/test_skills.py.
После смены версии пакета — python scripts/gen_plugin.py для манифестов.
Архитектура
LLM ⇄ FastMCP (streamable-HTTP/stdio) ⇄ tools/<domain>.py (зонтичные тулы)
⇄ MLSpaceClient ⇄ TokenManager ⇄ api.ai.cloud.ru/public/v2
| Модуль | Ответственность |
|---|---|
config.py |
Настройки (Settings) из окружения: креды, base_url, readonly, dry_run, транспорт, host/port, таймаут, включённые домены. |
auth.py |
TokenManager: обмен service_auth, кэш токена (TTL 1ч), single-flight рефреш за ~60с до истечения и при 401. |
client.py |
MLSpaceClient: единый httpx.AsyncClient, инъекция заголовков, шаблоны путей, повторяемые query-ключи, JSON-тело на любом методе (включая DELETE), один прозрачный ретрай на 401. |
errors.py |
Маппинг HTTP/исключений → понятные сообщения (включая разбор detail[]). |
formatting.py |
Компактный JSON, обрезка списков/логов, удаление шумовых ключей, редактирование секретов. |
workspace_context.py / resource_refs.py |
Выбор фиксированного контекста, отдельные клиенты и проверяемые адреса jobs/notebooks. |
overview.py |
Ограниченный обход инвентаря и очереди с происхождением и полнотой наблюдений. |
job_hooks.py |
Job preflight, fail-closed delete guard и совместимость ответов; leaf без импорта registry. |
registry.py |
Op/Param/DomainTool + единый дженерик-диспетчер: стрип write в readonly, гейт confirm, dry-run, clamp пагинации, lint тела, формат ответа. |
tools/<domain>.py |
Чистые декларативные данные: DOMAIN: DomainTool (карта action → Op + список Param). Никакой механики запросов. |
bodyspec.py |
Загрузка body_schemas.json; summarize() для подсказок + fail-open lint(). |
server.py / __main__.py |
Сборка FastMCP, общие instructions, регистрация доменов, запуск транспорта. |
Каждый доменный модуль — независимая единица из чистых данных; вся механика живёт в ядре один раз, поэтому домены не могут «разъехаться» по заголовкам/путям/ кодированию.
Документация
Обратная связь и вклад в проект
Нашли ошибку или неудобный сценарий работы с MLSpace? Создайте Issue: опишите, что хотели сделать, что получилось, версию плагина,
ОС и клиент — Claude Code, Codex или OpenCode. Не прикладывайте ключи, токены,
.env или логи с чувствительными данными.
Исправления и улучшения присылайте через Pull Request. Как запустить проверки и устроен проект — в CONTRIBUTING.md.
Особенно рады вашим скиллам! Если вы нашли удобный способ запускать обучение, разбирать ошибки, работать с данными или обслуживать инференс — оформите его в скилл и поделитесь. Такие сценарии помогают всем проще работать с MLSpace. Готовая реализация необязательна: можно начать с Issue с примером задачи и ожидаемым результатом.
Metadata
Release files for mlspace-plugin 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mlspace_plugin-0.3.0.tar.gz | 258.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mlspace_plugin-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 460.5 kB
Release files / mlspace_plugin-0.3.0.tar.gz
| Download URL | mlspace_plugin-0.3.0.tar.gz |
|---|---|
| Size | 258.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6b32dd695a6c6d881ef3c18a4d866e09a13b9665cb82eccb923c82e5dd290f7a
|
|
BLAKE2b-256 checksum How to use checksums |
b139cd78d3101113e19b6f0f56eadb8d2e3315251898e22e59482c884f30cdc3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / mlspace_plugin-0.3.0-py3-none-any.whl
| Download URL | mlspace_plugin-0.3.0-py3-none-any.whl |
|---|---|
| Size | 202.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c467c22a33b7b953a5970140c38cff05ae436c90fc4a5ad9695b27f3bc5a052
|
|
BLAKE2b-256 checksum How to use checksums |
95223970591d76519be796d0a974e30fb57be30ff0939f4a50ab8bb72cab2d16
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|