Model Context Protocol (MCP) быстро стал стандартом для подключения инструментов к Claude Desktop, Cursor и другим клиентам. Но если вы пишете MCP-серверы, то наверняка сталкивались с тем, что ошибки в них проявляются не сразу и не очевидно. Случайный вывод в stdout, отсутствие аннотаций безопасности или скрытые инструкции в описаниях инструментов могут привести к поломке клиента или уязвимостям. В этой статье я расскажу, как создал линтер для MCP, какие проблемы он помогает найти и какие баги обнаружились даже в официальных серверах.

Почему MCP-серверы нуждаются в линтинге

MCP использует JSON-RPC поверх stdio или HTTP. Любое нарушение протокола — например, лишний вывод в stdout — ломает поток сообщений, и клиент перестаёт отвечать. Кроме того, инструменты MCP могут выполнять опасные действия: удаление файлов, запись в базы данных, отправку запросов. Если для такого инструмента не указана аннотация destructiveHint, агент может выполнить его без подтверждения пользователя. Ещё одна проблема — prompt injection: в описании инструмента можно спрятать инструкцию, которая заставит модель раскрыть контекст или выполнить нежелательное действие. Всё это трудно отловить вручную, особенно когда серверов много.

Какие проверки реализованы в линтере

Я написал mcp-linter на чистом Node.js/TypeScript без сторонних зависимостей. Он анализирует код сервера и конфигурацию, применяя 34 правила, разделённые на категории:

  • Протокол: проверка на наличие вывода в stdout, корректность JSON-RPC, соответствие версии MCP, обработка ошибок.
  • Безопасность: наличие аннотаций destructiveHint для опасных инструментов, проверка описаний на подозрительные паттерны (prompt injection), ограничение прав доступа.
  • Качество кода: использование устаревших методов, отсутствие валидации входных параметров, неинформативные сообщения об ошибках.
  • Производительность: избыточные вызовы, блокирующие операции.

Каждое правило имеет вес, по сумме баллов сервер получает оценку здоровья от A+ до F (0–100). Это помогает быстро понять общее состояние проекта.

Как линтер помогает исправлять ошибки

Помимо диагностики, mcp-linter умеет автоматически исправлять некоторые проблемы. Флаг --fix применяет безопасные правки: удаляет лишние console.log, добавляет недостающие аннотации, форматирует описания. Автоисправления не затрагивают логику работы сервера, поэтому их можно запускать в CI. Для интеграции с GitHub Security линтер экспортирует отчёт в формате SARIF v2.1.0. Это позволяет видеть предупреждения прямо в интерфейсе GitHub и блокировать merge при критических ошибках. Готовый GitHub Action можно добавить в workflow за пару строк.

Что показала проверка официальных серверов

Самый интересный результат — запуск линтера на официальных MCP-серверах от Anthropic. Оказалось, что даже в них встречаются недочёты. Например, в некоторых серверах отсутствовали аннотации destructiveHint для инструментов, которые изменяют состояние (запись в память, удаление сущностей). Это значит, что агент мог выполнить их без дополнительного подтверждения. Также нашлись описания инструментов с конструкциями, похожими на prompt injection, хотя и не обязательно вредоносными. Были и мелкие нарушения протокола: вывод отладочной информации в stdout в определённых условиях. Эти находки подтверждают, что автоматическая проверка полезна даже для зрелых проектов.

Как начать использовать линтер

Самый простой способ — запустить через npx без установки:

  • npx mcp-linter -- npx -y @modelcontextprotocol/server-memory — проверит сервер памяти из официального репозитория.
  • Для своего сервера укажите команду запуска или путь к файлу конфигурации.
  • Добавьте флаг --fix для автоисправления.
  • Для экспорта в SARIF используйте --format sarif --output report.sarif.

Линтер не заменяет ручной аудит, но помогает поймать типовые ошибки на раннем этапе. Если вы разрабатываете MCP-сервер, добавьте его в свой CI-пайплайн — это займёт немного времени, но снизит риск неприятных сюрпризов в продакшене.

Типичные ошибки и как их избежать

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

  • Никогда не пишите в stdout — используйте stderr для логов или специальные механизмы MCP.
  • Всегда указывайте аннотации для инструментов, которые могут изменить данные или выполнить опасные действия. Это не только безопасность, но и предсказуемость для пользователя.
  • Проверяйте описания инструментов на наличие скрытых инструкций. Лучше избегать конструкций, которые могут быть интерпретированы моделью как команды.
  • Валидируйте входные параметры — это предотвращает неожиданное поведение и атаки.
  • Используйте линтер в CI — автоматическая проверка экономит время и нервы.

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