MCP-сервер превращает API в несколько именованных инструментов, которые агент вызывает прямо в ходе разговора. Длинная задача в такой схеме укладывается благодаря инструменту, который возвращает дескриптор, и агент короткими шагами ждёт его готовности. Вставьте ссылку на подкаст, попросите пересказ на французском, и ни одной строки кода писать не придётся.
Программный агент может работать с API VocalStack так же, как любая программа: прочитать справочник API, написать несколько строк с использованием SDK и запустить их. Это правильный путь для того, что будет работать без участия агента.
MCP (Model Context Protocol) нужен для другого случая: вы общаетесь с ассистентом и хотите, чтобы он прямо сейчас что-то расшифровал, без кода. MCP-сервер публикует короткий список именованных инструментов, и у каждого есть описание и JSON-схема аргументов. Агент читает этот список один раз и вызывает инструмент по имени, когда запрос ему соответствует. Просьба «Расшифруй этот подкаст и скажи, что в нём говорили о ценах» превращается в три вызова инструментов, и агент ни разу не видит HTTP-маршрута.
Серверы бывают двух видов. Локальный сервер запускается как подпроцесс клиента и работает через stdio, так устроены большинство серверов для файловых систем и баз данных. Удалённый сервер находится за URL и работает по Streamable HTTP, транспорту, который в мартовской редакции спецификации 2025 года заменил прежний транспорт HTTP-plus-SSE (server-sent events). Клиент отправляет каждый запрос, а сервер отвечает по тому же соединению; всё, что ему нужно сказать до окончательного результата, передаётся потоком заранее. Любой клиент, написанный по актуальной спецификации, может работать с серверами любого из этих видов.
Сервер VocalStack относится к удалённому виду, он доступен по адресу {{api}}/v1/mcp, и пользоваться им стоит столько же, сколько API. Для подключения нужен только URL.
Откройте раздел Developers на панели управления по ссылке {{app}}/developers. На первой вкладке Connect an AI agent показаны адрес сервера и фрагмент настройки для каждого клиента. Три фрагмента ниже совпадают с теми, что там показаны.
Выполните эту команду в терминале:
claude mcp add --transport http vocalstack {{api}}/v1/mcp
Добавьте это в .cursor/mcp.json в вашем проекте или в ~/.cursor/mcp.json, чтобы настройка действовала для всех проектов:
{"mcpServers":{"vocalstack":{"url":"{{api}}/v1/mcp"}}}
Любой клиент, который поддерживает Streamable HTTP, может добавить сервер по этому URL. Ниже общий вид, который показывает панель управления:
{
"vocalstack": {
"type": "streamable-http",
"url": "{{api}}/v1/mcp"
}
}
Для начала ключ API не нужен. При первом подключении клиента вы входите в свой аккаунт VocalStack в браузере, а клиент сохраняет токен. Панель управления сообщает об этом одной строкой: "You'll sign in with your VocalStack account the first time. No key needed."
Это работа спецификации авторизации MCP, а не особый трюк VocalStack. Удалённый сервер отвечает на неаутентифицированный запрос ошибкой 401, которая указывает на его метаданные защищённого ресурса: небольшой JSON-документ, в котором названы сервер авторизации и области доступа, которые требует сервер. Клиент читает его, проходит стандартный поток OAuth 2.1 в браузере и возвращается с токеном, выданным только для этого сервера. Любой удалённый MCP-сервер, который следует спецификации, авторизует вас так же, поэтому перечисленные выше клиенты справляются с этим, ничего не зная о VocalStack.
Ключ API тоже работает, для клиента, запущенного на сервере или в скрипте. Передавайте его в заголовке Authorization: Bearer vs_key_..., тот же заголовок принимает REST API. Ключи создаются в разделе Developers → API keys. Два инструмента транскрибации требуют разрешений Write и Stream audio. Второе кажется странным для файла, но инструменты проходят через ту же точку создания, что и любая транскрибация, включая живые, и эта точка проверяет оба разрешения. Инструментам чтения нужно разрешение Read; list_voices требует только действующих учётных данных.
Войдя в систему, агент видит девять инструментов. Вы редко будете называть их сами, но знание о них объясняет, что агент будет делать дальше.
Каждый инструмент принимает и возвращает JSON в camelCase с теми же именами полей, что и типы /v1; дескриптор транскрибации — её transcriptionId.
transcribe_url начинает транскрибацию аудио или видео по публичному URL: ссылка на файл, эпизод подкаста, видео YouTube. Прямые трансляции не принимаются. Необязательные аргументы: name, spokenLanguage (не указывайте его, чтобы язык определился автоматически), speakerLabels (auto, on или off) и startS/endS, чтобы транскрибировать только часть аудио.transcribe_file делает то же самое для файла, который есть у агента: он передаётся как fileBase64 вместе с filename. Размер после декодирования ограничен 10 МиБ, это примерно десять минут MP3 при 128 кбит/с; для большего файла дайте агенту ссылку.Оба инструмента сразу возвращают transcriptionId, state: "queued" и подсказку next с именем инструмента ожидания. Транскрипции, созданные агентом, начинаются как приватные, без ссылки для общего доступа.
Агент не может выдержать живую трансляцию терпеливее, чем вы: он вызывал бы инструмент ожидания, пока кто-нибудь не забрал бы у него ноутбук. У готовой записи есть конец, и именно его ждёт следующая пара инструментов.
Вызов инструмента — это один HTTP-запрос, а HTTP-запросы не рассчитаны на час. Клиенты обрывают такие запросы, прокси их закрывают, а модель, заблокированная на одном инструменте, ничего другого делать не может. Поэтому для любой длинной задачи через MCP действует тот же шаблон, что и в REST API: запустить задачу и получить дескриптор, ждать её ограниченное время и вызвать инструмент снова, если она ещё не готова. Состояние хранит дескриптор, а не соединение.
wait_for_transcription ждёт, пока задача не станет done или failed, либо пока не истечёт timeoutS (по умолчанию 50 секунд, максимум 60, чтобы вызов укладывался в таймауты, которые применяют большинство клиентов и прокси). Если результат содержит timedOut: true, задача ещё идёт, и агент вызывает инструмент снова. Пока инструмент ждёт, сервер отправляет уведомления о прогрессе MCP, если клиент их запросил: процент и фазу, например «загрузка 3.1 / 8.0 МБ» или «транскрибация 01:25 из 02:00».get_transcription возвращает статус и, когда задача готова, текст. format: "text" выдаёт по одной строке на сегмент в виде [mm:ss] Speaker 1: ...; "segments" выдаёт строки с временными метками start, end, speaker и speakerName; includeWords: true добавляет тайминги слов. Результаты разбиваются на страницы (offset, limit, по умолчанию 500 сегментов) с полем nextOffset, если остались ещё данные.Разбиение на страницы нужно модели, а не сети. Всё, что возвращает инструмент, попадает в контекстное окно агента, где оно конкурирует с вашим разговором и тратит токены на каждом следующем шаге. Двухчасовая встреча — это десятки тысяч слов; если вернуть их все сразу, вопрос, который вы задали, вытеснится из контекста. Хорошие инструменты MCP возвращают страницу и курсор и позволяют агенту решить, сколько ему нужно.
Разрыв соединения или таймаут никогда не отменяет задачу, потому что задача живёт на сервере, а не в запросе MCP. Когда она готова, она становится ещё одной записью в вашей библиотеке, и следующие инструменты работают с ней так же, как с любой другой.
list_transcriptions выводит транскрипции аккаунта, сначала новые, с состоянием и длительностью; lifecycle принимает значения active, archived или all.search_transcriptions ищет сказанное во всех транскрипциях, на любом языке, и возвращает подходящие строки, каждая с указанием транскрипции и секунды, на которой это прозвучало. transcriptionId сужает поиск до одной транскрипции; lang добавляет перевод каждого совпадения.Найти строку — простая половина задачи. Ещё два инструмента разбираются с тем, что говорилось во всём материале.
get_summary возвращает ИИ-заголовок и краткое содержание готовой транскрипции, при необходимости переведённые с помощью lang. Состояние state: "pending" означает, что краткое содержание ещё пишется (обычно оно готово в течение нескольких секунд после завершения задачи), и агент спрашивает снова.translate_transcription возвращает готовую расшифровку на другом языке, как текст или как сегменты с временными метками, с разбиением на страницы, как у get_transcription. Переводы сохраняются, поэтому повторный запрос не повторяет работу.list_voices выводит голоса, которые могут озвучить расшифровку на нужном языке: идентификатор, имя, пол и акцент, если они известны, оценку качества и то, является ли голос стандартным или одним из ваших клонированных голосов. Он описывает голоса, но не заставляет один из них что-то произнести (подробнее о том, чего сервер не делает, ниже).Вот как инструменты работают вместе на практике.
Когда сервер подключён, разговор в Claude Code выглядит так. Вы вставляете ссылку на подкаст и просите пересказ на французском.
Агент вызывает transcribe_url:
{ "url": "https://example.org/episodes/42.mp3", "name": "Episode 42", "speakerLabels": "auto" }
Он получает transcriptionId и state: "queued" и следует подсказке next:
{ "transcriptionId": "4f1c...", "timeoutS": 50 }
Пятидесятиминутный эпизод транскрибируется в много раз быстрее, чем проигрывается, но не за одно ожидание. Первое ожидание возвращает timedOut: true с прогрессом, скажем, 61 процент, поэтому агент вызывает инструмент ещё раз и получает state: "done".
Теперь агент вызывает get_summary с lang: "fr":
{ "transcriptionId": "4f1c...", "lang": "fr" }
Если краткое содержание всё ещё pending, агент ждёт несколько секунд; иначе он передаёт вам заголовок и краткое содержание на французском. Спросите «где они говорили о ценах?», и агент вызовет search_transcriptions с query: "pricing" и тем же transcriptionId, а затем процитирует подходящие строки с их временными метками. Попросите весь текст на французском, и он вызовет translate_transcription.
Несколько вызовов инструментов, без кода, и транскрипция в вашей библиотеке. Каждый из этих вызовов прошёл через те же проверки, что и запрос REST, а именно эти проверки определяют счёт и лимиты.
Сервер MCP — это API, работающий через другой вход: те же лимиты и тот же счёт.
POST /v1/transcriptions: действуют лимит создания тарифа (10, 100 или произвольное число транскрипций, начатых за час), ограничение одновременных транскрипций (1, 5 или без ограничения) и ваш кредит. Бонус при регистрации в $5 покрывает первую сессию, карта не нужна.isError: true с кодом ошибки REST API, предложением, по которому модель может действовать, и полями retryable и retryAfterS. У insufficient_credit есть topUpUrl; rate_limited сообщает, сколько ждать. Это важнее, чем кажется: модель читает текст ошибки, и предложение, по которому можно действовать, превращает тупик в следующий вызов инструмента./v1/mcp: зацикленный агент получает HTTP 429 с Retry-After до того, как запустится любой инструмент.idempotencyKey: повторное использование ключа завершённого вызова возвращает первый результат, а повторное использование с другими аргументами отклоняется, так что агент, который повторяет вызовы сам, никогда не запустит вторую задачу. Любой инструмент, который тратит деньги, должен это поддерживать: агенты повторяют вызовы куда охотнее людей.Это границы того, что делает сервер. Два пункта намеренно находятся за их пределами.
У сервера нет инструмента, который превращает произвольный текст в речь, и такой инструмент не планируется. VocalStack озвучивает расшифровки и их переводы стандартным или клонированным голосом и больше ничего. list_voices сообщает агенту, какие голоса могут прочитать расшифровку на нужном языке, а не как заставить голос произнести что-то новое.
Инструменты транскрибации также не принимают прямые трансляции. Прямой эфир YouTube или радиопоток требует живой транскрибации, которую запускают из панели управления или через POST /v1/transcriptions/live в справочнике API. Готовое видео YouTube — это файл, и transcribe_url его принимает.
Если вы предпочитаете написать код сами, транскрибация файла через API описывает те же шаги в виде HTTP-вызовов, а руководство по транскрибации в реальном времени рассказывает о WebSocket.