Заметки

Как создать свой MCP-сервер: пошаговый гайд для разработчика

M
Markabus
·18 июля 2026 г.
Тёмная графитовая сцена: центральный светящийся узел-коннектор, от которого расходятся тонкие каналы данных к полупрозрачным голо-панелям — базе данных, API, файлу и серверу; синий цвет использован только как акцентная подсветка каналов
Как создать свой MCP-сервер: пошаговый гайд для разработчика

Model Context Protocol (MCP) превратился в стандартный способ давать ИИ-моделям доступ к внешним данным и действиям: файлам, базам, API, вашей CRM. Готовых серверов уже сотни, но рано или поздно возникает задача, под которую подходящего сервера нет, — и его приходится писать самому. Хорошая новость: минимальный рабочий MCP-сервер занимает пару десятков строк кода. В этом гайде разберём, из чего состоит сервер, какие бывают транспорты, и напишем рабочий пример на Python и на TypeScript.

Если вы ещё не знакомы с самим протоколом, начните с заметки «Что такое MCP простыми словами» — там разобрано, зачем нужен этот «разъём для ИИ». А если интересует не написание сервера с нуля, а подключение готовых инструментов к сайту и CRM, посмотрите практический разбор «MCP: подключаем ИИ к сайту и CRM».

Что делает MCP-сервер

MCP-сервер — это программа, которая по стандартному протоколу сообщает ИИ-клиенту (Claude Desktop, Claude Code, IDE, вашему агенту): «вот что я умею», а затем выполняет запросы. Клиент и сервер обмениваются сообщениями в формате JSON-RPC 2.0. Модель сама решает, когда вызвать ваш инструмент, а сервер просто отдаёт результат. Благодаря единому протоколу один и тот же сервер работает с любым MCP-совместимым клиентом — писать отдельную интеграцию под каждое приложение больше не нужно.

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

Три строительных блока: инструменты, ресурсы, промпты

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

Инструменты (tools) — действия, которые вызывает модель: «найти клиента по email», «создать задачу», «выполнить SQL-запрос». Это самый частый и самый мощный примитив. У инструмента есть имя, описание и схема входных параметров, по которой модель понимает, что и как передавать.

Ресурсы (resources) — данные только для чтения, которые клиент подгружает в контекст: содержимое файла, запись из базы, документ. В отличие от инструментов, ресурсы не выполняют действий и не имеют побочных эффектов — их выбирает и подставляет приложение или пользователь.

Промпты (prompts) — переиспользуемые шаблоны запросов, которые сервер отдаёт клиенту как готовые сценарии. Например, «сделай ревью этого кода по нашему чек-листу». Пользователь выбирает промпт в интерфейсе, а сервер подставляет нужные параметры.

Для большинства задач достаточно инструментов, поэтому дальше сосредоточимся на них.

Транспорты: stdio и Streamable HTTP

Транспорт — это канал, по которому клиент общается с сервером. Актуальная спецификация (версия 2025-11-25) определяет два стандартных транспорта.

stdio — клиент запускает ваш сервер как дочерний процесс и обменивается с ним сообщениями через стандартный ввод-вывод. Это простейший вариант, идеальный для локальных инструментов: интеграций с Claude Desktop, CLI-утилит, доступа к локальным файлам. Спецификация рекомендует поддерживать stdio всегда, когда это возможно.

Streamable HTTP — сервер работает как отдельный веб-сервис на одном HTTP-эндпоинте (например, https://example.com/mcp), принимающем POST и GET. При необходимости он может стримить ответы через Server-Sent Events. Этот транспорт нужен для удалённых серверов, к которым подключаются несколько клиентов по сети. Он пришёл на смену старому транспорту HTTP+SSE из версии протокола 2024-11-05 — если встречаете в старых гайдах отдельный SSE-эндпоинт, знайте, что он устарел.

Начинать почти всегда стоит с stdio: меньше кода, не нужно думать про аутентификацию и сеть, легко отлаживать. Перейти на HTTP можно потом, когда сервер понадобится вынести на удалённую машину.

Пишем MCP-сервер на Python

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

Установка

Понадобится Python 3.10+ и пакет mcp. Удобнее всего ставить через менеджер uv, но подойдёт и обычный pip:

pip install "mcp[cli]"

Первый инструмент

Создадим файл server.py. Инструмент — это функция с декоратором @mcp.tool(); SDK сам построит схему параметров из аннотаций типов, а строку документации использует как описание для модели.

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("my-server")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Сложить два числа."""
    return a + b

@mcp.tool()
def get_weather(city: str) -> str:
    """Вернуть погоду для указанного города."""
    # здесь мог бы быть реальный запрос к API
    return f"В городе {city} сейчас +18 °C, ясно"

if __name__ == "__main__":
    mcp.run(transport="stdio")

Это уже полноценный сервер с двумя инструментами. Аннотации типов (a: int, city: str) важны: по ним SDK формирует схему, а модель понимает, что передавать. Строка-докстринг — не формальность, а описание, которое читает ИИ, решая, вызывать ли инструмент.

Подключение к клиенту

Чтобы Claude Desktop увидел сервер, добавьте его в конфигурацию клиента, указав команду запуска процесса:

{
  "mcpServers": {
    "my-server": {
      "command": "python",
      "args": ["/полный/путь/к/server.py"]
    }
  }
}

После перезапуска клиента инструменты add и get_weather станут доступны модели. Точно так же сервер подключается к Claude Code и другим MCP-совместимым клиентам.

Пишем MCP-сервер на TypeScript

Если вам ближе экосистема Node.js, есть официальный TypeScript SDK — пакет @modelcontextprotocol/sdk. Установка:

npm install @modelcontextprotocol/sdk zod

Библиотека zod нужна для описания схем входных параметров. Минимальный сервер выглядит так:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "my-server", version: "1.0.0" });

server.registerTool(
  "add",
  {
    title: "Сложение",
    description: "Сложить два числа",
    inputSchema: { a: z.number(), b: z.number() },
  },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }],
  })
);

const transport = new StdioServerTransport();
await server.connect(transport);

Логика та же, что и в Python: создаём объект McpServer, регистрируем инструменты через registerTool() (для ресурсов и промптов есть registerResource() и registerPrompt()), затем подключаем транспорт и вызываем server.connect(). Результат инструмента возвращается в поле content — массиве блоков, чаще всего текстовых.

Безопасность: не пропускайте этот раздел

Пока сервер работает по stdio на вашей машине, поверхность атаки минимальна. Но как только вы переводите его на Streamable HTTP и открываете наружу, появляются реальные риски, и спецификация прямо предписывает защиту.

Во-первых, сервер обязан проверять заголовок Origin у всех входящих соединений — это защита от атак DNS rebinding, когда вредоносный сайт в браузере пытается достучаться до вашего локального сервера. Если Origin некорректен, нужно отвечать 403 Forbidden. Во-вторых, при локальном запуске сервер стоит привязывать только к 127.0.0.1, а не к 0.0.0.0, чтобы он не был виден всей сети. В-третьих, для любых сетевых подключений следует внедрять аутентификацию.

Отдельно помните про доверие к вводу: инструмент, выполняющий SQL или shell-команды по параметрам от модели, — потенциальная дыра. Валидируйте входные данные и ограничивайте права так же строго, как для любого публичного API.

Как отладить и что дальше

Для локальной отладки удобен инспектор — официальная утилита, которая подключается к вашему серверу и показывает список инструментов, их схемы и результаты вызовов без необходимости поднимать полноценный клиент. Запускается она через npx и открывает веб-интерфейс, где можно вручную дёргать инструменты и смотреть JSON-RPC-обмен.

Когда сервер готов, дальнейший путь зависит от задачи: для личных инструментов достаточно stdio и локального запуска, а для командного использования сервер оборачивают в Streamable HTTP, разворачивают на сервере и закрывают аутентификацией. Начните с малого — один-два инструмента на stdio, — убедитесь, что модель корректно их вызывает, и наращивайте функциональность оттуда.

Вывод

Собственный MCP-сервер — это не сложная инфраструктура, а несколько функций, обёрнутых в стандартный протокол. Выберите SDK по вкусу (Python с FastMCP или TypeScript), опишите инструменты обычными функциями с понятными аннотациями и описаниями, запустите на stdio и подключите к клиенту. Когда понадобится удалённый доступ — переходите на Streamable HTTP, не забывая про проверку Origin, привязку к localhost и аутентификацию. Этого достаточно, чтобы дать вашему ИИ-ассистенту доступ к чему угодно — от базы данных до внутреннего API.

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

Q.На каком языке лучше писать MCP-сервер?

Официальные SDK есть для Python (класс FastMCP) и для TypeScript (пакет @modelcontextprotocol/sdk). Логика идентична, поэтому выбирайте тот язык, что ближе вашему проекту.

Q.Нужен ли серверу HTTP или хватит stdio?

Для локальных инструментов достаточно транспорта stdio — клиент сам запускает сервер как процесс. Streamable HTTP нужен, когда сервер должен работать удалённо и обслуживать несколько клиентов по сети.

Q.Правда ли, что SSE-транспорт устарел?

Да. Старый транспорт HTTP+SSE из версии протокола 2024-11-05 заменён на Streamable HTTP в актуальной спецификации (2025-11-25). Отдельный SSE-эндпоинт в новых серверах не нужен.

Q.Что такое инструменты, ресурсы и промпты?

Это три вида возможностей MCP-сервера: инструменты — действия, которые вызывает модель; ресурсы — данные только для чтения; промпты — готовые переиспользуемые шаблоны запросов.

Источники

Предыдущая
MCP: подключаем ИИ к сайту и CRM

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