Сервер MCP перетворює API на кілька іменованих інструментів, які агент викликає під час розмови, а довга задача вміщується в один із них, коли інструмент повертає дескриптор, на який агент чекає обмежені проміжки часу. Вставте посилання на подкаст, попросіть основну думку французькою, і жодного коду писати не доведеться.
Програмний агент може використовувати API VocalStack так само, як будь-яка програма: прочитати довідку з API, написати кілька рядків із SDK і запустити їх. Це правильний шлях для того, що працюватиме без агента.
MCP (Model Context Protocol) призначений для іншого випадку: ви спілкуєтеся з асистентом і хочете, щоб він щось розшифрував просто зараз, без коду. Сервер MCP публікує короткий список іменованих інструментів, кожен з описом і JSON-схемою аргументів. Агент читає список один раз і викликає інструмент за назвою, коли запит відповідає йому. «Транскрибуй цей подкаст і скажи, що там казали про ціни» стає трьома викликами інструментів, а агент ніколи не бачить HTTP-маршруту.
Серверів два типи. Локальний сервер працює як підпроцес клієнта і обмінюється даними через stdio, так працює більшість серверів для файлових систем і баз даних. Віддалений сервер розміщений за URL і працює через Streamable HTTP, транспорт, що замінив старіший HTTP plus SSE (server-sent events) у березневій редакції специфікації 2025 року. Клієнт надсилає кожен запит, а сервер відповідає на тому самому з’єднанні; все, що він має сказати до фінального результату, передається потоком раніше. Будь-який клієнт, написаний під поточну специфікацію, може працювати з обома типами.
Сервер VocalStack є віддаленим, за адресою {{api}}/v1/mcp, і користування ним коштує стільки ж, скільки коштує API. Усе, що вам потрібно, — це URL.
Відкрийте розділ Developers на панелі керування за посиланням {{app}}/developers. Перша вкладка, Connect an AI agent, показує URL сервера і фрагмент налаштування для кожного клієнта. Три фрагменти нижче відповідають тим, що показано там.
Виконайте це у вашому терміналі:
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 у браузері, а клієнт зберігає токен. Панель керування пояснює це одним рядком: «Вперше ви увійдете до свого облікового запису VocalStack. Ключ не потрібен».
Це працює завдяки специфікації авторизації MCP, а не якомусь трюку VocalStack. Віддалений сервер відповідає на неавторизований запит кодом 401, що вказує на його метадані захищеного ресурсу: невеликий JSON-документ, який називає сервер авторизації та області доступу (scope), потрібні серверу. Клієнт читає його, виконує стандартний потік 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 MiB, приблизно десятьма хвилинами MP3 на 128 kbps; для більших файлів дайте агентові посилання.Обидва повертають результат одразу з transcriptionId, state: "queued" і підказкою next, що називає інструмент очікування. Транскрипції, створені агентом, спочатку приватні, без посилання для спільного доступу.
Агент не може витримати пряму трансляцію терплячіше, ніж ви; він би постійно викликав інструмент очікування, доки хтось не забрав би ноутбук. Завершений запис має кінець, і саме його чекає наступна пара інструментів.
Виклик інструмента — це один HTTP-запит, а HTTP-запити не призначені для того, щоб тривати годину. Клієнти відмовляються від них, проксі закривають їх, а модель, заблокована на одному інструменті, не може робити нічого іншого. Тому шаблон для будь-якої довгої задачі за MCP той самий, що й у REST API: запустити задачу й отримати дескриптор, чекати на нього обмежений час і викликати знову, якщо вона ще не готова. Стан несе дескриптор, а не з’єднання.
wait_for_transcription блокується, доки задача не стане done або failed, або доки не мине timeoutS (за замовчуванням 50 секунд, максимум 60, що тримає виклик у межах таймаутів більшості клієнтів і проксі). Якщо результат містить timedOut: true, задача ще виконується, і агент викликає інструмент знову. Поки інструмент чекає, сервер надсилає сповіщення про прогрес MCP, якщо клієнт їх запитав: відсоток і фазу, наприклад «отримано 3.1 / 8.0 MB» або «транскрибовано 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.