Как писать MCP-серверы

MCP-серверы в 2026: как проектировать tools, resources и prompts, когда выбирать stdio или Streamable HTTP, как тестировать через Inspector и где чаще всего ломается server design.

MCP-сервер в 2026 уже не стоит воспринимать как "маленький bridge к одной функции". Хороший MCP server теперь чаще проектируют как capability surface для agent stack: с tools, resources, prompts, transport choice, security boundaries, test tooling и иногда remote deployment path.

Из-за этого статья про MCP-серверы уже не должна сводиться к одному примеру на TypeScript. Намного важнее понять, какой server surface вообще стоит публиковать, чем просто научиться вызвать server.tool().

MCP-сервер — это адаптер между AI-приложением и внешней системой. Он делает ваши данные и действия доступными через общий протокол, чтобы Claude, IDE, agent runtime или другое MCP-совместимое приложение могли работать с ними единообразно.
Самый частый anti-pattern — брать внутренний REST API и механически выставлять его 1:1 как набор MCP tools. Обычно это даёт шумный, небезопасный и неудобный server surface. MCP-сервер должен проектироваться под agent use case, а не быть слепой обёрткой вокруг всех endpoint'ов.

Короткая версия

Хороший MCP-сервер в 2026 обычно проектируется по пяти решениям:

  1. какие capabilities нужны: tools, resources, prompts;
  2. local или remote transport: stdio или Streamable HTTP;
  3. какие trust boundaries и permissions;
  4. как тестировать через Inspector;
  5. как сделать contracts короткими, различимыми и безопасными.

Практическая рамка:

  • tools для actions;
  • resources для readable context;
  • prompts для reusable task scaffolding;
  • stdio для local developer/server cases;
  • Streamable HTTP для remote and service-style deployments.
ПромптMCP server review
Когда плохая идея публиковать 40 внутренних endpoint'ов как 40 MCP tools?
Ответ модели

Когда агенту не нужен весь этот surface и descriptions начинают пересекаться. Обычно лучше сделать меньше, но более task-oriented tools с ясными contracts и ограниченными правами.

Плохой MCP server
Один endpoint сервиса = один tool. Названия абстрактные, output шумный, права широкие, transport выбран случайно.
Нормальный MCP server
Server surface спроектирован вокруг agent tasks: tools различимы, resources полезны как context layer, transport соответствует deployment mode, а test path проходит через Inspector.

1. Что такое хороший MCP server surface

Current MCP ecosystem уже достаточно зрелый, чтобы отличать "сервер существует" от "сервер хорошо спроектирован".

Хороший server surface обычно:

  • минимален;
  • ориентирован на реальные agent tasks;
  • не раскрывает лишние internal details;
  • имеет предсказуемые outputs;
  • ограничивает опасные действия.

То есть цель не "дать доступ ко всему", а "дать удобный и безопасный слой возможностей".

2. Когда публиковать tools, resources и prompts

Tools

tools нужны, когда агент должен что-то сделать:

  • создать issue;
  • найти запись;
  • изменить объект;
  • запустить bounded operation;
  • выполнить action в системе.

Resources

resources полезны, когда агенту нужно читать данные как context, а не инициировать action:

  • конфиги;
  • справочники;
  • документы;
  • read-only snapshots;
  • статусы и каталоги.

Prompts

prompts полезны, когда вы хотите дать reusable task template:

  • code review prompt;
  • incident triage template;
  • document analysis workflow;
  • customer support investigation scaffold.

Практический принцип простой:

  • если это чтение, сначала думайте про resources;
  • если это действие, сначала думайте про tools;
  • если это reusable task framing, думайте про prompts.

3. Transport choice: stdio vs Streamable HTTP

Старые explainers часто оставляли transport choice как второстепенную деталь. В 2026 это уже архитектурное решение.

stdio

Обычно лучше подходит для:

  • local development;
  • desktop tooling;
  • IDE integrations;
  • subprocess-style servers;
  • quick prototyping.

Плюсы:

  • минимальная операционная сложность;
  • простая локальная интеграция;
  • хороший старт для первого сервера.

Streamable HTTP

Обычно нужен для:

  • remote servers;
  • team-shared MCP services;
  • hosted infrastructure;
  • centralized enterprise integrations.

Плюсы:

  • нормальный service deployment path;
  • лучше подходит для remote access и observability;
  • естественнее для server-style operations.

Выбор транспорта должен идти не от вкуса, а от deployment model.

4. Design rules для tools

Больше всего проблем в MCP-серверах приносит не transport, а poorly designed tools.

Нормальный tool contract обычно:

  • имеет узкое имя;
  • описывает use case, а не только техническое действие;
  • не перегружен аргументами;
  • возвращает короткий структурированный результат;
  • чётко сообщает про failure.
Плохой tool
name: update_record description: обновляет запись
Нормальный tool
name: create_incident_ticket description: Create a new incident ticket in the internal tracker. Use for outages, service degradation, or operational incidents. Returns ticket id, title, severity, and current status.

5. Design rules для resources

Resources часто недооценивают, хотя они позволяют не превращать всё в tools.

Полезные patterns:

  • read-only status snapshots;
  • policy documents;
  • repo/service metadata;
  • dashboards as structured text or JSON;
  • catalog data for lookup.

Resources особенно полезны, когда вы хотите:

  • дать модели context без side effects;
  • уменьшить число tools;
  • сделать reading path более безопасным.

6. Security и trust boundary

MCP-сервер почти всегда выходит к реальным данным и действиям. Поэтому security design должен быть explicit.

Обычно нужно решить:

  • какие directories или systems доступны;
  • какие действия read-only, а какие write-capable;
  • где approval or human confirmation;
  • какие credentials живут внутри server;
  • как логировать вызовы и failures.

Если сервер подключён к prod-like systems, model convenience не должна быть приоритетом над boundaries.

7. Testing path: Inspector first

Current official tooling отдельно продвигает Inspector, и это очень правильная инженерная привычка.

Inspector нужен, чтобы:

  • видеть capabilities сервера;
  • руками вызывать tools;
  • читать resources;
  • ловить schema and output bugs;
  • проверять transport behavior.

Это сильно лучше, чем впервые тестировать сервер уже внутри Claude Desktop или coding IDE.

8. TypeScript и Python

На практике самые частые server implementations всё ещё:

  • TypeScript;
  • Python.

TypeScript хорош, когда:

  • стек уже Node-based;
  • нужен хороший DX для schema/contracts;
  • удобен ecosystem around desktop/IDE tooling.

Python хорош, когда:

  • tools тесно связаны с data/science/backend code;
  • удобно быстро оборачивать existing scripts;
  • server живёт рядом с internal automation.

Но статья про "как писать MCP-серверы" в 2026 должна учить не языку, а server design.

9. Где чаще всего ломаются MCP servers

Типовые failure modes:

  1. слишком много tools;
  2. overlapping descriptions;
  3. giant noisy outputs;
  4. плохой transport choice;
  5. отсутствие test path через Inspector;
  6. слабая permission model;
  7. путаница между resources и tools.
Если сомневаетесь, начните с меньшего server surface. Один хороший resource и два ясных tools обычно полезнее, чем каталог из двадцати vaguely defined возможностей.

Плюсы

  • Переиспользуемый capability layer для разных MCP hosts
  • Чистый способ публиковать tools и context для agent stack
  • Inspector делает testing и debugging намного проще
  • stdio и Streamable HTTP покрывают local и remote deployment paths
  • Resources позволяют давать context без лишних side effects

Минусы

  • Плохой design быстро превращает server в noisy adapter
  • Нужно отдельно проектировать boundaries и permissions
  • Transport choice и hosting уже становятся архитектурной задачей
  • Schema/contract quality критична для usability
  • Не все hosts одинаково реализуют весь MCP surface

Минимальный TypeScript skeleton

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: "status-server",
  version: "1.0.0",
});

server.tool(
  "get_service_status",
  "Return current status for a named service.",
  { service: z.string() },
  async ({ service }) => ({
    content: [
      {
        type: "text",
        text: JSON.stringify({ service, status: "healthy" }),
      },
    ],
  })
);

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

Этого достаточно для первого local server. Дальше важнее не расширять код бездумно, а понять, какие capabilities реально нужны агенту.

Когда добавлять Streamable HTTP

Обычно переход к remote transport имеет смысл, когда:

  • сервер нужен нескольким людям или командам;
  • вы хотите service-style hosting;
  • нужен централизованный доступ к internal systems;
  • нужен более нормальный ops path, чем subprocess-local mode.

Server review checklist

  1. У каждого tool ясное назначение и непересекающееся описание.
  2. Resources действительно read-oriented, а не disguised actions.
  3. Transport соответствует deployment reality.
  4. Dangerous capabilities не открыты по умолчанию.
  5. Server проходит через Inspector до интеграции в host.
ПромптMCP design reviewer
У нас internal billing API. Что публиковать первым: 15 endpoints или 3 task-oriented tools?
Ответ модели

Почти всегда лучше 3 task-oriented tools. MCP server должен быть спроектирован вокруг реальных agent jobs, а не зеркалировать весь backend surface.

Проверьте себя

Проверьте себя

1. Когда `resources` обычно лучше, чем `tools`?

2. Когда `Streamable HTTP` обычно уместнее `stdio`?

3. Какой самый частый anti-pattern при написании MCP server?