Открытый гайд · ИИ-офис

Свой MCP-сервер:пишем с нуля

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

@kir.player
~13 минут
июнь 2026

Готовые MCP-серверы закрывают типовое: документация, браузер, поиск. Но рано или поздно упираешься в задачу, которой нет в каталоге: «дай Claude читать нашу внутреннюю базу», «пусть дёргает наш приватный API», «научи его понимать наш формат данных». Тут и пишут свой MCP-сервер — это проще, чем кажется. По сути ты пишешь несколько обычных функций и оборачиваешь их в стандартный протокол, чтобы Claude мог их вызывать.

Что узнаешь из гайда

  • Чем свой MCP-сервер отличается от готовых связок и когда он нужен
  • Из чего состоит сервер: инструменты, описания, схема параметров
  • Как выглядит скелет сервера — на разобранном примере
  • Как подключить через claude mcp add и .mcp.json
  • Транспорты stdio и HTTP и где какой брать

Часть 1 · Понятие

Что такое свой MCP-сервер

Главное

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

Расшифруем аббревиатуру. MCP (Model Context Protocol) — это стандарт, по которому модель получает доступ к внешним инструментам и данным. Сервер — программа, которая по этому стандарту предоставляет инструменты. Claude Code выступает клиентом: он подключается к серверу, видит список его инструментов и вызывает их, когда задача подходит.

Что такое MCP и как ставить готовые серверы — отдельный гайд про MCP-серверы и готовые связки. Здесь же мы идём дальше: не подключаем чужой сервер, а пишем свой, когда готового под задачу не существует.

Когда писать свой

Внутренний CRM без публичного API, своя база с особой логикой доступа, корпоративный сервис за VPN, нестандартный формат отчётов — всё это кандидаты на свой MCP-сервер. Если готовый сервер закрывает задачу — бери его, не изобретай. Свой пишут только тогда, когда готового нет.


Часть 2 · Анатомия

Из чего состоит сервер

Главное

Сервер объявляет инструменты (tools). У каждого — имя, описание, схема входных параметров и функция-обработчик. Claude читает описания и вызывает нужный инструмент с аргументами.

Инструмент — это центральное понятие. Думай о нём как об одной функции, которую ты разрешаешь вызывать Claude. У инструмента четыре части:

ЧастьЧто это
ИмяКороткий идентификатор, например get_orders
ОписаниеПо нему Claude решает, когда инструмент применить
Схема входаКакие параметры принимает (тип, обязательность)
ОбработчикФункция, которая делает работу и возвращает результат

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

Описание инструмента работает так же, как описание скила: чем точнее формулировка «когда меня использовать», тем чаще Claude зовёт инструмент там, где надо. Это та же логика, что в гайде про скилы Claude Code— модель матчит задачу с описанием.


Часть 3 · Код

Скелет сервера на TypeScript

Главное

Минимальный сервер — это несколько десятков строк: заводишь сервер, регистрируешь один инструмент с обработчиком, запускаешь на транспорте stdio. Дальше добавляешь инструменты по одному.

Серверы пишут на любом языке, для которого есть SDK; чаще всего на TypeScript или Python. Возьмём TypeScript и официальный пакет @modelcontextprotocol/sdk. Сначала ставим зависимости:

терминал · установка SDK
# Заводим проект и ставим официальный MCP SDK
npm init -y
npm install @modelcontextprotocol/sdk

Теперь скелет. Логика простая: создаём сервер, объявляем один инструмент с понятным описанием и схемой входа, пишем обработчик, запускаем на stdio. Код ниже — иллюстрация устройства (точные сигнатуры сверяй с актуальной докой SDK):

server.ts · минимальный MCP-сервер
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// 1. Заводим сервер с именем и версией
const server = new McpServer({ name: "my-orders", version: "1.0.0" });

// 2. Регистрируем инструмент: имя, описание, схема входа, обработчик
server.tool(
  "get_order",                       // имя — короткое и понятное
  "Достать заказ по номеру из нашей внутренней базы", // описание = триггер
  { orderId: z.string() },           // схема входа: один строковый параметр
  async ({ orderId }) => {
    // 3. Обработчик: тут твоя реальная логика (запрос в БД, вызов API)
    const order = await fetchOrderFromDb(orderId);
    return { content: [{ type: "text", text: JSON.stringify(order) }] };
  },
);

// 4. Запускаем на транспорте stdio — Claude общается через ввод-вывод
await server.connect(new StdioServerTransport());

Разберём по шагам. Сервер заводится один раз с именем и версией. Инструмент — это четыре части из прошлого раздела, собранные в один вызов: имя, описание, схема входа (тут через библиотеку zod), обработчик. Транспорт stdio в конце — способ, которым Claude будет общаться с сервером. Всё, что реально делает работу, живёт в обработчике: запрос в базу, вызов API, чтение файла.

Описание решает всё

Текст в описании инструмента — это то, по чему Claude решает, звать его или нет. Пиши конкретно: не «работа с заказами», а «достать заказ по номеру из внутренней базы». Размытое описание = инструмент либо не вызывается, либо вызывается невпопад. Это та же дисциплина, что и с описаниями скилов.


Часть 4 · Подключение

Подключаем сервер к Claude Code

Главное

Два пути: команда claude mcp add в терминале или запись в файл .mcp.json в корне проекта. Оба указывают Claude, как запустить твой сервер.

Способ 1. Команда claude mcp add

Для локального сервера на stdio: указываешь имя и через -- — команду запуска процесса. Всё, что после --, это как запустить твой сервер:

терминал · добавляем локальный сервер
# Синтаксис: claude mcp add <имя> -- <команда запуска>
claude mcp add my-orders -- node /path/to/server.js

# С переменной окружения (например, ключ к базе)
claude mcp add my-orders --env DB_URL=postgres://... -- node /path/to/server.js

Способ 2. Файл .mcp.json

Если сервер нужен всей команде — пропиши его в .mcp.json в корне проекта. Файл едет в гит, и при git pull сервер появляется у всех:

.mcp.json · в корне проекта
{
  "mcpServers": {
    "my-orders": {
      "type": "stdio",
      "command": "node",
      "args": ["./mcp/server.js"]
    }
  }
}

После подключения Claude Code видит инструменты сервера и зовёт их по описанию — как любые встроенные. Проверить, что сервер подключился, можно командой /mcp в чате.

Коротко

  • Личный/разовый сервер — claude mcp add <имя> -- <запуск>.
  • Командный — запись в .mcp.json в корне проекта, едет в гит.
  • Проверка подключения — команда /mcp в чате Claude Code.

Часть 5 · Транспорт

Транспорт и область видимости

Главное

Транспорт — как сервер общается: stdio (локальный процесс) или HTTP (удалённый по URL). Scope — кто видит сервер: только ты, проект или все твои проекты.

stdio против HTTP

Транспорт stdio — это локальный сервер: Claude запускает его как процесс на твоей машине и говорит с ним через стандартный ввод-вывод. Идеален для инструментов, работающих локально: доступ к файлам, локальной базе, скриптам. Транспорт HTTP — это удалённый сервер по URL, к которому подключаются по сети. Берут, когда сервис крутится на хосте и доступен команде.

ТранспортКогда брать
stdioЛокальный инструмент: файлы, локальная база, скрипты
HTTPУдалённый сервис по URL, общий для команды

Scope: кто видит сервер

При добавлении через claude mcp add у сервера есть область видимости (scope), как и у скилов с командами:

  1. local — приватный для текущего проекта, только у тебя. Дефолт.
  2. project — в .mcp.json проекта, едет в гит, виден всей команде.
  3. user — твой личный сервер во всех проектах на этой машине.

Когда свой сервер не нужен

Если задачу закрывает готовый MCP-сервер из каталога — не пиши свой, это лишний код, который тебе же поддерживать. Если нужен разовый скрипт, а не постоянный инструмент — проще дать Claude запустить его через bash. Свой сервер оправдан, когда доступ к источнику нужен регулярно и готового решения нет.

Коротко

  • Сервер = набор инструментов: имя, описание, схема входа, обработчик.
  • Скелет на @modelcontextprotocol/sdk — пара десятков строк, транспорт stdio для локального.
  • Подключение — claude mcp add или .mcp.json; HTTP — для удалённого, scope — кому виден.

Вопросы

Частые вопросы

Что такое свой MCP-сервер и зачем его писать?

MCP-сервер — это программа, которая даёт Claude Code новые инструменты: доступ к твоей базе, внутреннему API, файлам в особом формате. Готовые серверы (Context7, Playwright) закрывают типовые задачи, а свой пишут, когда нужен доступ к чему-то твоему — внутренней системе, приватной базе, нестандартному источнику данных, которого нет в готовых связках.

Из чего состоит MCP-сервер?

Сервер объявляет набор инструментов (tools): у каждого есть имя, описание, схема входных параметров и функция-обработчик. Claude читает описания, выбирает нужный инструмент под задачу, вызывает его с аргументами и получает результат. По сути ты пишешь обычные функции и оборачиваешь их в стандартный протокол, чтобы Claude мог их вызывать.

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

Локальный сервер подключается командой claude mcp add <имя> -- <команда запуска> с транспортом stdio, либо записью в .mcp.json в корне проекта. В .mcp.json указываешь command и args для запуска процесса. После добавления Claude Code видит инструменты сервера и вызывает их по описанию.

Чем транспорт stdio отличается от HTTP в MCP?

Stdio — это локальный сервер: Claude запускает его как процесс на твоей машине и общается через стандартный ввод-вывод. HTTP — это удалённый сервер по URL, к которому подключаются по сети. Для своего инструмента, работающего локально (доступ к файлам, локальной базе), берут stdio. Для сервиса, который крутится на хосте и доступен команде, — HTTP.

Читать дальше

Соседние гайды

Telegram про вайбкодинг и ИИ

Прикладной материал, разборы и рабочие приёмы — то, чем пользуюсь сам, без воды. Залетай, там самое полезное.

Зайти в Telegram