2026: OpenClaw на удалённом физическом Mac — подключение MCP: stdio и Streamable HTTP (runbook: spawn ENOENT, несовпадение версий протокола, тайм-ауты инструментов + CLI + FAQ)
Команды, которые держат OpenClaw на безлюдных физических Mac, сталкиваются с тремя повторяющимися классами сбоев MCP: stdio spawn ENOENT из-за урезанного PATH, сдвиг версий или типов контента у Streamable HTTP и вызовы tools/call, которые упираются в тайм-аут клиента или сервера. Здесь — семь шагов выкатки, матрица stdio vs HTTP, готовые JSON-фрагменты, таблицы разбора симптомов, ориентиры для SLO и FAQ, чтобы переносить исправления во внутренние runbook. Для контекста по «локальному» развёртыванию шлюза см. материал OpenClaw и задержки агентов на Mac mini.
1. Почему MCP ломается на удалённых Mac-шлюзах
MCP (Model Context Protocol) — это структурированные сообщения поверх транспорта. На ноутбуке сбой виден сразу в терминале; на арендованном или колокейшенном Mac шлюз часто крутится под launchd без login-shell, с другим рабочим каталогом и PATH без Homebrew или Volta — и stdio-серверы падают до первой строки лога.
- Дрейф окружения — интерактивный SSH подхватывает
~/.zprofile, демон — нет. Команды из SSH даютspawn ENOENTпод шлюзом. - Несовпадение транспорта — Streamable HTTP и SSE требуют согласованных ревизий протокола, заголовков
Acceptи поведения TLS. Прокси с буферизацией или gzip без сброса даёт «несовпадение версии» или 406 при живой сети. - Слои тайм-аутов — клиент модели, шлюз OpenClaw, MCP-сервер и сам инструмент задают разные дедлайны. Расширение только одного слоя маскирует баг и вешает задания на общих физических узлах.
Если вы выводите Streamable HTTP через тот же периметр, что и webhook, повторите дисциплину Bearer-токена и префиксов путей, что и для публичных hook-эндпоинтов, чтобы 401/404 не маскировались под ошибки MCP. Выбор региона узла для глобальных команд — в руководстве по региону облачного Mac-сервера.
2. stdio и Streamable HTTP: когда какой транспорт
Выбирайте транспорт с минимумом движущихся частей на одном хосте; переходите на HTTP, когда нужно шарить сервер или выносить авторизацию на прокси.
| Критерий | stdio MCP-сервер | Streamable HTTP MCP-сервер |
|---|---|---|
| Радиус поражения при сбое | Изолированный дочерний процесс; шлюз перезапускает один сервер. | Общий порт и TLS-сертификат; ошибка конфигурации бьёт по всем клиентам URL. |
| Чувствительность к PATH и cwd | Высокая — типичный режим отказа ENOENT. | Ниже для разрешения бинарника (сервер под systemd/launchd), выше для апстрим-URL. |
| Мультитенантность / удалённые клиенты | Один процесс шлюза на машину без ручного мультиплексирования. | Естественно — один HTTP-сервер, много вызывающих за auth. |
| Наблюдаемость | Структурные логи шлюза + stderr дочернего процесса. | Добавьте access-лог прокси, тайминги upstream и трассировку ALPN/TLS. |
3. Семь шагов воспроизводимой выкатки
- Зафиксировать личность процесса — пользователь OpenClaw, label LaunchAgent/ plist или unit, cwd из
launchctl print. - Проиграть stdio без шлюза — от этого пользователя:
/bin/bash -lc 'which node; node -v'и точная команда MCP с тем же env. - Укрепить конфиг stdio — абсолютные
command, явныйargs, при необходимостиcwdи блокenv(см. JSON ниже). - Опционально HTTP — слушать
127.0.0.1, TLS на nginx/Caddy,curl -vдля проверки согласованияAccept. - Зафиксировать версии — закрепить MCP SDK / пакет сервера в той же major.minor, что клиент внутри OpenClaw; записать в changelog.
- Бюджет тайм-аутов — измерить P95
tools/callна реалистичных входах; клиентский wait ≥ P95×1,5 с жёстким потолком. - Контракт логов — одна JSON-строка на
initialize,tools/listиtools/callс общим correlation id.
Для сценариев агентов 7×24 зафиксируйте, кто владеет перезапуском plist, ротацией логов и политикой обновлений Node — иначе тайм-ауты MCP окажутся симптомом «плавающего» окружения, а не сети.
4. Фрагменты конфигурации CLI (пример JSON)
Подстройте ключи под схему OpenClaw или хоста; критичны абсолютные пути и явные блоки окружения.
stdio-сервер с точкой входа Node (macOS)
{
"mcpServers": {
"repo-tools": {
"command": "/opt/homebrew/bin/node",
"args": ["/usr/local/lib/mcp-servers/repo-tools/dist/main.js"],
"cwd": "/Users/shared/mcp/repo-tools",
"env": {
"PATH": "/opt/homebrew/bin:/usr/bin:/bin",
"NODE_ENV": "production"
}
}
}
}
stdio через login-shell (когда нужно подтянуть профили)
{
"mcpServers": {
"legacy-npx": {
"command": "/bin/bash",
"args": ["-lc", "exec npx --yes @example/[email protected]"],
"env": { "HOME": "/Users/shared" }
}
}
}
Streamable HTTP (ссылка на стороне клиента)
{
"mcpServers": {
"http-shared": {
"url": "https://mcp.internal.example.com/v1/mcp",
"headers": {
"Authorization": "Bearer ${MCP_EDGE_TOKEN}"
}
}
}
}
5. Runbook по симптомам
5.1 spawn ENOENT (stdio)
| Сигнал | Вероятная причина | Порядок исправления |
|---|---|---|
ENOENT на node |
В PATH демона нет Homebrew. | Абсолютный command или PATH в env. |
| ENOENT на пути скрипта | Неверный cwd или symlink недоступен пользователю сервиса. | Задать cwd; заменить symlink на realpath. |
| Работает только в SSH | Интерактивная оболочка и launchd экспортируют разное. | Обёртка bash -lc или перенос переменных в EnvironmentVariables plist. |
5.2 Версия протокола / 406 (Streamable HTTP)
Сравните логи рукопожатия сервера и клиента. Если сервер ждёт text/event-stream, а прокси включает gzip без сброса буфера, клиент «зависает» с формулировкой про несовпадение версии при совпадающем semver.
5.3 Тайм-ауты инструментов
Зафиксируйте три таймера: (A) ожидание на стороне модели/маршрутизатора, (B) дедлайн шлюза к upstream, (C) внутренний тайм-аут задачи в MCP-сервере. Сначала ослабляйте самый «тесный» слой, соседние — только если трейсы показывают очередь.
6. Цифры для внутренних SLO
- ~4 Вт — типичное потребление Mac mini на Apple Silicon в простое при SSH и лёгких шлюзах; удобно для TCO против простаивающих x86-башен.
- 25 с — ориентир верхней границы «быстрого» P95 для
tools/callна общих узлах; дальше — дробить инструмент или стримить частичные результаты вместо бесконечного роста тайм-аутов. - 600 с — тяжёлые обслуживающие операции (полный скан репозитория) лучше вынести в асинхронные задания с опросом статуса, а не в один блокирующий вызов MCP — по аналогии с длинными git/npm в CI-зеркалах.
7. FAQ
Запускать MCP-серверы от root?
Лучше выделенный сервисный пользователь с ACL на workspace; root ломает привычные macOS privacy-запросы и усложняет аудит TCC.
Влияет ли Rosetta на бинарники MCP?
Да: смесь arm64 Node и нативных аддонов только x64 даёт мгновенные циклы падений, похожие на тайм-ауты. Стандартизируйте архитектуру на сервер.
Можно ли корпоративный HTTPS-инспектирующий сертификат?
Корневой MITM нужно импортировать в связку ключей, которой доверяет пользователь сервиса; иначе TLS у Streamable HTTP падает непрозрачными handshake-ошибками.
Где фиксировать смену протокола?
Таблица совместимости во внутренней вики: сборка OpenClaw, версия MCP SDK, хеш пакета сервера и дата последнего smoke-теста tools/list.
8. Этот стек на тихом и экономичном Mac mini
stdio MCP-серверы безжалостны к паритету окружения — такая нагрузка предсказуемее на долгоживущем macOS-хосте с фиксированными путями, Gatekeeper и SIP, чем на импровизированных Windows-ВМ. Apple Silicon Mac mini сочетает очень низкое потребление в простое (порядка нескольких ватт), бесшумное охлаждение и нативный Unix-стек: Node, прокси и шлюзы на launchd могут работать круглосуточно без типичной «пляски» драйверов.
Если вы стандартизируете удалённые шлюзы OpenClaw с MCP-сайдкарами, консолидация на классе оборудования Mac mini M4 сокращает число переменных: одна архитектура для агентов, сборочных инструментов и агентов наблюдаемости, плюс FileVault и TCC дают более чистую историю аудита, чем смесь произвольных Linux-образов.
Чтобы с минимальным трением отрепетировать runbook выше, Mac mini M4 остаётся самым доступным физическим якорем — возьмите узел и перенесите те же JSON-конфиги, что проверили на staging.
Нужен стабильный физический Mac для OpenClaw и MCP?
Арендуйте узел Mac mini с тем же macOS-стеком, что в этом runbook: низкое потребление в простое, тихая работа 7×24 и предсказуемые пути для stdio-серверов.