runpod-mcp
runpod-mcp — кастомный MCP-сервер для репликации Learning-to-Swim
Отдельное примечание: этот сервер извлечён (со всей историей) из проекта
learning-to-swim-replication. Относительные ссылки, как../runbook/RUNBOOK.md, относятся к родительскому проекту и корректно резолвятся только когда этот репозиторий лежит внутри него (или симлинкован туда); сам сервер работает автономно.
Задаче‑ориентированные инструменты (14) зеркалируют runbook/RUNBOOK.md родительского проекта вместо ~50 универсальных зеркал API. Кастомный, потому что ни один RunPod API не выполняет команды на поде — официальный MCP покрывает только управляющую плоскость (control plane); запуск pod_setup.sh, sanity‑прогона по осям и обучение требуют SSH + rsync, что закодировано здесь с ограничителями стоимости в коде.
Архитектура
.mcp.json → run.sh (venv bootstrap) → server.py (FastMCP, stdio; thin)
└── runpod_mcp/
config.py Keychain key fetch + rpa_ scrubber
api.py REST v1 (pods/volumes/billing) + unauth GraphQL gpuTypes
guardrails.py one-pod-per-vehicle (unknown refused) · 4090-only · no spot · volume required · confirm gate
ssh.py hardened ssh/scp/rsync; known_hosts_runpod; 60s conn cache
jobs.py detached jobs: /workspace/jobs/<id>/{cmd.sh,pid,out.log,exit_code,meta.json}
training.py DR tables (RUNBOOK/yaml-cross-checked) + verbatim train cmd
supervise.py Mac-side background CLI: launch→poll→pull→sync→spend→stop (reuses tools.*)
watch.py Mac-side ADVISORY observation CLI: discover job→tail out.log→parse metrics→page on plateau/failure/stall (read-only; never stops pods)
remote/ job_wrapper.sh · idle_watchdog.sh · apply_bluerov2_patch.py
deadman.py Mac-side stop-pod fuse: arm --vehicle → sleep → stop with retries (per-vehicle pid/summaries)
supervise.sh → caffeinate -i wrapper around python -m runpod_mcp.supervise
watch.sh → caffeinate -i wrapper around python -m runpod_mcp.watch (live-pod behavior UNVERIFIED — fixture/mock-verified only; see CLAUDE.md §D)
deadman.sh → caffeinate -i wrapper around python -m runpod_mcp.deadman (arm/cancel REQUIRE --vehicle; bare status reports all vehicles)Stateless и в разрезе аппарата: «под» — это то, что возвращает
GET /podsпри совпадении с настроенным именем выбранного аппарата (hippocampus→lts-replication,bluerov2→lts-replication-bluerov2; параметрvehicleкаждого инструмента по умолчанию равенhippocampus, аstop_pod/terminate_podтребуют его явного указания); консоль и MCP всегда согласованы. Единственное локальное состояние — кэш (host, port) на 60–секундного на каждый Runtime.Асинхронные задания: один SSH‑вызов запускает
setsid bash job_wrapper.sh <dir> <pod_id> <ceiling> <auto_stop>; состояние остаётся на сетевом томе (network volume), поэтому оно переживает перезапуски MCP, сон Mac и остановку пода.timeout --kill-afterжёстко ограничивает верхний предел wall-clock (exit 124); суффикс auto-stop выполняется строго ПОСЛЕ записи exit_code, так что таймаут никогда не может обойти его. Pod id передаётся аргументом командной строки (переменные окружения контейнера ненадёжны в «отправленных» (detached) BatchMode‑shellах);/etc/rp_environmentподключается для получения учётных данных runpodctl; активация auto_stop синхронно проверяет runpodctl и громко падает, если тот не работает. Пробник (2026-08-09) — трёхсторонняя диагностика: проверки в «голой» оболочке ничего не решают (они отвечают H1‑vs‑H2 и фиксируют голый PATH), затем/etc/rp_environmentподключается безусловно, и уже «подключённая» пара несёт вердикт —NO_RUNPODCTL(бинарник по‑прежнему отсутствует даже после source, код выхода 90),NO_CREDENTIAL_AUTH_SOURCEDвсё ещё отказ после подключения, код 91),PROBE_OK(успешное только после подключения;NO_RUNPODCTL_AUTH_BARE— промежуточный диагностика, который продолжает выполнение).Idle‑сторож: переустанавливается на каждом переходе в
running— очистка диска контейнера уносит всё установленное на лету (самidle_watchdog.sh, apt‑библиотеки X11/GL,rsync), поэтому установка при каждом переходе остаётся;runpodctlпри этом входит в ОБРАЗ (IMAGE-SHIPPED) и появляется снова при каждой перезагрузке (очистка draws образа на место, а не опустошает диск — уточнение от 2026-08-09). Каждые 5 мин: если нет живого pid задания + нет sshd‑сессии +/workspace/.keepalive старше 60 мин →runpodctl stop pod.touch /workspace/.keepalive— “мано-nrǔ” («единственная дверь») для ручной сессии.Успешная установка выдаётarmed (stop path unverified)— probes подтверждают READ (get pod), сторожевому нужно WRITE (stop actual namestop); первый реальное подтверждение — строка об успешной остановке в/workspace/.idle_watchdog.log. Статус на 2026-08-09: установочный probe не прошел на каждом записанном выводё (непрозрачный rc=91 до фикса) — сторожевой так и не активировался; дефект 2 уходит релизным статуом DIAGNOSED, а не CLOSED, и sentinel следующего bring‑up,предпорешит это.idle_watchdog: FAILED` ⇒ не запускать ни заданий без дополнительной защиты Mac‑side.Guardrails — как код: один под на каждый заявленный аппара (любые и DNA under other pod имя на аккаунте отказываются), RTX–4090 ×1, SECURE, interruptible принудительно false, need a network volume,
terminate_podтребуетзации_Scopeявноеvehicleи обвечённую строкуterminate <pod_name этого аппарата>(например,terminate lts-replication); на поде одновремено не больше одного job — кроме случая, когда заданforce.
Установка / регистрация
Зарегистрируйте сервер в .mcp.json проекта (Claude Code), указав абсолютный путь к run.sh — run.sh при первом запуске сам соберёт собственное .venv:
{
"mcpServers": {
"runpod": {
"command": "bash",
"args": ["/path/to/runpod-mcp/run.sh"]
}
}
}Установка
API key (никогда не на диске/в git/в argv — только macOS Keychain; сервер читает его через
security find-generic-passwordи вычищает значенияrpa_из каждой ошибки и лога):security add-generic-password -a kyle -s runpod-api-key -w '<KEY>'(Имя учётной записи для lookup сейчас захардкожено как
kyleвrunpod_mcp/config.py— поправляйте оба вместе, если ваш аккаунт macOS отличается.)SSH-ключ:
~/.ssh/id_ed25519(.pub)должен существовать;.pubпередаётся при создании поданая через envPUBLIC_KEY— именно его реально соблюдают образыrunpod/pytorch(live‑checked); также ставится belt‑and‑bracesSSH_PUBLIC_KEY. Прямой SSH наroot@publicIp:portMappings["22"]; прокси‑SSH от RunPod не (нет scp). Хост‑ключи кладутся в специализированный~/.ssh/known_hosts_runpod, который усекается под каждый запуск пода (после затирание диска хосте выKey пересоздаются; заброшенные записи только дают ложные MITM‑отказы).Больше ничего — при первом запуске
run.shсоздаст.venv/и установит requirements.txt (срабатывает один раз, по «маркерной» проверке).
Тестирование
runpod-mcp/.venv/bin/python -m pytest runpod-mcp/tests -q # offline (default)
RUNPOD_MCP_LIVE=1 runpod-mcp/.venv/bin/python -m pytest \
runpod-mcp/tests/test_live.py -q # live $0 read-onlyОфлайн‑тесты используют httpx.MockTransport + поддельный SSH с duck‑typing
— без сети, прилож без ключей. Живые тесты — это read‑only GETs и handshake
MCP stdio через run.sh, проверяющий, что все 14 инструментов
регистрируются; таблицы DR сверяются разбором
BLUEROV2/config/bluerov2_heavy.yaml,
RUNBOOK.md и
APPLYM; патч‑скрипт прогоняется на
зафиксированных фрагментах‑фикстурах источника 7c5ebe7 (плюс
SHA‑гейтованный тест против реального ссылочного клона, если тот
присутствуетл Join — read‑only, во временных копиях).
test_supervise.py гоняет ядро CLI supervise на внедрённых подменах и
фейковых частотах без реального ожидания, охватывая все ветви безопасности:
нормальное завершение, спуск на ошибке, forced‑stop по
максимальному ожинию, отказ когда под не running, отказ в заапуске,
транзиторные полиинг‑ошибка, сбой захвата также останавливается, вариант
и флаг --no-stop, и во всех случаях утверждается, что
terminate_pod не вызывается.
Корневые репо pytest -q игнорирует эту папку (conftest.py
collect_ignore) — лёгкое интересное корневое venv не содержит
mcp/httpx.
Контролируемые запуски (supervise.sh)
Одна команда, которая прогоняет целую серию целиком: verify‑pod‑running
→ dry‑run производную во ограниченный wall‑clock‑потолок →
launch(auto_stop=false) → опрос job_status → безусловно тянет
/workspace/jobs/<job_id>/ + sync_logs + spend_report → stop_pod
→ постоянный JSON‑summary; агент запускает её именно раз как
фоновую задачу и получает уведомление о заверding. Переиспользует
runpod_mcp.tools.* (никакое дублирование логики, всеми
guardrails предписаны) и никогда не вызывает terminate_pod. Это CLI
на стороне Mac, не 15‑й его MCP‑инструмент: инструмент, который
опрашивает минутами, заблокирует stddio‑сервер.
# training run (background task)
supervise.sh --training curee --dr DR_0 --seed 1 \
[--interval 45] [--max-wait N] [--backstop 300] [--no-stop] \
[--sync-subdir rsl_rl/warpauv_direct] [--summary-path PATH]
# generic job — --sync-subdir REQUIRED (pass 'none' to skip the analysis sync;
# the job-dir pull always happens); --vehicle routes the pod (default
# hippocampus; --training mode derives it from the training vehicle instead)
supervise.sh --job-name eval --command "…" --workdir /workspace \
--sync-subdir <dir|none> [--max-runtime-sec N] [--vehicle bluerov2]Безопасность денег: у цикла опроса ровно два выхода — нормальное
завершение → stop_pod; либо истёл --max-wait (всегда конечный,
а под ещё running → force‑stop + ненулевой exit + с флагом
force_stopped в сводке. Откаченный «refusal» в запуске → без
остановки (чини и повторяе), exit 2. Файл supervise-<job_id>.json
в соответствующем каталоге логов авто (logs/pod/ для hippocampus,
logs/pod/bluerov2/ для bluerov2) — это контракт восстановления (более
поздняя сеанс сверяется с его него состояния остановки). Оговорки по
живучести: caffeinate -i защищает от засыпания в холостом ходу, но
<не член> от закрытия крышки; выживание процессов запущенных
run_in_background через переживание WarmLifecycle reaping не проверено
— потолочек timeout назначения процесса — гарантированный
anchort; под‑side idle‑watchguard подстраховал бы, но ни разу не
взводился ни на одном записанном bring‑а (DIAGNOSED, не CLOSED — см.
на chapters idle‑watchdog), поэтому включайте Macy‑side deadman,
когда ensure_pod сообщает idle_watchdog: FAILED.
Цепочки кампаний (CUREE/chains/)
Один bash‑скрипт на кампанию (называется по ID, например
chain-011-CUREE_Adaptive_weights.sh): вся последовательность под‑side
задач кампейна — патчи, гейты, тренировки, эвалы, синки — в виде
упорядоченных слап соответствующих ссылок. Цепи запускаются только через
supervise.sh (который владеет и захватом и стопом), никогда вручную;
они всё время являются устойчивой записью того, что именно выполнила
кампания.
Dry‑прогоны
ensure_pod, run_pod_setup, run_job, launch_training,
apply_bluerov_patches все принимают dry_run=true и возвращают
точные вычисленные payloads/edits/commands, ничего не варьируя ($0).
supervise использует именно этот dry‑run путь, чтобы вычислить
свой конечный --max-wait перед реальным запуском.
NGC fallback image (ручная смена — читать полностью)
nvcr.io/nvidia/isaac-sim:4.5.0 (запасной вариант дня‑1 в RUNBOOK) не
имеет, sshd — это ломает всю SSH‑историю этого сервера. Переключение
требует docker‑start команду, которая ставит и запускает sshd (это
не однострочное изменение) флаг Николая со сдерживанием перед всеми
изменениями image_name в pod_defaults.yaml.
Known риски (принято на этапе планирования)
URL загрузки IsaacSim 4.5.0 в
pod_setup.shможет вернуть 404 — проявится в хвосте логаjob_status; исправления runbook, не MРов.Наличие 4090-flactinet по дата‑центрам; источник volume привязывает один DC. Покрытие через
gpu_availability(data_center_id=...)+ рецепти восстановления уensure_podпри отсутствии GPU; крайний случай — создать второй volume в другом DC.
Лицензия
MIT — см. LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Create and manage AI agents that collaborate and solve problems through natural language interacti…
Build, validate, and deploy multi-agent AI solutions from any AI environment.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/kyle-nelson-berkeley/runpod-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server