Команды и пакеты в этом уроке проверены по официальной документации на октябрь 2026. SDK и Claude Code обновляются часто: если команда не сработала, сверься с документацией MCP в Claude Code и modelcontextprotocol.io. Актуальные версии: Актуальное сейчас.
Суть урока
MCP — это как USB-порт для Claude. USB — стандартный разъём: подключи мышь, флешку, микрофон, принтер — компьютер их видит. MCP — стандартный протокол: подключи свой CRM, базу данных, корпоративный API, файловую систему — Claude их видит как инструменты. Сегодня ты напишешь собственный MCP сервер: 30-50 строк кода, и у Claude появляются новые возможности которых у него не было.
Ключевые концепции
- MCP (Model Context Protocol) — открытый стандарт Anthropic для подключения AI к внешним инструментам (modelcontextprotocol.io)
- MCP сервер — программа которая предоставляет tools, resources, prompts для Claude
- Транспорты: stdio (локально), HTTP (remote, рекомендуемый), SSE (remote, deprecated), WebSocket (только через JSON-конфиг)
- Три типа объектов: tools (действия), resources (данные), prompts (шаблоны)
- Три области видимости: local (дефолт, приватно), project (через
.mcp.json, для команды), user (все проекты) - Установка:
claude mcp add(CLI),.mcp.json(файл), или через плагин - Токен-экономика: предупреждение при >10,000 токенов, лимит по умолчанию 25,000 токенов на вызов
- TypeScript SDK —
@modelcontextprotocol/server/ Python SDK —pip install "mcp[cli]"(старый TypeScript-пакет@modelcontextprotocol/sdkещё встречается в примерах)
Теория
Архитектура MCP
Claude Code (Client)
│
│ Стандартный MCP протокол (JSON-RPC 2.0)
│ через stdio или HTTP (SSE устарел)
▼
MCP Server (твой код)
│
├── tools → функции которые Claude может вызвать
├── resources → данные которые Claude может прочитать
└── prompts → шаблоны для повторяющихся задач
│
▼
Внешняя система (CRM, БД, API, файлы...)Ключевое: MCP сервер — обычная программа. Она запускается когда Claude Code стартует в проекте и остаётся активной пока сессия открыта. Claude вызывает tools через JSON-RPC запросы, сервер отвечает результатами.
Что можно делать с подключёнными MCP серверами (из официальной документации):
- Реализовать фичу из issue tracker: "Сделай фичу из JIRA ENG-4521 и создай PR на GitHub"
- Анализировать мониторинг: "Проверь Sentry и покажи ошибки за 24 часа"
- Запрашивать базы данных: "Найди пользователей которые использовали фичу X"
- Интегрировать дизайны: "Обнови шаблон по новым Figma макетам"
- Автоматизировать: "Создай черновики писем для этих 10 пользователей"
Три способа установки MCP серверов
Способ 1: Remote HTTP сервер (рекомендуемый для облачных сервисов)
claude mcp add --transport http notion https://mcp.notion.com/mcpСпособ 2: Remote SSE сервер (deprecated, используй HTTP)
claude mcp add --transport sse asana https://mcp.asana.com/sseСпособ 3: Локальный stdio сервер
claude mcp add --transport stdio --env AIRTABLE_API_KEY=YOUR_KEY airtable \
-- npx -y airtable-mcp-serverВажно: все опции (--transport, --env, --scope) ставятся перед именем сервера. -- разделяет имя от команды запуска.
Три области видимости (scope)
| Scope | Где хранится | Кому доступен | Когда использовать |
|---|---|---|---|
local (default) |
~/.claude.json |
Только тебе, только в этом проекте | Личные серверы, эксперименты |
project |
.mcp.json в корне проекта |
Всей команде (через git) | Общие для проекта инструменты |
user |
~/.claude.json |
Тебе во всех проектах | Личные утилиты для всех проектов |
# Добавить как project scope (для команды)
claude mcp add --transport http --scope project sentry https://mcp.sentry.dev/mcpПри конфликте имён приоритет: local > project > user > plugin > claude.ai connectors. Серверы, заданные администратором организации, имеют приоритет над всеми.
Управление серверами
claude mcp list # Список всех серверов
claude mcp get github # Детали конкретного сервера
claude mcp remove github # Удалить сервер
/mcp # Внутри Claude Code — статус серверов и повторное подключениеТокен-экономика MCP (важно для бизнеса)
Каждый MCP сервер потребляет токены из контекстного окна. Это критично для стоимости:
- Предупреждение при выводе >10,000 токенов от одного вызова
- Лимит по умолчанию: 25,000 токенов на один ответ MCP tool
- Настройка лимита:
MAX_MCP_OUTPUT_TOKENS=50000 claude - Таймаут старта:
MCP_TIMEOUT=10000 claude(10 секунд)
Авто-переподключение: если HTTP/SSE сервер отключается — Claude Code автоматически переподключается с экспоненциальным откатом (до 5 попыток). Локальные stdio-серверы сами не переподключаются: перезапусти их через /mcp.
Три типа объектов MCP
Tools (инструменты) — действия которые Claude может выполнять:
get_contact— получить контакт из CRMcreate_task— создать задачуsend_message— отправить сообщениеquery_database— выполнить запрос к БД
Resources (ресурсы) — данные которые Claude может читать:
crm://contacts/list— список контактовdb://reports/monthly— месячный отчётfile://config/settings— конфиг приложения
Prompts (шаблоны) — готовые инструкции для типовых задач:
analyze_deal— шаблон анализа сделкиwrite_followup— шаблон follow-up письма
Большинству проектов достаточно только tools.
Минимальный MCP сервер: Hello World
Устанавливаем SDK:
npm init -y
npm install @modelcontextprotocol/server zod
npm install -D @types/node typescript
mkdir srcВ package.json добавь "type": "module". Рядом положи tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"types": ["node"],
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}Создаём src/server.ts:
import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { z } from "zod";
// Создаём сервер
const server = new McpServer({
name: "my-first-mcp",
version: "1.0.0",
});
// Добавляем tool — простая функция
server.registerTool(
"get_weather", // Имя tool
{
description: "Получить погоду для города", // Описание для Claude
inputSchema: z.object({ // Параметры (Zod схема)
city: z.string().describe("Название города"),
}),
},
async ({ city }) => {
// Здесь реальная логика: API вызов, БД запрос, и т.д.
// Для примера — заглушка
return {
content: [{
type: "text",
text: `Погода в ${city}: +22°C, облачно`
}]
};
}
);
// Подключаем stdio транспорт и запускаем
const transport = new StdioServerTransport();
await server.connect(transport);Важно: stdio-сервер общается с Claude через стандартный вывод, поэтому в нём нельзя печатать логи через console.log. Для логов используй console.error.
Компилируем и запускаем:
npx tsc
node build/server.jsРеальный пример: MCP сервер для CRM
Полноценный сервер который Claude Code использует для работы с вымышленной CRM через REST API:
import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { z } from "zod";
const CRM_API_URL = process.env.CRM_API_URL || "https://api.mycrm.com";
const CRM_API_KEY = process.env.CRM_API_KEY || "";
const server = new McpServer({
name: "crm-mcp-server",
version: "1.0.0",
});
// Tool 1: Получить контакт по имени или email
server.registerTool(
"get_contact",
{
description: "Найти контакт в CRM по имени или email адресу",
inputSchema: z.object({
query: z.string().describe("Имя или email для поиска"),
}),
},
async ({ query }) => {
const response = await fetch(
`${CRM_API_URL}/contacts/search?q=${encodeURIComponent(query)}`,
{ headers: { "X-API-Key": CRM_API_KEY } }
);
const data = await response.json();
if (!data.contacts?.length) {
return { content: [{ type: "text", text: `Контакт "${query}" не найден` }] };
}
const contact = data.contacts[0];
return {
content: [{
type: "text",
text: JSON.stringify({
id: contact.id,
name: contact.full_name,
email: contact.email,
company: contact.company,
deal_stage: contact.deal_stage,
last_contact: contact.last_contact_date,
}, null, 2)
}]
};
}
);
// Tool 2: Создать задачу
server.registerTool(
"create_task",
{
description: "Создать задачу в CRM привязанную к контакту",
inputSchema: z.object({
contact_id: z.string().describe("ID контакта"),
title: z.string().describe("Название задачи"),
due_date: z.string().describe("Срок выполнения в формате YYYY-MM-DD"),
priority: z.enum(["low", "medium", "high"]).describe("Приоритет задачи"),
}),
},
async ({ contact_id, title, due_date, priority }) => {
const response = await fetch(`${CRM_API_URL}/tasks`, {
method: "POST",
headers: {
"X-API-Key": CRM_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ contact_id, title, due_date, priority }),
});
const task = await response.json();
return {
content: [{
type: "text",
text: `Задача создана. ID: ${task.id}. Срок: ${due_date}. Приоритет: ${priority}.`
}]
};
}
);
// Tool 3: Обновить статус сделки
server.registerTool(
"update_deal_stage",
{
description: "Обновить стадию сделки для контакта",
inputSchema: z.object({
contact_id: z.string().describe("ID контакта"),
stage: z.enum(["lead", "qualified", "proposal", "negotiation", "closed_won", "closed_lost"])
.describe("Новая стадия сделки"),
note: z.string().optional().describe("Заметка к изменению стадии"),
}),
},
async ({ contact_id, stage, note }) => {
await fetch(`${CRM_API_URL}/contacts/${contact_id}`, {
method: "PATCH",
headers: {
"X-API-Key": CRM_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ deal_stage: stage, stage_note: note }),
});
return {
content: [{
type: "text",
text: `Стадия сделки обновлена: ${stage}${note ? `. Заметка: ${note}` : ""}`
}]
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);Регистрация в проекте: .mcp.json
Чтобы Claude Code автоматически запускал твой MCP сервер при открытии проекта, создаёшь .mcp.json в корне проекта:
{
"mcpServers": {
"crm": {
"command": "node",
"args": ["./mcp-servers/crm/build/server.js"],
"env": {
"CRM_API_URL": "https://api.mycrm.com",
"CRM_API_KEY": "${CRM_API_KEY}"
}
}
}
}После этого при открытии Claude Code в этой папке сервер запускается автоматически. Claude видит tools get_contact, create_task, update_deal_stage как встроенные возможности.
Переменные окружения в .mcp.json (официальная фича):
Поддерживается синтаксис ${VAR} и ${VAR:-default} в полях command, args, env, url, headers:
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
}
}
}Это позволяет коммитить .mcp.json в git без секретов — каждый разработчик ставит свои переменные окружения.
Регистрация через CLI (альтернатива):
# Как user scope (доступен во всех проектах)
claude mcp add --transport stdio --scope user crm -- node ./server.js
# Добавить через JSON
claude mcp add-json crm '{"command":"node","args":["./server.js"],"env":{"CRM_API_KEY":"${CRM_API_KEY}"}}'Импорт из Claude Desktop (если уже настроено, работает на macOS и WSL):
claude mcp add-from-claude-desktopТестирование: MCP Inspector
Проект MCP предоставляет интерактивный инспектор для тестирования серверов без Claude (нужен Node 22.19 или новее):
npx @modelcontextprotocol/inspector node build/server.jsОткрывается веб-интерфейс где можно:
- Видеть все зарегистрированные tools
- Вызывать каждый tool вручную с параметрами
- Смотреть что server отвечает
- Дебажить ошибки
Есть и консольный режим: npx @modelcontextprotocol/inspector --cli node build/server.js --method tools/list покажет список tools и завершится. Это гораздо быстрее чем тестировать через Claude Code.
Claude Code как MCP сервер
Claude Code сам может работать как MCP сервер для других приложений:
claude mcp serveПодключение из Claude Desktop:
{
"mcpServers": {
"claude-code": {
"type": "stdio",
"command": "claude",
"args": ["mcp", "serve"],
"env": {}
}
}
}Это даёт другим AI приложениям доступ к инструментам Claude Code (Read, Edit, Bash и др.).
Привязка MCP серверов к суб-агентам
MCP серверы можно привязать к конкретному суб-агенту через поле mcpServers в frontmatter:
---
name: browser-tester
description: Tests features in a real browser using Playwright
mcpServers:
- playwright:
type: stdio
command: npx
args: ["-y", "@playwright/mcp@latest"]
---Инлайн-серверы подключаются при старте суб-агента и отключаются когда он завершает работу. Основной разговор не видит эти инструменты — это экономит контекст.
Python вариант: FastMCP
Если предпочитаешь Python, есть более декларативный способ: SDK строит описание tool из аннотаций типов и docstring. В актуальной документации класс называется MCPServer (в старых примерах встречается FastMCP):
# pip install "mcp[cli]" или uv add "mcp[cli]"
from mcp.server import MCPServer
mcp = MCPServer("crm-server")
@mcp.tool()
def get_contact(query: str) -> str:
"""Найти контакт в CRM по имени или email"""
# Логика поиска
return f"Контакт найден: {query}"
@mcp.tool()
def create_task(contact_id: str, title: str, due_date: str) -> str:
"""Создать задачу в CRM"""
# Логика создания задачи
return f"Задача создана: {title} для {contact_id}"
if __name__ == "__main__":
mcp.run(transport="stdio")Регистрация в .mcp.json:
{
"mcpServers": {
"crm-python": {
"command": "python",
"args": ["./mcp-servers/crm_server.py"]
}
}
}Публикация на npm
Если хочешь поделиться MCP сервером или использовать в нескольких проектах:
# package.json
{
"name": "@yourname/mcp-crm",
"version": "1.0.0",
"type": "module",
"bin": { "mcp-crm": "./server.js" },
"main": "./server.js"
}
# Публикация
npm publish --access publicПосле публикации любой может использовать:
{
"mcpServers": {
"crm": {
"command": "npx",
"args": ["-y", "@yourname/mcp-crm"]
}
}
}Ресурсы MCP: @-упоминания
MCP серверы могут предоставлять resources которые ты ссылаешь через @:
Проанализируй @github:issue://123 и предложи фикс Посмотри документацию @docs:file://api/authentication
Ресурсы появляются в автокомплите рядом с файлами когда ты набираешь @.
Динамическое обновление инструментов
Claude Code поддерживает list_changed нотификации от MCP серверов. Если сервер добавляет или убирает tools — Claude Code автоматически обновляет список без переподключения.
Практика
Задание: MCP сервер для работы с локальными файлами заметок
- Создай папку
my-notes-mcp/, инициализируй проект по шагам из раздела Hello World выше:npm init -y,npm install @modelcontextprotocol/server zod,npm install -D @types/node typescript,"type": "module"иtsconfig.json - Создай
src/server.tsс тремя tools:list_notes— список файлов в папке~/Notes/(или любой твоей)read_note— прочитать конкретный файл по имениcreate_note— создать новый файл с заметкой
- Скомпилируй:
npx tsc - Протестируй через MCP Inspector:
npx @modelcontextprotocol/inspector node build/server.js - Зарегистрируй в
.mcp.jsonпроекта - Перезапусти Claude Code — проверь что tools появились
- Попроси Claude: "Создай заметку о сегодняшней встрече" — он должен использовать твой tool
- Бонус: добавь
search_notestool который ищет по содержимому заметок через grep
Цель: написать работающий MCP сервер с нуля, зарегистрировать и протестировать через Claude Code.
Инструменты и ресурсы
- @modelcontextprotocol/server —
npm install @modelcontextprotocol/server— официальный TypeScript SDK - mcp —
pip install "mcp[cli]"— Python SDK (классMCPServer, раньшеFastMCP) - zod —
npm install zod— типизация параметров tools (обязательно для TypeScript SDK) - MCP Inspector —
npx @modelcontextprotocol/inspector— тестирование без Claude - Документация: modelcontextprotocol.io — спецификация протокола
- Официальная страница MCP в Claude Code: https://code.claude.com/docs/en/mcp
- GitHub: github.com/modelcontextprotocol/servers — сотни готовых серверов
- CLI команды:
claude mcp add— добавить серверclaude mcp list— список серверовclaude mcp get <name>— детали сервераclaude mcp remove <name>— удалитьclaude mcp add-from-claude-desktop— импорт из Claude Desktopclaude mcp add-json <name> '<json>'— добавить из JSONclaude mcp serve— запустить Claude Code как MCP сервер/mcp— статус серверов внутри Claude Code (включая OAuth аутентификацию)
Ключевые выводы
MCP сервер — обычная программа на TypeScript или Python. 30-50 строк кода дают Claude новые инструменты. Сложность растёт только от сложности твоей логики, не от MCP протокола.
Транспорты: stdio (локально), HTTP (remote, рекомендуемый), SSE (deprecated), WebSocket (через JSON-конфиг). Три scope: local (по умолчанию), project (
.mcp.jsonдля команды), user (все проекты).
Токен-экономика: результаты вызовов MCP потребляют контекст (описания инструментов по умолчанию подгружаются по мере надобности). Предупреждение при >10,000 токенов вывода. Лимит по умолчанию 25,000 токенов. Настраивается через
MAX_MCP_OUTPUT_TOKENS.
Тестируй через MCP Inspector перед подключением к Claude — это экономит время на отладке.
MCP серверы можно привязать к суб-агентам через поле
mcpServersв frontmatter — сервер подключается только на время работы суб-агента и не засоряет контекст основного разговора.
.mcp.jsonподдерживает переменные окружения (${VAR},${VAR:-default}) — можно коммитить в git без секретов.
Следующий урок
Отметка хранится только в этом браузере и никуда не отправляется. Мой прогресс