Вайбцех

MCP сервер что это и как запустить: 8 правил безопасной команды

Опубликовано 16 мин чтенияБазовый
Автор показывает схему MCP-сервера, рядом удивлённый кот и карточка с одной безопасной командой.
Что узнаете
  • понятную схему связи AI-клиента, MCP-клиента и MCP-сервера
  • критерии запуска без внешнего Node.js или Python runtime
  • структуру одной ограниченной tool-команды и JSON-конфигурации
  • пошаговую проверку подключения через stdio
  • список причин, из-за которых сервер не запускается или ломает JSON-RPC
Применить за 30 мин
Базовый
16просмотров
Что в инструкции
  1. Что такое MCP-сервер и зачем он нужен?
  2. Можно ли запустить MCP локально без лишних зависимостей?
  3. Что должна делать одна безопасная команда?
  4. Как выглядит простой MCP-сервер для локального запуска?
  5. Настройка MCP: где лежит JSON-конфигурация и что в ней проверить?
  6. Сколько ресурсов может потреблять локальный MCP-бинарник?
  7. Как запустить сервер и подключить его к AI-клиенту?
  8. Почему локальный MCP-сервер всё равно опасен?
  9. Что ломается, если писать что-то в stdout?
  10. Что делать, если клиент не видит сервер?
  11. Вопросы и ответы

[!tip] Хочешь собрать свои локальные инструменты без лишнего runtime? В практикуме по вайб-кодингу для предпринимателей есть отдельный маршрут от идеи до рабочего инструмента.

Что такое MCP-сервер и зачем он нужен?

Представь связку из трёх частей:

  • Host - AI-приложение, в котором ты работаешь.
  • MCP-клиент - часть host, которая подключается к конкретному серверу.
  • MCP-сервер - отдельная программа с инструментами и данными.

Модель не запускает программу напрямую: она видит описание инструмента и предлагает его вызвать, после чего Host показывает запрос, MCP-клиент передаёт вызов серверу, а сервер возвращает результат.

Официальная документация описывает MCP так:

MCP - это открытый стандарт для подключения AI-приложений к внешним системам, перевод автора.

- Model Context Protocol, What is the Model Context Protocol?

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

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

Именно здесь MCP полезнее обычной инструкции в чате. Команда становится доступной модели в понятной форме. При этом границу задаёт сама программа.

[!tip] Если хочешь пройти этот сценарий с поддержкой, практикум по вайб-кодингу для предпринимателей поможет собрать рабочий локальный инструмент и проверить его по шагам.

Начинай с одной функции

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

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

Можно ли запустить MCP локально без лишних зависимостей?

Если ищешь примеры по запросу «разработка mcp», то чаще всего увидишь Python или TypeScript. Это нормальный путь, но он не равен zero-dependency:

  • Python-сервер использует Python и пакет mcp.
  • TypeScript-сервер использует Node.js, SDK и дополнительные пакеты.
  • готовый статический бинарник запускается напрямую, без установки этих runtime.

В README mcp-stama формулировка звучит так:

“Blazingly fast, zero-dependency, single static Rust binary built for Cursor, Claude Desktop, and Windsurf.”

Перевод автора: «Молниеносный MCP-сервер без внешних runtime-зависимостей, собранный в один статический бинарник Rust для Cursor, Claude Desktop и Windsurf».

- StamManif, mcp-stama

Но внутри проекта всё равно есть Rust-зависимости, включая ignore, gix, bollard и sysinfo. Они попадают в сборку. Точнее сказать так: бинарнику не нужен внешний runtime, потому что библиотеки уже входят в сборку.

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

Проверенного официального примера ручной реализации MCP на чистом стандартном runtime без SDK в фактуре нет. Поэтому я не буду выдавать короткий самодельный JSON-RPC-файл за готовое универсальное решение. Для первой проверки подойдёт SDK-пример на Python. Для автономного запуска нужен уже собранный бинарник.

Что должна делать одна безопасная команда?

Кот удивлённо смотрит на карточки с правилами одной безопасной команды.

Минимальная конструкция выглядит так:

  1. Один локальный MCP-сервер.
  2. Одна tool-функция.
  3. Узкая схема входных данных.
  4. Заранее определённое действие.
  5. Ограниченный доступ к конкретной директории.
  6. Запрет строк вроде bash -c, sh -c и cmd /c.
  7. Логи в stderr.

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

Есть неприятная деталь: описание JSON Schema само по себе не гарантирует, что обработчик получит правильные данные. Модель может передать null, пустой массив или неподходящую форму. Поэтому проверяй аргументы внутри самой функции.

MCP-спецификация формулирует риск прямо:

“Tools represent arbitrary code execution and must be treated with appropriate caution.”

Перевод автора: «Инструменты представляют произвольное выполнение кода, поэтому с ними нужно обращаться осторожно».

- Model Context Protocol, Specification

Не передавай в tool команду целиком. Опасный вариант выглядит так:

run_shell("проверь статус и потом удали временные файлы")

Здесь модель фактически получает возможность сформировать действие. Безопаснее зарегистрировать конкретную функцию:

project_status(repo_path)

Внутри неё нет выбора программы. Нет shell. Нет удаления. Есть только проверка пути и заранее написанная логика чтения статуса.

Я бы не брал первым примером полноценный filesystem-сервер. В официальном filesystem-сервере есть чтение, запись, поиск, перемещение и другие операции. Он умеет ограничивать каталоги, но поверхность действий всё равно большая. Для первого подключения лучше взять одну read-only команду.

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

В официальном Python SDK пример выглядит так:

python
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Demo", json_response=True)

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b

Логика здесь прозрачная:

  • add - имя tool;
  • a и b - два входных аргумента;
  • тип int задаёт ожидаемый формат;
  • результатом становится сумма.

Такой пример быстро ловит базовые ошибки при разработке MCP. Клиент должен увидеть сервер, получить список tools, показать add и вернуть результат вызова. Если вместо этого происходит disconnect, проблема, скорее всего, в запуске, окружении или протоколе, а не в бизнес-логике.

Это хороший первый шаг для проверки MCP. Доступа к файлам пример не даёт: у функции нет пути, каталога и операции чтения. Она не доказывает, что сервер умеет безопасно работать с файловой системой.

Потом можно заменить тело на конкретное локальное действие. Но я бы не расширял интерфейс сразу. Сначала проверь 2 + 3 = 5. Затем добавь одну операцию чтения. После каждого изменения снова проверь список tools и один вызов.

Практикум «Старт»

Три дня живой практики: от идеи до работающего проекта по ссылке

2 000 ₽старт 5 августа, 18:00 МСК

Настройка MCP: где лежит JSON-конфигурация и что в ней проверить?

Когда я настраиваю MCP, сначала проверяю несколько конкретных полей. Если ты пришёл по запросу «mcp настройка», начни с той же проверки:

json
{
  "mcpServers": {
    "safe-command": {
      "command": "/absolute/path/to/safe-command",
      "args": []
    }
  }
}

safe-command - имя, под которым сервер появится в клиенте. Оно не обязано совпадать с именем бинарника.

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

args - аргументы запуска. Если серверу нужна фиксированная папка, её можно передать здесь, но сама программа всё равно должна проверить значение.

В Windows путь записывай одним из двух способов:

json
{
  "command": "C:/Users/me/mcp/safe-command.exe",
  "args": []
}

или:

json
{
  "command": "C:\\Users\\me\\mcp\\safe-command.exe",
  "args": []
}

Строка с одиночными обратными слешами может сломать JSON из-за escape-последовательностей.

Конфигурация приложения и конфигурация проекта не одно и то же. В quickstart user guide для Claude Desktop указаны такие расположения: quickstart user guide

macOS:
~/Library/Application Support/Claude/claude_desktop_config.json

Windows:
%APPDATA%\Claude\claude_desktop_config.json

Claude Code использует scopes, как описано в документации подключения Claude Code к MCP. Пользовательский scope доступен между проектами. Проектный сохраняется в .mcp.json конкретного проекта. Если сервер добавлен внутри одной папки, в другой он может не появиться.

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

Практический промпт для проверки конфигурации:

Проверка MCP-конфига
Проверь этот MCP-конфиг как строгий валидатор. Найди только синтаксические и запускаемые проблемы: отсутствие mcpServers, отсутствие command, относительный путь, неправильные слеши в Windows, лишние аргументы и несоответствие имени исполняемого файла. Не предлагай новые серверы и не меняй структуру без объяснения причины. В конце выдай исправленный JSON без комментариев.

Если клиент не видит сервер, не переписывай tool. Сначала проверь этот JSON и путь к программе.

Сколько ресурсов может потреблять локальный MCP-бинарник?

ПоказательЗаявление README, не независимый benchmark
RAM mcp-stamaменее 10 MB
RAM стандартных Node.js или Python-инструментов200 MB и более
Cold start mcp-stamaменее 2 ms
Пробуждение стандартных инструментов1-3 секунды
Пакеты в legacy-вариантах100 и более
Cold start legacy MCP-серверов в таблице1 500-3 000 ms

В README сравнение подано как преимущество одного статического Rust-бинарника. Это может быть полезной инженерной целью: не тянуть внешний runtime ради одной небольшой команды.

Но цифры нельзя переносить на любой Rust-сервер. На расход влияют сборка, операционная система, набор библиотек и конкретное действие tool. В самой фактуре нет конфигурации машины, методики измерений или независимого повторения.

Поэтому вывод остаётся практическим. Если задача узкая, один бинарник убирает отдельный слой окружения. Это упрощает запуск и диагностику. Но слово «быстрее» не заменяет проверку handshake, списка tools и реального вызова.

Как запустить сервер и подключить его к AI-клиенту?

Сиба-ину одобряет схему подключения MCP-сервера из трёх шагов.
  1. Подготовь исполняемый файл.

    Собери сервер или возьми готовый бинарник, который запускается напрямую. Для Python- и TypeScript-примеров зафиксируй runtime и путь к файлу, потому что графический клиент может не видеть окружение терминала.

    Проверь запуск из терминала:

    bash
    /absolute/path/to/safe-command

    Сервер может ждать сообщения и ничего не печатать в обычный вывод. Это не доказывает поломку. Для stdio такой процесс ждёт JSON-RPC от клиента.

  2. Проверь абсолютный путь.

    Укажи полный путь к бинарнику или к программе с явным runtime. Не оставляй только safe-command, если клиент запускается из другого окружения.

    Для Windows используй прямые слеши или экранированные обратные:

    C:/Users/me/mcp/safe-command.exe
    C:\\Users\\me\\mcp\\safe-command.exe
  3. Добавь сервер через CLI.

    В Claude Code команда для локального stdio-сервера выглядит так:

    bash
    claude mcp add --transport stdio safe-command -- /absolute/path/to/safe-command

    -- отделяет параметры Claude Code от команды и её аргументов. Если серверу нужна фиксированная директория, передай её после разделителя:

    bash
    claude mcp add --transport stdio safe-command -- /absolute/path/to/safe-command /absolute/path/to/project
  4. Выбери подходящий scope.

    Для одного проекта используй проектный scope. Если сервер нужен в разных проектах, добавь пользовательский scope:

    bash
    claude mcp add --transport stdio --scope user safe-command -- /absolute/path/to/safe-command
    bash
    claude mcp add --transport stdio --scope project safe-command -- /absolute/path/to/safe-command

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

  5. Перезапусти приложение полностью.

    Для Claude Desktop обычно требуется полный перезапуск: закрой клиент, включая процесс в трее, если он там остался, затем открой его заново. Для другого host проверь его инструкцию по перечитыванию MCP-конфигурации.

  6. Проверь список tools.

    Выполни команду списка MCP-серверов или открой список подключённых tools в клиенте. На этом шаге проверяется запуск процесса и handshake. Если сервер не появился, не переходи к отладке результата команды.

  7. Сделай один вызов.

    Вызови одну зарегистрированную tool с простым допустимым аргументом. У калькулятора это 2 и 3. Read-only команда должна получить заранее разрешённую директорию. Сверь фактический результат, а не сообщение «подключено».

  8. Посмотри журналы при сбое.

    Проверь журналы клиента и сервера. Диагностика должна идти в stderr, поэтому не добавляй отладочный текст в stdout ради удобства.

    [!warning] Inspector не равен клиенту Считай проверку в Inspector диагностической эвристикой: он запускает процесс в условиях текущего терминала, а Claude Desktop или другой графический клиент может использовать другое окружение. Поэтому Inspector не доказывает работу сервера в конкретном host. Проверка в Inspector не доказывает, что тот же путь и runtime доступны host.

Теперь добавь одну read-only tool, проверь tools/list и сделай один tools/call. Если соединение падает, первым делом убери вывод из stdout.

Почему локальный MCP-сервер всё равно опасен?

Официальная рекомендация описывает модель угроз без смягчений:

“Local MCP servers are binaries that are downloaded and executed on the same machine as the MCP client.”

Перевод автора: «Локальные MCP-серверы являются бинарными файлами, которые скачиваются и выполняются на той же машине, что и MCP-клиент».

- Model Context Protocol, Security Best Practices

Проверь риск по порядку:

  1. Убедись, что сервер получает только нужные файлы.
  2. Проверь, какие действия доступны с правами текущего пользователя.
  3. Отдели текст из README, issue или сообщения от разрешенных инструкций.
  4. Убедись, что строка не передается в shell как дополнительная команда.
  5. Удали секреты из конфигурации и логов.

Для первой версии я бы зафиксировал такие ограничения:

  1. Команда только read-only.
  2. Путь только внутри заранее разрешённой директории.
  3. Нет bash -c, sh -c, cmd /c и конкатенации shell-строк.
  4. Нет токенов и паролей в конфигурации.
  5. Нет сетевого доступа без отдельной причины.
  6. Минимальные права процесса.
  7. Явное подтверждение запуска и вызова.

stdio подходит для локального процесса, потому что клиент и сервер общаются напрямую через стандартные потоки. Перед выдачей доступа полезно сверить права с чек-листом безопасной проверки MCP. HTTP добавляет сетевую поверхность и требует отдельной защиты, включая авторизацию или ограниченный IPC-механизм.

Размер tool сам по себе не делает её безопасной. Безопасность задают пределы действия. add почти нечего менять. Функция, которая принимает путь и вызывает shell, может сделать намного больше, даже если её код занимает несколько строк.

Практикум «Старт»

Три дня живой практики: от идеи до работающего проекта по ссылке

2 000 ₽старт 5 августа, 18:00 МСК

Что ломается, если писать что-то в stdout?

Мужчина закрывает лицо рядом со схемой потоков stdout, JSON-RPC и stderr.

Нельзя делать так:

python
print("server started")

И так:

javascript
console.log("server started");

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

python
import sys

print("server started", file=sys.stderr)
javascript
console.error("server started");

Официальная документация формулирует правило прямо:

“Never write to stdout. Writing to stdout will corrupt the JSON-RPC messages and break your server.”

Перевод автора: «Никогда не пиши в stdout. Запись в stdout испортит сообщения JSON-RPC и сломает сервер».

- Model Context Protocol, Build an MCP server

Проблема может быть не в твоём коде. Текст иногда печатает зависимость, драйвер или startup-обвязка. Поэтому сервер способен работать на одной машине и отключаться на другой, где отличается окружение или версия пакета.

Ожидаемый поток выглядит иначе:

stdin  -> сообщения от MCP-клиента серверу
stdout -> сообщения JSON-RPC от сервера клиенту
stderr -> логи и диагностика

Не используй stdout для баннера, версии, предупреждения или отладочного значения. Если нужно понять, где сервер остановился, поставь запись в stderr перед проверкой входа и после завершения действия.

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

Что делать, если клиент не видит сервер?

Иди по этому порядку:

  1. Проверь абсолютный путь к бинарнику или runtime.
  2. Убедись, что файл существует и имеет право на запуск.
  3. Проверь JSON: mcpServers, command, args, слеши в Windows.
  4. Определи, где лежит конфигурация именно этого host.
  5. Проверь scope в Claude Code.
  6. Запусти ту же команду вручную.
  7. Посмотри журналы клиента и сервера.
  8. Полностью перезапусти приложение.

Если npx работает в терминале, это ещё не значит, что его найдёт Claude Desktop. Графическое приложение не обязано наследовать настройки NVM, asdf или изменения .zshrc и .bashrc. Для такого случая используй абсолютный путь к node и файлу сервера либо готовый бинарник.

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

Если Inspector показывает tool, а Claude Desktop нет, сравни условия запуска и окружение:

  • текущую директорию;
  • PATH;
  • виртуальное окружение;
  • runtime;
  • путь к конфигу;
  • права на файл.

После изменения JSON перезапусти приложение целиком. Закрытие окна может оставить процесс активным, и старый конфиг продолжит использоваться.

Не начинай с переписывания сервера. Сначала докажи, что клиент запускает ту же команду, проходит initialize, получает tools/list и отправляет один tools/call. Если процесс не стартует, проблема не в описании tool. Если список tools приходит, но вызов ломается, переходи к аргументам, stdout и обработчику.

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

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

Как запустить MCP-сервер через CLI?

В Claude Code добавь локальный процесс командой claude mcp add --transport stdio safe-command -- /absolute/path/to/safe-command. Это локальное подключение к процессу через stdio, а не через SSH. Если ты сравниваешь варианты по запросу «mcp ssh», SSH здесь не нужен. После добавления проверь scope, полностью перезапусти клиент и посмотри список tools. Разделитель -- отделяет параметры Claude Code от команды и её аргументов.

Как защитить локальный MCP-сервер?

Оставь одну read-only tool, ограничь каталог и набор аргументов, не передавай строки в shell, не храни секреты в конфиге и запускай процесс с минимальными правами. Для локального подключения используй stdio, а перед подтверждением проверь точную команду, которую клиент собирается выполнить. Затем вызови одну безопасную tool и проверь фактический результат, а не только статус подключения.

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

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

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

В приведённых источниках подтверждён локальный запуск через stdio: клиент сам запускает процесс и поддерживает соединение. Это не то же самое, что постоянно работающая служба systemd или Windows Service. Подтверждённого сценария для фонового сервиса здесь нет, поэтому первый эксперимент я бы оставил обычным: сначала проверь запуск и полный цикл подключения из клиента, а уже потом оценивай службу.

Где посмотреть простой пример MCP-сервера?

Самый короткий учебный пример, который я использую, это tool add на Python SDK. Она получает два числа и возвращает сумму, поэтому результат легко проверить как 2 + 3 = 5. Внешний сервис не нужен, но нужны Python и пакет mcp. Пример удобен для проверки MCP, запуска процесса и первого вызова, но не показывает работу с файлами и ограничение доступа к каталогам.

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

У Claude Desktop путь зависит от системы: ~/Library/Application Support/Claude/claude_desktop_config.json на macOS и %APPDATA%\Claude\claude_desktop_config.json на Windows. Claude Code использует свои scopes, то есть области действия настройки, и проектный .mcp.json. Другие клиенты могут хранить настройки иначе, поэтому сначала выбери конкретный host, затем проверь его путь и scope до перезапуска.

Как подключить свой MCP-сервер?

Подготовь исполняемый файл, укажи абсолютный путь в command, добавь аргументы в args, подключи процесс через stdio, перезапусти клиент и проверь tools/list, затем один tools/call. Проверка в Inspector отдельно не доказывает работу в графическом клиенте.

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

Для готового статического бинарника установка MCP не требует отдельного Node.js или Python runtime. Если ты ищешь «установка mcp», сначала проверь совместимость файла с системой и права на запуск, затем укажи абсолютный путь в конфигурации и проверь handshake, то есть первый обмен сообщениями клиента и сервера. Если сервер написан на Python или TypeScript, понадобятся соответствующие runtime, SDK и пакеты.

Источники

Практикум «Старт»

Три дня живой практики: от идеи до работающего проекта по ссылке

2 000 ₽старт 5 августа, 18:00 МСК

Материал был полезен?
Сергей Мазур
Автор
Сергей Мазур
Основатель Вайбцеха

Собираю продукты с ИИ-агентами и рассказываю, как это делать без программиста.

Читайте также

Claude модели: как выбрать режим мышления агента в 2026 году

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

19 мин

Модели Claude в 2026: 6 шагов проверки ответа до коммита

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

12 мин

Claude модели против GLM 5.2: собрала страницу за 110,9 секунды в 2026

Claude - это семейство моделей, а не одна фиксированная система. Разбираю роли Fable, Opus, Sonnet и Haiku, сравнение с GLM 5.2 и проверки, которые ловят ложное «готово».

20 мин

Модель Claude против Kimi K3-256k: на какой задаче 1M токенов окупается в 2026

Разбираю модели Claude и Kimi K3-256k без рейтинга ради рейтинга. Показываю, где нужен контекст 1M, когда хватит 200K или 256K и как сменить модель в Claude Code.

15 мин

Термины из инструкции