Читать 7 мин

Удалите заброшенные MCP-серверы и не оставляйте доступ

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

Удалите заброшенные MCP-серверы и не оставляйте доступ

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

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

Удаленная конфигурация не означает отозванный доступ

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

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

Спецификация Model Context Protocol описывает серверы как поставщиков возможностей, например инструментов, ресурсов и промптов. Она также поддерживает разные транспорты, включая stdio и подключения на основе HTTP. При выводе сервера из эксплуатации это различие важно. Сервер stdio может работать только тогда, когда локальный клиент запускает его команду. Удаленный сервис останется доступным даже после того, как все разработчики удалят локальную запись, которая на него указывала.

Не смешивайте следующие понятия:

  • Запись конфигурации сообщает конкретному клиенту, где найти сервер.
  • Средство запуска это исполняемый файл, скрипт, команда контейнера, расширение или сервис, который запускает сервер или обращается к нему.
  • Предоставленное полномочие это токен, SSH-идентификация, разрешение OAuth, сессия аккаунта или сетевое разрешение, позволяющее действию выполниться.
  • Запись выполнения показывает, что клиент или агент действительно использовал этот путь.

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

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

Сначала составьте список клиентов, затем ищите на диске

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

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

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

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

ПолеЧто записать
Клиент и путь к конфигурацииКакая программа читает файл и где он находится
Имя сервераМетка, которую видит агент или пользователь
Транспорт и средство запускаКоманда stdio, URL, расширение, контейнер или скрипт
Владелец и назначениеОтветственный человек и текущая работа, которую поддерживает сервер
Целевые системыAPI, хосты, репозитории, хранилища данных или локальные каталоги, к которым есть доступ
Источник полномочийХранилище токенов, переменная окружения, SSH-идентификация, разрешение OAuth или управляемая идентификация
РешениеОставить, заменить, приостановить или вывести из эксплуатации

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

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

Ищите средства запуска, а не только файлы с названием MCP

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

В macOS эта команда дает ограниченный начальный список вероятных JSON-файлов конфигурации в домашнем каталоге. Кэш намеренно пропущен, иначе вы получите множество нерелевантных метаданных пакетов.

find "$HOME" -type f \( -name '.mcp.json' -o -name 'mcp.json' -o -name '*mcp*.json' \) \
  -not -path "$HOME/Library/Caches/*" \
  -print 2>/dev/null

Ожидаемый вид вывода:

/Users/dev/work/acme-api/.mcp.json
/Users/dev/Library/Application Support/example-client/settings.json
/Users/dev/.config/example-agent/mcp.json

Этот список служит доказательством, а не перечнем файлов для удаления. Откройте каждый файл и определите, какому клиенту он принадлежит. Файл с mcp в имени может быть документацией, архивным экспериментом или сгенерированным lock-файлом. И наоборот, файл настроек с обычным названием может содержать настоящее определение сервера.

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

jq -r '
  .mcpServers // empty
  | to_entries[]?
  | [.key, (.value.command // .value.url // "unknown"),
     ((.value.args // []) | join(" "))]
  | @tsv
' path/to/config.json

Обычно результат выглядит так:

issue-tracker	npx	-y @example/issues-mcp
legacy-reporting	https://reports.internal.example/mcp	

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

Затем проверьте точки запуска, которые переживают обычную очистку файлов. На Mac это профили оболочки, настройки задач редактора, глобальные бинарные файлы менеджеров пакетов и пользовательские launch agents. Команда launchctl print gui/$(id -u) может показать процессы, запускаемые вошедшим пользователем, но ее вывод способен раскрыть аргументы команд или значения окружения. Просматривайте его локально и не вставляйте в задачу или чат.

Ищите содержимое по узким запросам, а не сканируйте и не выгружайте весь домашний каталог. Например, если вы знаете, что заброшенный сервер вызывает old-report, ищите это точное имя, старый хост и исполняемый файл. Такой подход находит обертки вроде scripts/agent-tools.sh, не превращая проверку в сбор личных данных.

Определите текущие полномочия каждого сервера

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

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

  1. Нет удаленных полномочий. Сервер читает локальные несекретные файлы или создает локальный результат. Он все еще может создавать проблемы цепочки поставок или конфиденциальности, но отзыв обычно означает удаление разрешений процесса и конфигурации.
  2. Полномочия из окружения. Средство запуска получает API-токен, пароль или строку подключения через профиль оболочки, файл .env, настройку IDE или конфигурацию запуска.
  3. Полномочия из файла. Средство запуска читает закрытый SSH-ключ, сертификат клиента, файл сервисного аккаунта или локальную базу учетных данных.
  4. Полномочия под управлением провайдера. Сервер использует OAuth, установку приложения, вход с устройства или управляемую идентификацию. Разрешением управляет провайдер, а не локальный текстовый файл.
  5. Сетевые полномочия и полномочия аккаунта. Явный секрет не нужен, поскольку корпоративная сеть, локальный аккаунт, VPN-сессия или разрешенный адрес позволяют обратиться к сервису. Эту категорию легко пропустить и сложно корректно вывести из эксплуатации.

Для каждого источника полномочий запишите точный аккаунт, область действия и цель. Записи «токен Git» недостаточно. Нужно знать, принадлежит ли он личному аккаунту, аккаунту бота или общей машинной идентификации, а также может ли он читать репозитории, создавать задачи, запускать развертывания или обращаться к административным API.

Именно здесь очистка выявляет неудобные компромиссы. Локальная MCP-команда, получающая широкий личный токен через ~/.zshrc, не становится безопасной только потому, что разработчик перестал ею пользоваться. Тот же токен могут использовать другие скрипты, поэтому для его отзыва нужно согласовать зависимости. Это не повод откладывать работу, а причина сначала их изучить.

Ведите инвентаризацию по фактам. Не помещайте в нее значения токенов, закрытые ключи, полные заголовки авторизации или скопированное содержимое конфигураций. Ссылки вроде «учетные данные с именем reporting-read» или «отпечаток SSH, заканчивающийся на 3f:91» позволяют нужному человеку найти полномочия и не создают еще одно хранилище секретов.

Сначала отзовите доступ в сервисе, затем удаляйте локальные следы

Закройте забытые пути доступа
Когда хранилище заблокировано, Sallyport отклоняет все HTTP- и SSH-действия подключенных агентов.

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

Для API-токенов воспользуйтесь интерфейсом управления токенами провайдера или задокументированной конечной точкой отзыва. Убедитесь, какой именно токен вы отзывает: проверьте его идентификатор, метку, аккаунт, данные о создании или последнем использовании, если провайдер их показывает. Затем удалите его значение из локальных файлов и хранилищ учетных данных. Никогда не проверяйте отозванный токен, вставляя его в веб-форму или команду оболочки, которая может сохранить его в истории.

С OAuth нужна особая осторожность. RFC 7009 определяет запрос на отзыв токена, отправляемый на конечную точку отзыва сервера авторизации. Сервер также может вернуть успешный ответ, даже если токен недействителен. Это не позволяет вызывающей стороне узнать, существует ли токен. Поэтому код 200 сам по себе не доказывает, что отозван нужный грант. Проверьте страницу авторизаций или подключенных приложений у провайдера, а затем выполните контролируемый вызов через старый путь, только если это допускается вашей обычной практикой безопасности.

Для SSH удалите открытый ключ или ключ развертывания в каждом месте, где он принимается. Это могут быть авторизованные ключи аккаунта, настройки ключей развертывания репозитория, аккаунт bastion, сервис CI и источник управления конфигурацией, который заново заполняет authorized_keys. Удаление ~/.ssh/old_agent_key убирает только одну локальную копию. Оно ничего не делает с другой копией и с авторизацией на сервере.

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

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

Запишите результат отзыва как событие: кто его выполнил, какие полномочия отозвал, где это произошло и как результат проверили. Не сохраняйте секреты и снимки экрана с ними. Такая запись пригодится, если позже репозиторий перестанет работать и кто-то спросит, не стала ли причиной очистка.

Удаляйте локальные определения в обратимой последовательности

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

Для одного сервера используйте такую последовательность:

  1. Остановите нужный клиент агента и расширение редактора. Работающий клиент может удерживать дочерний процесс или переписать настройки при выходе.
  2. Скопируйте в запись о выводе из эксплуатации несекретные поля сервера: имя, команду или URL, аргументы, ожидаемую цель, владельца и дату удаления. Вместо секретных значений укажите, где они находились.
  3. Отзовите полномочия в целевом сервисе и запишите сведения о подтверждении.
  4. Удалите запись сервера из всех найденных конфигураций на уровне пользователя и проекта. Удалите переменные окружения и ссылки на устаревшие файлы учетных данных.
  5. Удалите выделенный пакет, расширение, образ контейнера или скрипт-обертку, если их не использует ни один активный сервер. Если пакет нужен другой работе, удалите только заброшенную команду и опишите общую зависимость.

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

Для JSON подойдет простая проверка синтаксиса через jq:

jq empty path/to/config.json && echo "valid JSON"

Она доказывает, что JSON разбирается. Это не подтверждает, что клиент принимает схему и что удалены все ссылки. После редактирования прочитайте нужный объект, затем проверьте список серверов в самом клиенте.

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

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

Докажите, что сервер больше не запускается и не получает доступ

Поместите MCP за шлюз действий
Подключите Claude Code или другого агента с поддержкой MCP через sp mcp, а Sallyport оставит границу полномочий на локальной машине.

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

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

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

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

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

Типичный сбой выглядит так: разработчик удаляет legacy-reporting из личной конфигурации агента, перезапускает агента и ничего не видит. Через неделю он открывает старый репозиторий. Его локальные настройки запускают npx со старым пакетом, скрипт загружает REPORTING_TOKEN из профиля оболочки, а удаленный API по-прежнему принимает токен. Каждая отдельная проверка выглядела чистой, потому что проверяла только личную конфигурацию. До удаления инвентаризация должна была связать конфигурацию репозитория, средство запуска, источник окружения и грант API.

Сохраняйте доказательства, не создавая новое хранилище секретов

Перестаньте передавать токены агентам
Sallyport сам подставляет API-учетные данные и возвращает результаты, не передавая секреты процессу агента.

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

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

История выполнения может выявить зависимости, которые пропустила инвентаризация. Проверьте историю сессий агентов, журналы клиентов, историю установки менеджера пакетов, изменения в системе контроля версий, добавившие конфигурацию, и активность целевого сервиса. Осторожно трактуйте временные метки. Журнал может показать запуск процесса, но не доказать завершение привилегированного действия.

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

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

Пусть срок владения истекает раньше, чем инструменты превратятся в археологию

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

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

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

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

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

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

Может ли неиспользуемый MCP-сервер быть угрозой безопасности?

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

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

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

Где на macOS хранятся конфигурации MCP-серверов?

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

Можно ли удалить конфигурацию MCP, не сломав проекты?

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

Нужно ли удалять старые API-токены из переменных окружения?

Считайте старую переменную окружения путем доступа, пока не доказано обратное. После отзыва соответствующего токена удалите ее из профилей оболочки, файлов окружения проектов, конфигураций запуска и настроек CI.

Как отозвать SSH-доступ для удаленного инструмента?

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

Как убедиться, что MCP-сервер действительно удален?

Запустите клиент с чистым профилем или после полного перезапуска проверьте его список серверов. Затем просмотрите журналы и записи активности на наличие удаленной команды и убедитесь, что ни один процесс оболочки, launch agent или расширение редактора ее не запускает.

Как часто командам нужно проверять MCP-серверы?

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

Что сделать перед удалением пакета MCP-сервера?

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

Может ли шлюз действий помочь управлять доступом агентов?

Sallyport хранит API- и SSH-учетные данные вне процесса агента и записывает сессии агентов и отдельные вызовы. Он не заменяет инвентаризацию: конфигурации агентов все равно нужно удалить, а доступ без владельца отозвать.

Sallyport

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

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