Читать 7 мин

Почему ошибки запуска MCP-серверов выглядят одинаково?

Сбои запуска MCP-сервера становятся диагностируемыми, если разделить запуск, рукопожатие, обнаружение инструментов и доказательства внешних действий.

Почему ошибки запуска MCP-серверов выглядят одинаково?

Клиент MCP может сообщить, что сервер «не удалось запустить», даже если операционная система уже запустила процесс, процесс прочитал входные данные, а сервер успел обратиться к чему-то за пределами машины. Это сообщение не является диагнозом. В него сваливают ошибки запуска, протокола, обнаружения и иногда выполнения инструментов.

Считайте запуск последовательностью границ, каждая из которых оставляет доказательства. Если вы не можете сказать, какую границу прошел сервер, нельзя понять, безопасен ли повтор, могли ли использоваться учетные данные или клиент просто не смог показать исправный сервер. Решение не в увеличении тайм-аута. Нужно разделить состояния и сделать каждое наблюдаемым.

Один красный статус скрывает четыре разные ошибки

Оператору нужны четыре ответа по порядку: запустил ли клиент настроенную команду, завершили ли обе стороны инициализацию MCP, получил ли клиент пригодный список инструментов и достиг ли какой-либо код внешнего канала. Каждый ответ доказывает разные вещи.

Процесс может завершиться еще до того, как появится в обычном смысле. Может отсутствовать исполняемый файл, рабочий каталог, менеджер пакетов может завершиться до вызова вашего кода, а дочерний процесс может сразу остановиться из-за отсутствующей переменной окружения. Назовем это ошибкой запуска. MCP-сессии еще нет, и код приложения мог вообще не выполниться.

Процесс может существовать и все равно не пройти обмен протоколом. При stdio дочерний процесс получает stdin и stdout, соединенные с клиентом. Сервер должен читать JSON-RPC из stdin и записывать в stdout только сообщения JSON-RPC. Затем он должен ответить на запрос клиента initialize совместимой версией протокола и объявленными возможностями. После этого клиент отправляет notifications/initialized. Если последовательность не завершилась, это ошибка рукопожатия.

Успешное рукопожатие еще не доказывает, что клиент узнал об инструментах. Сервер может объявить поддержку инструментов, но завершиться с ошибкой при их регистрации, создать недопустимую схему входных данных, вернуть неправильный результат tools/list или пустой список, потому что его конфигурация отключила все инструменты. Это ошибка обнаружения инструментов. Клиент и сервер могут быть достаточно исправны для обмена сообщениями, но агенту нечего вызывать.

Наконец, сервер может пройти обнаружение и завершиться с ошибкой только при запуске инструмента. Это ошибка выполнения инструмента. Ее нужно записывать в отдельный инцидент. Если смешать ее с запуском, кто-нибудь обязательно повторит запуск сервера, который уже отправил HTTP-запрос или открыл SSH-соединение.

Документация Model Context Protocol позволяет увидеть это разделение, даже если многие интерфейсы клиентов его скрывают. В рекомендациях по отладке отдельно рассматриваются проблемы процесса и конфигурации, протокол и журналы, а для локальных stdio-серверов отдельно отмечается необходимость держать обычные журналы вне stdout. Жизненный цикл инициализации протокола и запрос tools/list являются разными обменами. Сохраняйте это различие в собственной телеметрии, а не принимайте общий ярлык клиента.

Ошибка запуска заканчивается до появления MCP

Ошибка запуска означает, что клиент не получил пригодный дочерний процесс с читаемым протокольным потоком. Она не означает, что команда «выглядела правильно» в терминале.

Интерактивная оболочка многое скрывает. В ней есть свой PATH, текущий каталог, менеджеры версий языков, учетные данные и dotfiles, которые приложение для рабочего стола или подпроцесс агента может не получить. В macOS клиент может запускать процесс из /. Он может использовать ограниченное окружение. Команда может передаваться как исполняемый файл с массивом аргументов, а не через оболочку, поэтому алиасы и перенаправления оболочки не сработают.

До попытки рассуждать о MCP сохраните точную запись запуска:

run_id=run_01JX...
phase=launch
command=/usr/local/bin/node
argv=["/Users/dev/work/acme-mcp/dist/index.js"]
cwd=/
pid=84217
started_at=2026-07-22T14:03:12.417Z

После завершения процесса или истечения срока рукопожатия сохраните конечное событие:

run_id=run_01JX...
phase=launch
exit_code=1
signal=null
stderr=Error: ENOENT: no such file or directory, open './config.json'

Такая запись быстро разрешает распространенный спор. У сервера не было «проблемы MCP». Он ожидал, что относительный путь разрешится относительно каталога проекта, а клиент запустил его из /.

Используйте абсолютные пути для исполняемого файла, точки входа, конфигурации и любых файлов, которые читаются при запуске. Руководство по отладке MCP прямо указывает на неопределенный рабочий каталог серверов, запущенных клиентом, и рекомендует абсолютные пути. Это не вопрос стиля. Так устраняется источник ошибок, которые появляются только после установки той же конфигурации на другой машине.

Не объявляйте запуск успешным только потому, что получили PID. PID говорит, что ядро создало процесс. Он ничего не говорит о загрузке программы, целостности канала stdout или о том, не превратился ли процесс уже в зомби, ожидающий обработки.

Полезная машина состояний запуска невелика:

not_requested
  -> spawn_requested
  -> spawned
  -> executable_ready
  -> handshake_pending

spawned означает, что родитель получил PID дочернего процесса. executable_ready означает, что дочерний процесс после загрузки конфигурации и установки обработчика критических ошибок записал в stderr намеренное событие готовности, не относящееся к протоколу. Не отправляйте это событие в stdout. В stdio-сервере stdout не является каналом журналов, который случайно оказался рядом. Это провод протокола.

Событие готовности не должно утверждать, что сервер подключен к API, базе данных или удаленному узлу. Оно должно сообщать только доказанный факт: процесс дошел до настройки транспорта MCP. Строка ready=true становится опасной, если команды начинают понимать ее как «инструменты можно безопасно вызывать». Лучше явно назвать этап.

У рукопожатия узкое определение

Ошибка рукопожатия MCP начинается после появления пригодного процесса и заканчивается до завершения жизненного цикла инициализации. Не называйте ее ошибкой подключения, пока не проверите сообщения.

Для транспорта stdio важны первые байты в stdout. Обычный баннер запуска может повредить поток еще до того, как сервер увидит запрос. То же может сделать зависимость, печатающая уведомление об обновлении, console.log, Python print, форматировщик исключений или скрипт-обертка, который пишет статус в stdout. Официальные рекомендации MCP по сборке и отладке говорят об этом прямо: для stdio-серверов журналы нужно писать в stderr, потому что stdout несет протокольные сообщения.

Минимальная полезная трассировка исправной инициализации выглядит так:

{"direction":"in","id":1,"method":"initialize"}
{"direction":"out","id":1,"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"acme","version":"1.4.0"}}}
{"direction":"in","method":"notifications/initialized"}

Точная версия протокола зависит от версий, которые поддерживают клиент и сервер. Важно, что сервер выбрал принятую клиентом версию, вернул корректный результат и получил уведомление о завершении. Сохраняйте разобранное событие для каждого сообщения, а не необработанные данные, содержащие учетные данные.

Если трассировка начинается так, диагноз меняется:

stdout: Starting Acme MCP server
{"jsonrpc":"2.0","id":1,"method":"initialize",...}

Сервер может быть вполне способен ответить, но JSON-парсер клиента уже встретил недопустимый ввод. Тайм-аут после этого не означает, что сервер работал медленно. Он означает, что транспорт был поврежден.

Другая знакомая ошибка выглядит лучше:

phase=handshake
initialize_received=true
initialize_response_sent=false
fatal_error=Cannot read properties of undefined (reading 'tools')

Дочерний процесс запустился и получил запрос, но завершился при подготовке ответа. Это ошибка сервера или необработанное предположение о конфигурации, а не неправильная конфигурация клиента.

Делайте границы явными в журналах:

phase=handshake event=initialize_received run_id=run_01JX request_id=1
phase=handshake event=initialize_responded run_id=run_01JX request_id=1 protocol_version=2025-06-18
phase=handshake event=initialized_received run_id=run_01JX

Если записывать только connected=true, исчезает единственный бит информации, отличающий отправленный ответ от завершенного жизненного цикла инициализации. Клиент может закрыть или перезапустить процесс после получения ответа, но до отправки уведомления. С операционной точки зрения это не то же самое, что ошибка разбора инициализации.

Задайте для рукопожатия отдельный срок. Начинайте отсчет при создании процесса или, если это наблюдаемо, при готовности транспорта. Останавливайте его при получении notifications/initialized. При истечении срока сообщайте последнее подтвержденное событие, например spawned_no_initialize, initialize_received_no_response или response_sent_no_initialized. Такие имена подсказывают оператору, какую сторону проверять первой.

Обнаружение инструментов завершается после того, как сервер уже доступен

Ошибка обнаружения инструментов означает, что клиент и сервер могут говорить по MCP, но клиент не получил пригодный ответ на tools/list. Ее часто принимают за ошибку запуска, потому что многие клиенты ищут инструменты сразу после инициализации.

Не считайте пустую панель инструментов доказательством пустого результата tools/list. Некоторые клиенты скрывают инструменты после ошибки проверки схемы, кэшируют результаты или запрашивают инструменты только при начале задачи агентом. Другие подключаются к MCP-серверу ради ресурсов или подсказок и вообще не запрашивают инструменты. В доказательствах должны быть и запрос, и ответ.

Исправная трассировка обнаружения имеет такой вид:

{"direction":"in","id":2,"method":"tools/list"}
{"direction":"out","id":2,"result":{"tools":[{"name":"issue_lookup","description":"Fetch one issue by identifier","inputSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}]}}

В записи обнаружения указывайте число инструментов и дайджест нормализованных схем. Дайджест помогает понять, был ли в двух запусках один и тот же объявленный интерфейс, не сохраняя чувствительные описания или конфигурацию. Он также выявляет случайные изменения, когда инструмент остался, но обязательные параметры исчезли.

Не создавайте определения инструментов через обращение к внешнему сервису во время tools/list. Такой дизайн превращает обнаружение в побочный эффект, делает обновление списка похожим на выполнение и порождает худший вопрос при инциденте: «Изменило ли что-нибудь перечисление инструментов?» По возможности регистрация инструментов должна быть локальной и детерминированной.

Серверу может понадобиться конфигурация, чтобы решить, объявлять ли инструмент. Прочитайте ее при запуске и запишите результат, но не заставляйте обнаружение ждать обновления токена или SSH-проверки. Если инструменту нужны учетные данные, проверьте наличие локальной ссылки на них, не используя их. Реальное удаленное действие отложите до вызова инструмента клиентом.

Это важно для контроля агента. Если агент обращается к Sallyport через sp mcp, успешная запись обнаружения MCP показывает только то, что оболочка открыла вызываемые операции, а не то, что Sallyport выполнил HTTP- или SSH-действие.

Есть одна законная причина вернуть пустой список: в текущей конфигурации у сервера нет включенных инструментов. Укажите это в структурированном ответе или журнале для клиента. Не завершайтесь с ошибкой при регистрации, заставляя клиента гадать, был ли набор инструментов намеренно пустым.

phase=discovery event=tools_list_responded run_id=run_01JX tool_count=0 reason=no_enabled_tools

Такая запись дает оператору конкретную проблему конфигурации. Общая ошибка запуска оставляет лишь суеверие, которое повторяют снова.

Для внешней доступности нужно отдельное доказательство

Видите каждое действие отдельно
Журнал действий фиксирует отдельные операции и дает доказательства внешних вызовов, которых нет в статусе запуска клиента.

На вопрос «достиг ли процесс внешнего канала?» нельзя ответить по PID, успешному рукопожатию или заполненному списку инструментов. Нужна запись на границе, где код пытается выполнить внешнее действие.

Определяйте внешний канал узко. Сюда входят исходящий HTTP-запрос, запуск SSH-помощника, подключение к базе данных за пределами локального процесса, обновление облачных учетных данных, публикация в очереди сообщений и любой вызов, который может создать эффект или раскрыть информацию за пределами MCP-сессии. Чтение локального файла конфигурации не считается внешним каналом. Само по себе извлечение учетных данных из защищенного локального хранилища тоже не считается. Их отправка в запросе считается.

Записывайте попытку до начала вызова, затем ее результат. Используйте непрозрачный идентификатор действия, который можно связать с ID запроса MCP и ID запуска сервера.

run_id=run_01JX phase=execution event=external_attempt action_id=act_8Qf tool=issue_lookup channel=https host=api.example.test
run_id=run_01JX phase=execution event=external_result action_id=act_8Qf status=200 duration_ms=184

Не помещайте в записи заголовки авторизации, bearer-токены, подписанные URL, аргументы команд с секретами или полные тела ответов. Журнал инцидента, раскрывший учетные данные, которые он должен был расследовать, только усугубит ситуацию.

Расположение external_attempt имеет практическое значение. Если записать его слишком рано, можно заявить о внешнем вызове, хотя код лишь собрал объект запроса. Если слишком поздно, тайм-аут или падение процесса оставит пробел после того, как байты уже покинули машину. Отправляйте событие сразу перед вызовом библиотеки, который может начать сетевую или SSH-активность.

Пример сбоев показывает, почему это важно. Оператор добавляет MCP-сервер, который читает токен трекера задач при инициализации модуля и вызывает endpoint «кто я», чтобы его проверить. Дочерний процесс запускается, пишет отладочную строку в stdout и повреждает первое сообщение MCP. Клиент показывает «сервер не удалось запустить». Команда дважды перезапускает клиент.

Без записей этапов команда решает, что запрос не покинул машину, поскольку сервер не появился в интерфейсе клиента. Это неверно. Вызов при инициализации модуля выполнился до отправки клиентом initialize и трижды обратился к трекеру задач. Состояние интерфейса ничего не сказало о внешней доступности.

Перенесите проверку личности в намеренно доступный для чтения инструмент или выполняйте ее в рамках первого действия, которому действительно нужен удаленный сервис. Тогда это будет выполнение инструмента. Сервер сможет запуститься, инициализироваться и показать инструменты, не обращаясь к сети. Оператор сможет различать «сервер доступен» и «учетные данные и удаленный сервис работают». Это разные факты, их нужно разделять.

Журнал этапов превращает расплывчатые инциденты в проверяемые утверждения

Создавайте одну запись журнала на каждый запуск и добавляйте неизменяемые события этапов. Сложный движок правил не нужен. Нужны стабильные имена, временные метки и поля корреляции, достаточные для восстановления событий.

Используйте такую форму:

{
  "run_id": "run_01JX",
  "server_name": "acme",
  "pid": 84217,
  "phase": "discovery",
  "event": "tools_list_responded",
  "request_id": 2,
  "tool_count": 4,
  "at": "2026-07-22T14:03:13.083Z"
}

Журнал должен хранить события, а не выводы, вставленные в строку. phase=handshake и event=initialize_received можно подсчитать, найти запросом и проверить. message="MCP seems stuck" нельзя.

Держите модель состояний простой:

  1. spawn_requested, spawned, executable_ready и exited относятся к запуску.
  2. initialize_received, initialize_responded и initialized_received относятся к рукопожатию.
  3. tools_list_received и tools_list_responded относятся к обнаружению.
  4. tool_call_received, external_attempt и external_result относятся к выполнению.
  5. revoked, terminated и client_disconnected описывают прерывание, а не успех.

Команды часто смешивают установление сессии и полномочия на действие. Сервер может установить MCP-сессию, не имея права использовать учетные данные или подключаться к удаленной системе. Если считать это одним состоянием, событие одобрения будет выглядеть как событие подключения, а отклоненное действие как неудачный запуск.

Храните события авторизации рядом с вызовом, которым они управляют. Например, записывайте authorization_requested и authorization_granted после tool_call_received, но до external_attempt. Тогда оператор сможет доказательно сказать, что запрос инструмента поступил, человек его отклонил и внешней попытки не было. Это гораздо точнее, чем сказать, что запрос «не завершился».

Используйте ID запуска только для одного дочернего процесса. Не используйте имя сервера как идентификатор корреляции. Клиент может запустить две копии одного сервера, перезапустить одну после тайм-аута и сохранить старые метаданные инструментов. Повторно используемые идентификаторы смешают отдельные попытки в вымышленную историю.

Хешируйте или скрывайте значения, раскрывающие данные пользователя. Обычно нужны имя инструмента, хост endpoint, класс статуса, класс ошибки и время выполнения. Строка запроса, тело запроса или ответ обычно не нужны. Оператору нужно доказать прохождение границы, а не восстановить пользовательские данные из журналов.

Проверяйте границы, не полагаясь на весь клиент

Отзывайте конкретный запуск
Журнал сессий фиксирует запуски агентов и позволяет сразу отозвать запуск, если его поведение изменилось.

Полный клиент полезен для интеграционных тестов, но плох как первый источник сведений. Его интерфейс может объединять ошибки, кэшировать возможности, перезапускать дочерние процессы и применять собственный тайм-аут. Сначала проверяйте каждую границу более узким способом.

Начните с точной команды, окружения и рабочего каталога клиента. Не заменяйте настроенную команду на npm run dev. Не запускайте процесс из каталога проекта, если клиент запускает его из другого места. Перенаправьте stderr в файл для проверки, но оставьте stdout нетронутым, если через него другой процесс будет говорить по MCP.

Для stdio-сервера первым протокольным тестом используйте официальный MCP Inspector. Документация MCP рекомендует Inspector для проверки серверов через разные транспорты, а проект Inspector умеет напрямую запускать команду stdio. Он позволяет увидеть обмен инициализации и вызвать tools/list, не гадая, что настольный клиент сделал с результатом.

Затем сведите тест к трем проверкам:

1. Остается ли настроенная команда работать достаточно долго, чтобы получить initialize?
2. Возвращает ли она корректный ответ initialize и получает ли initialized?
3. Возвращает ли tools/list ожидаемые имена инструментов и схемы?

Только после этого вызывайте инструмент, который обращается к внешней системе. Выберите безопасное действие только для чтения. Убедитесь, что журнал выполнения содержит один external_attempt и один конечный результат. Изменяющие данные операции проверяйте в одноразовом окружении или используйте отдельный режим без обращения к рабочей конечной точке.

Для HTTP-транспортов добавляйте доказательства HTTP, но не смешивайте их с состоянием MCP. Записывайте метод запроса, путь endpoint, статус, идентификатор сессии, если он есть, и то, содержал ли ответ JSON или начинался с потока событий. TCP-соединение или HTTP 200 сами по себе не означают завершения инициализации MCP. После достижения запроса сервером применяйте те же записи жизненного цикла.

Храните в тестах сервер-заглушку, который намеренно завершается на каждой границе. Один экземпляр завершается до чтения входных данных. Другой пишет hello в stdout перед ответом. Третий отвечает на initialize, а затем возвращает недопустимую схему инструмента. Четвертый показывает один инструмент, обработчик которого записывает внешнюю попытку и возвращает контролируемую ошибку. Если интеграция клиента превращает все четыре случая в одно оповещение, исправьте интеграцию до того, как реальный сервер заставит вас отлаживать вслепую.

Тайм-ауты и повторы должны принадлежать конкретным этапам

Проверяйте полномочия до внешних вызовов
Заблокированное хранилище отклоняет любое действие, поэтому доступную MCP-сессию нельзя принять за полномочия.

Один тайм-аут запуска подталкивает к неправильному исправлению. Медленная загрузка пакета, ошибка разбора инициализации, исключение схемы и зависание удаленного API выглядят одинаково. Используйте отдельные сроки, потому что каждый принадлежит своему владельцу.

Запускающая сторона отвечает за период от spawn_requested до spawned. Сервер и транспорт отвечают за период от создания процесса до initialized_received. Путь регистрации сервера отвечает за обнаружение. Обработчик инструмента и его удаленная зависимость отвечают за выполнение. Называйте тайм-аут по владельцу и записывайте последнее подтвержденное событие этапа.

error=handshake_timeout last_event=initialize_received run_id=run_01JX

Это действие, а не догадка. Оно подсказывает сопровождающему сервер проверить подготовку ответа и stderr, а не удаленный API.

Автоматический повтор безопасен только тогда, когда сбойный этап не создает внешнего эффекта. Повторить неудачный запуск из-за временной недоступности исполняемого файла может быть приемлемо. Повторить запрос обнаружения обычно безопасно, если обнаружение локальное и не меняет состояние. Повторять вызов инструмента после external_attempt опасно, если удаленная операция не поддерживает документированный механизм идемпотентности с переданным значением идемпотентности.

Не прячьте повтор за перезапуском сервера. Если код запуска обновляет токен, создает туннель, отправляет телеметрию или проверяет удаленную личность, перезапуск уже является внешним действием. Это еще одна причина держать запуск локальным и переносить удаленную работу в явные инструменты.

Если клиент завершает дочерний процесс после истечения срока, по возможности запишите событие прерывания до завершения. Сервер может не успеть его сбросить. Родительский процесс должен записать запрос на завершение как отдельное событие и указать последнее событие дочернего процесса, которое он увидел. Так сохраняется честная картина: процесс, возможно, собирался ответить, но утверждать, что он ответил, нельзя.

Сначала сделайте запуск скучным, потом быстрым

Хороший MCP-сервер запускается без сети, использования учетных данных, изменяемых побочных эффектов и неоднозначности в протокольном состоянии. Он загружает локальную конфигурацию, устанавливает транспорт, отвечает на инициализацию и объявляет детерминированный интерфейс. Такое поведение проще сопровождать и безопаснее повторять.

Самая популярная плохая рекомендация звучит так: «проверяйте все при запуске». Она кажется ответственной, потому что ошибки появляются рано. На практике она смешивает локальную конфигурацию, личность, доступность удаленной системы и авторизацию в одном непрозрачном ритуале. Из-за этого клиенты повторяют внешние действия под ярлыком ошибки запуска.

Проверяйте локально все, что можно проверить локально. Отчитывайтесь о доступности удаленной системы через явный инструмент или первую операцию, которой она действительно нужна. Сохраняйте стабильные имена этапов. Для stdio оставляйте stdout только протокольным. Проверяйте намеренно сломанный сервер на каждой границе, которую вы обещаете наблюдать.

Когда следующий клиент сообщит, что MCP-сервер не запустился, по одной записи запуска вы должны ответить на четыре вопроса: запустился ли процесс, завершилась ли инициализация, можно ли было обнаружить инструменты и достигло ли что-либо внешнего мира. Если на все четыре ответить нельзя, статус все еще неоднозначен.

Вопросы и ответы

Почему MCP-клиент показывает одну ошибку для разных проблем запуска?

Разделяйте запуск процесса, инициализацию протокола, обнаружение возможностей и первое внешнее действие. Клиент может показать одну общую ошибку, хотя сбой произошел только на одном из этих этапов. В журналах нужно фиксировать границу, которую процесс прошел на каждом этапе.

Означает ли работающий процесс MCP, что сервер успешно подключился?

Нет. Запущенный процесс доказывает только то, что операционная система создала его и он еще не завершился. Он может загружать конфигурацию, ждать зависимость, писать посторонний текст в stdout или игнорировать запрос initialize от клиента.

Может ли вывод в stdout сломать MCP-сервер stdio?

Для stdio-сервера stdout является каналом протокола. Баннер, трассировка стека, уведомление менеджера пакетов или обычная команда print могут повредить поток JSON-RPC до того, как сервер ответит на initialize. Диагностический вывод отправляйте в stderr.

Что такое рукопожатие инициализации MCP?

Клиент отправляет запрос initialize, сервер возвращает совместимую версию протокола и свои возможности, после чего клиент отправляет уведомление notifications/initialized. Если сервер запустился, но не завершил этот обмен, это ошибка рукопожатия, а не проблема инструментов.

Что означает сбой обнаружения инструментов MCP?

Это значит, что клиент прошел инициализацию, но не получил пригодный результат от tools/list. Причиной может быть отсутствующий обработчик, исключение при построении схем, неподдерживаемое объявление возможностей или то, что клиент вообще не запрашивает инструменты.

Должен ли MCP-сервер обращаться к внешнему API при запуске?

Не помещайте сетевой запрос, вход по SSH, обновление токена или поиск секрета в запуск сервера, если без этого сервер не может работать. Сначала запустите протокольную точку, затем выполняйте внешний вызов внутри обработчика инструмента и записывайте его как отдельное действие.

Как воспроизвести сбой запуска MCP вне клиента?

Выполните ту же команду с тем же пользователем, рабочим каталогом и окружением, которые использует клиент. Затем проверьте сервер с помощью MCP Inspector или контролируемого обмена JSON-RPC. Тест из терминала может скрыть настоящую причину сбоя.

Что записывать при диагностике запуска MCP-сервера?

При запуске создайте уникальный идентификатор запуска и добавляйте его к событиям stderr, протокольным событиям, обнаружению инструментов и каждому исходящему запросу. Записывайте PID, путь к исполняемому файлу, код завершения и идентификатор внешнего действия. По умолчанию не записывайте учетные данные и тела запросов.

Каким должен быть тайм-аут запуска MCP?

Ограничение по времени полезно, но оно должно относиться к конкретному этапу. Используйте отдельный короткий срок для запуска, другой для инициализации и еще один для tools/list. Иначе одно сообщение о тайм-ауте уничтожит нужную вам диагностику.

Безопасно ли автоматически повторять неудачный запуск MCP-сервера?

Нет. Повтор запуска может повторить побочные эффекты, если код запуска создает файлы, обновляет токены или обращается к сервисам. Повторяйте только тот этап, для которого точно известно отсутствие внешнего эффекта, и присваивайте каждой попытке новый идентификатор запуска.

Sallyport

Sallyport выполняет API-вызовы и SSH-команды за вашего ИИ-агента. Ключи остаются в локальном хранилище на вашем Mac; вы подтверждаете каждый запуск, и каждое действие попадает в запечатанный журнал.

© 2026 Sallyport · Открытый код по лицензии Apache-2.0 · Oleg Sotnikov