
MCP-сервер из API: чем MCP отличается от API и как собрать его из OpenAPI
MCP-сервер из API отдаёт модели методы вашего REST API как инструменты, и FastMCP, генераторы или шлюзы собирают его из файла OpenAPI за несколько строк. Ниже разница между MCP и API, код на Python, готовые генераторы и шлюзы, пример с Wildberries и ограничения подхода.
адреса и методы вашего сервиса
описание API в JSON или YAML
from_openapi, RouteMap, фильтры
инструменты с описанием и JSON Schema
Claude, Cursor, Codex вызывают инструменты
Чем MCP отличается от API
REST API отвечает на HTTP-запросы по адресам и методам, которые описаны в документации. OpenAPI задаёт для такого описания единый формат, независимый от языка программирования: по нему человек и программа понимают, что умеет сервис, без исходного кода и разбора трафика.
MCP (Model Context Protocol) — открытый протокол для связи ИИ-приложений с внешними системами, построенный на сообщениях JSON-RPC 2.0. В нём три участника: хост, то есть ИИ-приложение вроде Claude или Cursor, клиент внутри хоста и сервер. Сервер отдаёт инструменты для модели, ресурсы с данными и шаблоны промптов. MCP сравнивают с портом USB-C для ИИ-приложений: один разъём для любых внешних систем.
Поэтому MCP с API не соперничает. В спецификации MCP среди задач инструментов прямо названы запросы к базам данных, вызовы API и вычисления: MCP-сервер чаще всего сам ходит в API и пересказывает модели его возможности на понятном ей языке.
| REST API | MCP | |
|---|---|---|
| Кто читает описание | разработчик и его программа, по документации OpenAPI | модель: клиент получает tools/list прямо во время работы |
| Формат обмена | HTTP-запросы по адресам и методам | сообщения JSON-RPC 2.0 |
| Что описано | эндпоинты, параметры и ответы | инструменты, ресурсы и шаблоны промптов |
| Кто решает, что вызвать | код, который написал разработчик | модель, по смыслу запроса пользователя |
| Как связаны | API работает как раньше | MCP-сервер сам ходит в API и пересказывает модели его возможности |
Когда сервер из API имеет смысл
Сервер, собранный из OpenAPI автоматически, хорош на старте: для прототипа, внутреннего демо или чтобы посмотреть на свой API глазами агента. Джереми Лоуин, автор FastMCP, называет конвертер OpenAPI полезным инструментом для старта и просит не выпускать такой сервер в продакшен.
Модели заметно лучше работают с продуманным набором инструментов, чем с сервером, механически снятым с OpenAPI. Разрыв особенно велик у сложных API с множеством эндпоинтов и параметров.
Причина в устройстве REST API: сотни узких эндпоинтов, гибкие параметры и масса вариантов удобны разработчику, агента они перегружают. Каждый лишний эндпоинт — плата токенами и задержкой на каждом шаге диалога. Мелкие атомарные вызовы агенту тоже мешают: цепочка из них медленная, ломается на любом звене и сжигает токены.
Если API большой и сервер нужен надолго, начните с задачи агента и напишите только инструменты под неё. Непонятные аргументы переименуйте, лишние параметры спрячьте за значениями по умолчанию. Сервер из OpenAPI годится как черновик: по нему видно, какие инструменты получились, и нужные можно переписать руками. Как написать сервер с нуля, разобрано на странице /mcp/sozdat-mcp-server/.
FastMCP: MCP-сервер из OpenAPI на Python
FastMCP — библиотека на Python 3.11 и новее, ставится командой uv add fastmcp. Метод FastMCP.from_openapi принимает спецификацию в виде словаря и асинхронный HTTP-клиент с базовым адресом API. Каждый эндпоинт из спецификации становится инструментом MCP, а вызов инструмента — HTTP-запросом к вашему API.
Имя инструмента берётся из operationId до первого двойного подчёркивания. Если operationId нет, в ход идёт summary, а без него — метод и путь. Имена переводятся в slug, обрезаются до 56 знаков, к повторам дописывается номер. Свои имена задаёт словарь mcp_names.
В актуальных версиях FastMCP клиент — httpx2.AsyncClient. Старый httpx.AsyncClient пока принимается с предупреждением об устаревании. Если клиент не передать, FastMCP создаст свой по первому адресу из блока servers спецификации, с таймаутом 30 секунд.
Внутри работает OpenAPIProvider, он появился в FastMCP 3.0.0. Его можно подключить к уже готовому серверу через mcp.add_provider и держать рядом инструменты, написанные руками.
import httpx2
from fastmcp import FastMCP
# Create an HTTP client for your API
client = httpx2.AsyncClient(base_url="https://api.example.com")
# Load your OpenAPI spec
spec = httpx2.get("https://api.example.com/openapi.json").json()
# Create the MCP server
mcp = FastMCP.from_openapi(
openapi_spec=spec,
client=client,
name="My API Server"
)
if __name__ == "__main__":
mcp.run()Какие эндпоинты отдать модели: RouteMap
По умолчанию FastMCP делает инструментом каждый эндпоинт: большинство клиентов MCP поддерживает только инструменты. Правила меняет упорядоченный список RouteMap. В каждом правиле указаны HTTP-методы, регулярное выражение для пути, теги OpenAPI и тип результата: TOOL, RESOURCE, RESOURCE_TEMPLATE или EXCLUDE.
Маршрут проверяется по правилам по порядку, срабатывает первое совпавшее, ваши правила идут раньше правила по умолчанию. Тип EXCLUDE убирает маршрут с сервера. Правило RouteMap(mcp_type=MCPType.EXCLUDE) в конце списка выключает всё, что вы не перечислили выше, и так собирается белый список эндпоинтов.
Для сложной логики есть функция route_map_fn: её вызывают для каждого маршрута, и она может сменить тип, даже отменить исключение. Функция mcp_component_fn правит уже созданный компонент на месте, например дописывает описание для модели. Теги из OpenAPI клиент видит в поле meta.fastmcp.tags.
from fastmcp import FastMCP
from fastmcp.server.providers.openapi import RouteMap, MCPType
mcp = FastMCP.from_openapi(
openapi_spec=spec,
client=client,
route_maps=[
# Analytics `GET` endpoints are tools
RouteMap(
methods=["GET"],
pattern=r"^/analytics/.*",
mcp_type=MCPType.TOOL,
),
# Exclude all admin endpoints
RouteMap(
pattern=r"^/admin/.*",
mcp_type=MCPType.EXCLUDE,
),
# Exclude all routes tagged "internal"
RouteMap(
tags={"internal"},
mcp_type=MCPType.EXCLUDE,
),
],
)Ключи, таймауты и ошибки API
Токен задаётся на HTTP-клиенте: заголовки из headers уходят с каждым запросом. Если операция в OpenAPI сама объявляет заголовок параметром, значение берётся из вызова инструмента.
Когда MCP-сервер работает по HTTP, FastMCP передаёт в API заголовки входящего запроса, кроме учётных и служебных: Authorization, Cookie, Host. Токен, с которым клиент пришёл к MCP-серверу, сам в ваш API не попадёт.
httpx2.AsyncClient по умолчанию ждёт 5 секунд без сетевой активности. Для медленного API передайте клиенту timeout=30.0, а timeout=None выключит ожидание совсем.
Ошибку API модель получает со статусом и причиной, для 429 сохраняется текст «Rate limited by upstream API, please retry later». JSON-тело ошибки передаётся как JSON, HTML-страницы отбрасываются, прочий текст обрезается до 1 000 знаков. Параметр mask_error_details=True прячет подробности. Аргументы, которых нет в операции, FastMCP отбрасывает с предупреждением в журнале, а в строгом режиме проверки вызов падает до отправки запроса.
import httpx2
from fastmcp import FastMCP
# Bearer token authentication
api_client = httpx2.AsyncClient(
base_url="https://api.example.com",
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
# Create MCP server with authenticated client
mcp = FastMCP.from_openapi(
openapi_spec=spec,
client=api_client,
)Пример: свой API на FastAPI превращается в MCP одной строкой
Если API написан на FastAPI, файл спецификации искать не нужно: FastMCP.from_fastapi(app=app) берёт её из самого приложения. FastAPI в зависимости FastMCP не входит, его ставят отдельно.
Получается обычный сервер FastMCP: к нему можно добавить свои инструменты декоратором @mcp.tool, работают те же RouteMap. Имена инструментов складываются из имени функции, пути и метода, например create_product_products_post и list_products_products_get, поэтому их стоит переименовать через mcp_names.
В Claude Code сервер ставится командой fastmcp install claude-code server.py, она сама вызывает claude mcp add. Ключи API передаются флагами --env или файлом через --env-file.
# Assumes the FastAPI app from above is already defined
from fastmcp import FastMCP
# Convert to MCP server
mcp = FastMCP.from_fastapi(app=app)
if __name__ == "__main__":
mcp.run()
# Установка в Claude Code (в терминале):
# fastmcp install claude-code server.py --env API_KEY=your-api-keyГотовые генераторы и шлюзы
# openapi-mcp-generator: проект на TypeScript из спецификации
npx openapi-mcp-generator --input ./openapi.json --output ./my-mcp
# @ivotoby/openapi-mcp-server: без генерации кода, только мета-инструменты
npx @ivotoby/openapi-mcp-server --api-base-url https://api.example.com --openapi-spec https://api.example.com/openapi.json --tools dynamic
# Speakeasy: сервер на TypeScript через мастер
speakeasy quickstart --mcp
# agentgateway: цель типа openapi в config.yaml
# targets:
# - name: openapi
# openapi:
# schema:
# file: ./examples/mcp-openapi/openapi.json
# host: localhost:8080
agentgateway -f config.yamlopenapi-mcp-generator — CLI на Node.js под лицензией MIT. Из OpenAPI 3.0 или 3.1 он генерирует проект на TypeScript под stdio, SSE, Streamable HTTP или Cloudflare Workers, и код остаётся у вас. Ключи берутся из переменных окружения, аргументы проверяются по JSON Schema до запроса, операции отбираются флагами --include-tags, --exclude-tags, --include-operations и --exclude-operations. Версия 5 требует Node.js 22.19 или новее и не принимает Swagger 2.0: его сначала переводят командой npx swagger2openapi.
@ivotoby/openapi-mcp-server обходится без генерации кода: запускается через npx с адресом API и ссылкой на спецификацию, заголовки для авторизации передаются в API_HEADERS. В режиме --tools dynamic вместо инструмента на каждый эндпоинт сервер отдаёт три мета-инструмента: list-api-endpoints, get-api-endpoint-schema и invoke-api-endpoint. Фильтры --tag, --resource и --operation оставляют нужную часть API.
Speakeasy собирает сервер на TypeScript командой speakeasy quickstart --mcp. Расширение x-speakeasy-mcp в OpenAPI задаёт имена, описания и scope инструментов. Флаг --scope read при запуске монтирует только инструменты со scope read, и сервер работает на чтение. Режим --mode dynamic оставляет мета-инструменты list_tools, describe_tool и execute_tool.
Шлюзы собирают MCP из API без кода. В agentgateway цель типа openapi в YAML-конфиге превращает каждый метод спецификации в инструмент и проксирует вызовы в API. IBM ContextForge регистрирует REST-инструменты через свой API с полем integration_type REST, сопоставлением аргументов заголовкам и параметрам запроса, таймаутом и списком разрешённых хостов, а потом собирает их в виртуальный сервер. Unla — шлюз на Go, переводит REST API в MCP по YAML-конфигу, который вставляют в веб-интерфейсе. Сравнение шлюзов — на странице /mcp/proksi-shlyuzy/.
API Wildberries и MCP
Wildberries описывает Seller API в спецификациях OpenAPI 3.0, по файлу на раздел: общее, работа с товарами, заказы FBS и DBW, DBS, самовывоз, поставки FBW, продвижение, общение с покупателями, тарифы, аналитика, отчёты, документы и бухгалтерия. Токен передаётся в заголовке Authorization.
Сервер marketplaces-mcp-ru собрал из этих спецификаций каталог на 307 методов WB в 70 секциях. Инструмент на каждый эндпоинт дал бы больше 300 инструментов, поэтому агенту отданы мета-инструменты поверх каталога: поиск метода, его описание, вызов на чтение, запись с подтверждением и удаление с двойным подтверждением.
У методов, импортированных из спецификаций, пути надёжны, HTTP-методы нет: живая проверка находила GET, которые на деле POST и отвечают 405. Если собираете сервер для кабинета сами, начните с одного раздела и через RouteMap оставьте только GET, пока не проверите запись. Готовые серверы для кабинета продавца собраны на странице /mcp/wildberries/.
Ограничения
Каждый инструмент с описанием и схемой попадает в контекст модели, и при сотнях эндпоинтов растут расход токенов, задержка и путаница между похожими инструментами. Помогают фильтры по тегам и путям, scope на чтение и динамический режим с мета-инструментами.
Спецификация MCP приравнивает инструмент к выполнению произвольного кода: хост обязан спросить согласие пользователя перед вызовом любого инструмента, а для чувствительных операций клиенту рекомендовано отдельное подтверждение. Подсказки readOnlyHint и destructiveHint клиент обязан считать недоверенными, если они пришли от сервера вне доверенного круга. Значение destructiveHint по умолчанию — true. POST, PUT и DELETE, которые модели не нужны, выключайте через EXCLUDE.
Сервер обязан проверять входные данные, ограничивать доступ и частоту вызовов и очищать выходные данные. FastMCP не пропускает в путевых параметрах сегменты . и .., openapi-mcp-generator по умолчанию не тянет внешние $ref ради защиты от SSRF и отказывает в вызове, если нужного ключа нет.
Модель выбирает инструмент по имени, описанию и схеме, и без operationId и summary имена выйдут вида метод плюс путь. Составные схемы FastMCP разворачивает в плоский набор аргументов: у тел с discriminator все поля вариантов становятся необязательными, и неверную комбинацию отклонит уже сам API.
Частые вопросы
Что такое API MCP?
Чем MCP отличается от API?
Как сделать MCP-сервер из REST API?
Можно ли подключить OpenAPI к Claude через MCP?
Есть ли MCP-сервер для API Wildberries?
Источники: https://modelcontextprotocol.io/specification/2026-07-28, https://modelcontextprotocol.io/specification/2026-07-28/ser, https://modelcontextprotocol.io/docs/getting-started/intro, https://modelcontextprotocol.io/docs/learn/architecture, OAI/OpenAPI-Specification, PrefectHQ/fastmcp/blob/main/docs/integrations/openapi.mdx, PrefectHQ/fastmcp/blob/main/docs/integrations/fastapi.mdx, PrefectHQ/fastmcp/blob/main/docs/integrations/claude-code.md