SellChatGPTУроки по Claude › Введение в Model Context Protocol

Введение в Model Context Protocol

Model Context Protocol (MCP) — общие правила, по которым программа отдаёт языковой модели свои данные и действия: описали один раз, дальше подключается любой совместимый клиент. В уроке — архитектура и три примитива протокола, сервер на Python, проверка инспектором и подключение к хосту. После урока вы напишете свой сервер, отладите его и объясните, что летает по проводу при вызове инструмента.

Инструменты глубже 8 разделов ~8 мин чтения практика и чеклист
Содержание урока
  1. Задача, ради которой появился протокол
  2. Кто с кем говорит: хост, клиент, сервер
  3. Три примитива: инструменты, ресурсы, промпты
  4. Сервер на Python: минимальный рабочий каркас
  5. Проверка инспектором до того, как к серверу пустят модель
  6. Подключение к хосту и собственный клиент
  7. Как выбрать примитив под задачу
  8. Ошибки, которые встречаются чаще всего
  9. Практика
  10. Проверьте себя
  11. Частые вопросы
  12. Похожие уроки

Кому подойдёт

Урок для разработчиков на Python, которым нужно подключить модель к своим базам и внутренним API, и для тех, кто хочет понимать устройство серверов MCP, прежде чем ставить чужие.

Что понадобится

Python 3.10 или новее, Node.js (инспектор запускается через npx), редактор и терминал; пакет mcp и инспектор бесплатны и ключей не требуют. Чтобы инструменты вызывала живая модель, нужен хост с платным доступом, а сервисы Anthropic из России открываются только через VPN.

Задача, ради которой появился протокол

До MCP каждая связка «модель плюс внешняя система» писалась заново: свой формат описания функций, свой способ вернуть результат, своя авторизация. Пять источников данных и три приложения — пятнадцать интеграций, и каждая ломается по-своему. Anthropic опубликовала MCP в конце 2024 года как открытую спецификацию против такого умножения; официальные SDK есть для Python, TypeScript, Java, Go и других языков.

Смысл — в разделении ответственности: кто владеет данными, описывает их один раз по общим правилам, а кто владеет моделью — один раз учится эти описания читать. Так же работает Language Server Protocol в редакторах кода. Ваш сервер одинаково подключается и к настольному приложению, и к агенту в терминале, и к своему скрипту.

MCP не заменяет ваш HTTP API и не делает модель умнее: он отвечает только за то, как модель узнаёт о возможностях и в каком виде получает результат. Есть библиотека для работы с базой — сервер будет тонкой обёрткой над ней.

Кто с кем говорит: хост, клиент, сервер

Ролей три. Хост — приложение, в котором живёт модель: настольный клиент, агент в терминале, ваш скрипт. Клиент — объект внутри хоста, держащий соединение ровно с одним сервером: серверов десять, значит и клиентов десять. Сервер — ваш процесс, отвечающий на «что ты умеешь» и «сделай вот это». Напрямую модель с сервером не говорит: между ними хост, он и спрашивает разрешение.

Разговор идёт сообщениями JSON-RPC 2.0: запрос с полем id, ответ с тем же id, уведомление без id. Соединение открывает рукопожатие: клиент шлёт initialize с версией протокола и своими возможностями, сервер отвечает своими, клиент подтверждает notifications/initialized. Дальше спрашивают списки: {"jsonrpc":"2.0","id":1,"method":"tools/list"}, так же resources/list и prompts/list. Изменился набор — сервер шлёт notifications/tools/list_changed.

Транспортов два. При stdio хост сам запускает ваш процесс и общается через стандартный ввод-вывод, отсюда правило: в stdout ничего, кроме протокольных сообщений. Streamable HTTP нужен, когда сервер живёт отдельно от пользователя: один endpoint, POST от клиента, поток событий в ответ. Отдельный SSE-канал из ранних редакций спецификации заменён на Streamable HTTP.

Три примитива: инструменты, ресурсы, промпты

Инструменты (tools) — действия. У каждого есть имя, описание и схема входа в JSON Schema; список забирают через tools/list, вызов делают через tools/call с полями name и arguments. Инициатор — модель: она читает описания и решает, что дёрнуть. Результат приходит блоками содержимого: текст, изображение, ссылка на ресурс. Ошибку отдавайте результатом с флагом isError — протокольную ошибку модель не увидит.

Ресурсы (resources) — данные для чтения по URI: file:///home/user/notes.md или своя схема orders://2026-08-21. Список даёт resources/list, шаблоны с параметрами в фигурных скобках — resources/templates/list, содержимое — resources/read с указанием mimeType. Ресурс выбирает приложение или человек, а не модель: типичный интерфейс — кнопка «прикрепить». Чтение не должно иметь побочных эффектов.

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

Есть и обратное направление: сервер может попросить хост сходить к модели за коротким ответом (sampling), узнать разрешённые каталоги (roots) или спросить пользователя посреди выполнения (elicitation). Поддержка у клиентов разная — смотрите ответ на initialize.

Сервер на Python: минимальный рабочий каркас

Установка одна: pip install "mcp[cli]" в виртуальном окружении. Дальше файл server.py с объектом FastMCP: его имя пользователь увидит в списке подключений. Рукопожатие, маршрутизацию и сериализацию FastMCP берёт на себя.

Инструмент — функция под @mcp.tool(): имя функции становится именем инструмента, докстринг — описанием, аннотации типов — схемой входа. Лаконичность тут вредит: описание читает модель, и «ищет заказ по номеру вида SCG-12345, возвращает статус, сумму и дату оплаты» полезнее, чем «поиск заказа». Для сложных правил — Pydantic и Field(description=...).

Ресурс объявляется как @mcp.resource("orders://{date}"), параметры из URI приезжают аргументами; промпт — @mcp.prompt(). Запуск в конце файла: mcp.run() поднимает stdio, mcp.run(transport="streamable-http") — сетевой транспорт. Аргумент ctx: Context даёт ctx.info() и ctx.report_progress().

  • pip install "mcp[cli]"
  • from mcp.server.fastmcp import FastMCP
  • mcp = FastMCP("orders")
  • @mcp.tool() над def find_order(number: str) -> str: с докстрингом
  • @mcp.resource("orders://{date}") над def orders_by_day(date: str)
  • if __name__ == "__main__": mcp.run()

Проверка инспектором до того, как к серверу пустят модель

Отлаживать сервер сразу в чате — худший вариант: непонятно, кто ошибся, вы или модель. Инспектор поднимается командой mcp dev server.py или npx @modelcontextprotocol/inspector python server.py. Внутри — вкладки примитивов, форма для аргументов и журнал сообщений.

Главная ценность инспектора — сырые сообщения: initialize, ответ сервера, tools/list и каждый tools/call с аргументами и результатом. Если сервер не стартует, там же traceback, и причина скучная: не тот интерпретатор, зависимости в другом окружении, опечатка в пути.

  • Рукопожатие прошло, сервер отвечает
  • Схема как задумана: необязательный параметр не стал обязательным
  • Корректные аргументы дают ожидаемый результат
  • Мусор на входе даёт ошибку, а не роняет процесс
  • Ресурс читается по URI, шаблон подставляет параметр
  • Промпт разворачивается в осмысленные сообщения

Подключение к хосту и собственный клиент

Настольному клиенту сервер прописывают в claude_desktop_config.json (%APPDATA%\Claude на Windows, ~/Library/Application Support/Claude на macOS): объект mcpServers, внутри запись с command и args, секреты — блоком env. Пути указывайте абсолютные, python берите из своего окружения, иначе процесс не найдёт зависимости. После правки конфига приложение закрывают полностью; в терминальном агенте то же делает claude mcp add.

Свой клиент — несколько десятков строк: StdioServerParameters с командой запуска, stdio_client, ClientSession, затем await session.initialize(), list_tools() и call_tool("find_order", {"number": "SCG-12345"}). Так же работают read_resource и get_prompt.

Дальше клиент соединяют с моделью: список из list_tools переводится в описание инструментов вашего API почти один в один. Модель просит вызов — вы выполняете его через call_tool, отдаёте результат и повторяете цикл, пока она не закончит. Здесь начинаются расходы: токены тарифицируются, доступ из России требует VPN, сам сервер остаётся локальным и бесплатным.

  • from mcp import ClientSession, StdioServerParameters
  • from mcp.client.stdio import stdio_client
  • await session.initialize()
  • tools = await session.list_tools()
  • result = await session.call_tool("find_order", {"number": "SCG-12345"})

Как выбрать примитив под задачу

Правило простое. Есть побочный эффект, параметры или поиск — инструмент. Нужно отдать данные, которые человек выберет сам, — ресурс. Хотите зафиксировать формулировку задачи целиком — промпт. Спорное решает вопрос: кто должен решать, что это вызывается прямо сейчас.

На каталоге договоров: список файлов и содержимое файла — ресурсы, договор выбирает юрист. Поиск с фильтрами по дате и контрагенту — инструмент, запрос формулирует модель. Отправка уведомления — инструмент с подтверждением на стороне хоста. «Сверь редакцию с шаблоном и выпиши отличия» — промпт.

Учтите ограничение: часть клиентов умеет только инструменты. Если сервер должен работать везде, продублируйте ключевые ресурсы инструментами list_contracts и read_contract.

Набор держите компактным: описания всех инструментов уходят в контекст модели на каждом шаге и сбивают выбор, когда имена близки по смыслу. Универсальный do_anything с полем action тоже плох — модель лишается подсказки в виде схемы.

Ошибки, которые встречаются чаще всего

Самая обидная — обычный print в stdio-сервере: stdout занят протоколом, посторонняя строка ломает разбор JSON, и соединение падает без объяснений. Логи пишите в stderr или через контекст сервера.

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

Третья — объём ответа. Инструмент, вываливающий весь дамп таблицы, съедает контекст и деньги: добавьте limit и offset, отдавайте страницу или сводку вместо сырых строк.

И про безопасность: локальный сервер работает с вашими правами, а его ответ попадает в контекст модели, где могут оказаться строки под видом системных указаний. Ставьте серверы, авторам которых доверяете, и подтверждайте необратимые действия руками.

  • Относительные пути и системный python в конфиге
  • Забыли перезапустить хост после правки конфига
  • Секреты в коде, а не в блоке env

Практика

  1. Создайте виртуальное окружение и установите пакет: pip install "mcp[cli]".
  2. Напишите server.py: объект FastMCP и инструмент под @mcp.tool() с аннотациями типов и честным докстрингом — поиск заказа в словаре-заглушке.
  3. Запустите mcp dev server.py и вызовите инструмент в инспекторе: с корректными аргументами, с пустой строкой, с числом вместо строки.
  4. Добавьте ресурс через @mcp.resource с параметром в URI и промпт через @mcp.prompt(), перечитайте списки и проверьте подстановку.
  5. Вставьте print("debug") в тело инструмента, посмотрите, как рвётся соединение, и замените вывод на логи в stderr.
  6. Пропишите сервер в claude_desktop_config.json с абсолютными путями, перезапустите приложение и дайте модели задачу под ваш инструмент.
  7. Напишите client.py: stdio_client, ClientSession, initialize, list_tools и call_tool — выведите список инструментов и результат вызова.

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

  • Объясняю разницу между хостом, клиентом и сервером и называю оба транспорта
  • Сервер проходит рукопожатие и отдаёт tools/list, вызов в инспекторе возвращает ожидаемый результат
  • Понимаю, кто инициирует вызов инструмента, ресурса и промпта, и выбираю примитив под задачу
  • Подключаю сервер к хосту через конфиг и нахожу по журналу причину, если он не поднялся
  • Написал свой клиент и провёл цикл: список инструментов, вызов, возврат результата модели
  • Знаю, почему вывод в stdout ломает stdio-сервер, и возвращаю ошибку так, чтобы её прочитала модель

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

Нужен ли платный доступ, чтобы попробовать MCP?

Чтобы написать сервер и прогнать его через инспектор — нет: пакет mcp и инспектор работают локально, без ключей и без оплаты. Деньги начинаются там, где подключается модель: подписка на приложение и обращения к API тарифицируются отдельно. Доступ к сервисам Anthropic из России требует VPN — и для приложений, и для API.

MCP работает только с Claude?

Нет, спецификация открытая, серверы подключают разные хосты, редакторы и агентские фреймворки. Различается не протокол, а глубина поддержки: где-то есть только инструменты, где-то ещё ресурсы, промпты и обратные вызовы. Что умеет конкретный клиент, видно в его ответе на initialize.

Что выбрать: stdio или HTTP?

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

Как проверить чужой сервер перед установкой?

Прочитайте код и список инструментов: что каждый делает с вашими данными и куда ходит по сети. Посмотрите, какие пути и переменные окружения сервер просит в конфиге — доступ к домашнему каталогу целиком нужен редко. Первый запуск делайте на тестовых данных, в отдельном окружении или контейнере.

Чем MCP отличается от вызова функций через API модели?

Вызов функций (tool use) — формат одного запроса: вы перечисляете инструменты в теле запроса и сами исполняете вызовы. MCP добавляет уровень выше: обнаружение возможностей, транспорт, единый способ отдавать данные и шаблоны сообщений. Разница в переносимости — один сервер подключается к разным приложениям без переписывания.

Чтобы пройти практику, нужен рабочий доступ

Подключим подписку на ваш аккаунт: оплата картой РФ, по СБП или криптой, пароль от аккаунта не нужен. Обычно за 15 минут в рабочее время.

Подключить Claude Pro — 2 490 ₽ Все уроки

Похожие уроки