Перейти к содержимому
PD
MCP-серверы

MCP-сервер на Python: свой сервер с нуля

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

Все статьи гида MCP-серверы · 11

Минимальный MCP-сервер пишется за вечер. Разберём, из чего он состоит и на чём спотыкаются при первом запуске.

Что нужно до кода

Три решения, которые определят качество результата сильнее, чем язык и библиотека.

Какие инструменты объявить. Не отражение вашего API, а операции в терминах задач агента. Подробно - в статье про обёртку API.

Как их описать. Агент выбирает по описанию. Это основная работа.

Какие права нужны. Начинайте с чтения. Права на запись добавляются отдельно и осознанно.

Минимальный сервер

Официальный SDK для Python берёт на себя протокол, и от вас требуется объявить инструменты. Структура получается такой:

  • Создаётся объект сервера с именем.
  • Каждый инструмент объявляется функцией: имя, описание, типы аргументов, тело.
  • Сервер запускается и слушает стандартный ввод.

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

Что важно сделать сразу:

  • Типы аргументов проставить явно. Без них схема получится расплывчатой, и агент будет передавать не то.
  • Перечислить допустимые значения там, где их конечное число. Параметр status без перечисления вариантов гарантирует ошибки.
  • Возвращать структуру, а не отформатированный текст. Текст агент разберёт, но структура надёжнее и короче.
  • Ошибки возвращать текстом с объяснением, а не пустым результатом.

Запуск и подключение

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

  1. Ничего не печатать в stdout. Это самая частая ошибка: одна отладочная строка ломает протокол, и клиент видит сервер упавшим. Логи идут в stderr или в файл.
  2. Проверить запуск руками до подключения. Сервер должен стартовать и ждать ввода, а не завершаться.
  3. Указать полный путь к интерпретатору в конфиге, если есть сомнения: клиент запускает процесс в своём окружении, где PATH может отличаться.

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

Тестирование

До того, как отдавать серверу реальные права, стоит проверить три вещи.

Инструменты вызываются напрямую. Вызовите функции как обычные функции Python и убедитесь, что они работают. Это отделяет ошибки логики от ошибок протокола.

Сервер отдаёт список инструментов. После подключения спросите у агента, что ему доступно. Пустой список при живом сервере - почти всегда провал авторизации.

Агент выбирает верно. Дайте несколько типовых запросов и посмотрите, какой инструмент вызывается. Если не тот - правьте описание, а не промпт. Это самый информативный тест, и он же чаще всего пропускается.

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

Что добавить, когда базовое работает

  • Лимиты на объём ответа. Обязательны: ответ попадает в контекст целиком.
  • Подтверждение для опасных операций. Не «инструмент с предупреждением в описании», а отдельный шаг.
  • Аутентификацию через переменные окружения, если сервер ходит во внешнюю систему.
  • Обработку таймаутов. Внешний вызов, который висит, подвешивает и агента.

Разбор на конкретной системе - MCP-сервер для 1С. Безопасность и права - отдельная статья. Общая картина - гид по MCP.

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

Сложно ли написать свой MCP-сервер?

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

На чём писать MCP-сервер?

На том же, на чём написано то, к чему он даёт доступ. Официальные SDK есть для Python и TypeScript; Python удобнее, когда сервер ходит в базу или в системы, где уже есть готовые библиотеки.

Почему сервер запускается, но клиент его не видит?

Чаще всего в стандартный вывод попал посторонний текст. Stdout занят протоколом, и любая отладочная печать ломает обмен. Всё диагностическое должно идти в stderr или в файл.

Ещё по теме