Построй свой MCP-сервер: дай Claude доступ к любому API
MCP (Model Context Protocol) — это USB-интерфейс для AI: стандартный разъём, через который Claude подключается к любому инструменту. Разбираем, как спроектировать и запустить собственный MCP-сервер — от выбора инструментов до первого вызова из Claude Desktop.
СреднийMCP30 минTypeScript, MCP SDK, Claude Desktop
1
Когда MCP, а когда обычный код?
Вы хотите дать Claude доступ к CRM. Без MCP есть три пути: данные в промпт (ограничен контекстом), промежуточный сервис (поддерживать навсегда), или API-вызовы прямо в приложении (жёсткая привязка). MCP решает иначе — универсальный протокол, как USB-C: один разъём для всех устройств.
Простое правило: Claude сам решает, какой инструмент вызвать — MCP. Фиксированная цепочка вызовов — обычный код или n8n. Главная ценность — переиспользование: написал сервер для Jira, и к нему подключается Claude Desktop, Cursor, любой MCP-клиент.
Когда MCP, а когда нет?
Claude сам выбирает инструмент и порядок вызовов
Нужно переиспользовать доступ к API в разных клиентах
Линейный пайплайн с фиксированной последовательностью
Одноразовый скрипт для конкретной задачи
MCP — не замена Function Calling. Function Calling — вы контролируете логику в коде. MCP — Claude сам решает, что вызвать. Разные уровни автономии.
2
Узкие инструменты побеждают широкие — всегда
Инструмент `manage_database(action, params)` — это кнопка «сделать хорошо». Claude не понимает, что произойдёт, и вызывает её непредсказуемо. А `query_users`, `update_order`, `get_product` — три понятных кнопки, которые Claude комбинирует сам.
Ответьте на три вопроса до кода: что Claude должен уметь, что ему не нужно, и где граница безопасного. Начинайте только с read-инструментов — Claude будет экспериментировать, и пусть эксперименты не стоят вам строк в базе.
❌ Широкий инструмент
- manage_database(action, params)
- Claude не знает что именно произойдёт
- Ошибки сложно отлаживать
✅ Узкие инструменты
- query_users, update_order, get_product
- Claude комбинирует сам
- Каждый тестируется отдельно
Напишите описание инструмента до кода. Если не можете объяснить в двух предложениях, когда Claude должен его вызывать — граница инструмента ещё нечёткая.
3
Три слоя сервера — и только один ваш
MCP-сервер — не веб-сервер в привычном смысле. Это процесс-переводчик: с одной стороны Claude со своими запросами, с другой — ваш API или база данных. Переводчик принимает запрос, делает нужный вызов, возвращает результат в понятном Claude формате.
Транспорт (stdio или HTTP+SSE) — для начала всегда stdio: нет сетевых проблем, нет auth, проще отлаживать. Протокол (JSON-RPC 2.0) — SDK полностью скрывает эту деталь. Ваша бизнес-логика — единственный слой, где вы принимаете решения. Остальное — шаблон, который SDK генерирует за вас.
Ваша бизнес-логика
Что именно делает инструмент
Протокол (JSON-RPC 2.0)
SDK обрабатывает автоматически
Транспорт (stdio / HTTP+SSE)
Начинайте с stdio — проще
MCP-сервер = три слоя:
Бизнес-логика: ваш код (единственное, что вы пишете)
Протокол: JSON-RPC 2.0 (SDK обрабатывает)
Транспорт: stdio (локально) или HTTP+SSE (удалённо)
Инструмент = имя + схема входа + обработчик
get_order({ orderId }) → данные заказа из БД
Начинайте с stdio — проще отлаживать4
Описание инструмента — это промпт. Пишите его как промпт
Когда Claude выбирает инструмент, он читает три вещи: имя, описание, схему параметров. Это и есть промпт — только в формате JSON Schema. От качества этих трёх элементов зависит, будет ли Claude вызывать инструмент правильно, слишком часто, слишком редко или с неправильными параметрами.
Имя — глагол + объект: `get_customer_orders`, `search_knowledge_base`. Не `tool1`, не `handleRequest`. Claude использует имя как первую подсказку при выборе инструмента, и оно должно быть самоочевидным.
Описание — мини-инструкция для Claude. Включите: что делает инструмент, когда вызывать, что возвращает. Отдельно: когда НЕ вызывать. Кажется излишним, но именно негативные инструкции предотвращают ложные вызовы.
Схема параметров — добавляйте описания к каждому полю. `customerId` без описания — загадка. `customerId` с «UUID из CRM, не email и не имя» — конкретная инструкция. Claude будет передавать именно то, что вы ожидаете. Принцип: если стажёр поймёт инструмент, прочитав только схему — она хорошая.
Инструмент: search_orders
Описание: "Поиск заказов по статусу или клиенту.
Вызывать: когда спрашивают о заказах, доставке.
НЕ вызывать: для создания/изменения заказов."
Параметры:
customerId — "UUID из CRM, не email и не имя"
status — pending | shipped | delivered
limit — макс 20, по умолчанию 10Включите в описание инструмента когда его НЕ вызывать. Звучит странно, но отрицательные инструкции снижают количество ложных вызовов в разы.
5
Ошибки — это промпты для Claude, а не логи для вас
Представьте: Claude — курьер, которому вы дали адрес. GPS говорит «улица не найдена» — одна ситуация (уточнить). «Дорога закрыта» — другая (объехать). «GPS недоступен» — третья (подождать). Ваша задача — давать Claude именно такие сигналы, а не просто «что-то пошло не так».
В обычном API ошибка летит разработчику как HTTP 500. В MCP — ошибка летит Claude, и он должен с ней что-то сделать: повторить, объяснить пользователю, выбрать другой инструмент. Два типа: исключение процесса (сервер упал — Claude бессилен) и ошибка в контенте (`isError: true` с описанием — Claude читает и реагирует). Для бизнес-ошибок всегда второй вариант. Никогда не бросайте исключения из обработчика — это убивает весь MCP-сервер, а не один вызов.
Что писать в ошибке? Три элемента: что произошло, почему, что попробовать дальше. Не «Internal error», а «Order not found. The orderId may be from another system. Try search_orders by customer name.» Claude буквально прочитает это и скорректирует следующий шаг.
Тестируйте ошибки первыми. Вызовите инструмент с несуществующим ID, пустой строкой, невалидными параметрами — и проверьте, что Claude получает полезные подсказки, а не стектрейсы.
6
Подключил — теперь итерируй описания, а не код
Claude Desktop — идеальная среда для проверки MCP-сервера, потому что это рентген: видны не только результаты, но и как Claude рассуждал, какой инструмент выбрал, с какими параметрами. Добавить сервер — файл конфига с путём к скомпилированному JS, перезапуск приложения, инструменты появились.
Но важнее настройки — методика тестирования. Попросите Claude выполнить задачу с цепочкой вызовов: «Найди заказы клиента Иванов за последнюю неделю и скажи, какой из них на доставке». Это проверит и отдельные инструменты, и их комбинацию — именно для этого вы и строили MCP-сервер.
Итерация — самая ценная часть процесса. После первого теста вы обнаружите: Claude вызывает с неправильными параметрами (проблема описания), вызывает когда не нужно (описание слишком широкое), не вызывает когда нужно (название неочевидное). Каждый из этих сигналов — это правка в описании инструмента, а не в логике. Итерация описаний даёт больше, чем рефакторинг кода.
Используйте MCP Inspector (`npx @modelcontextprotocol/inspector`) до Claude Desktop — он показывает инструменты и позволяет вызывать вручную, как Postman для MCP. Экономит 80% времени на отладку.
Результат
Работающий MCP-сервер, подключённый к Claude Desktop. Claude вызывает ваши инструменты автономно — потому что описания написаны как промпты, а не как документация.