Serwer MCP zamienia API w kilka nazwanych narzędzi, które agent wywołuje w trakcie rozmowy. Długie zadanie mieści się w takim serwerze, gdy narzędzie zwraca uchwyt, na który agent czeka w ograniczonych turach. Wklej link do podcastu, poproś o najważniejsze wątki po francusku, a kodu nie trzeba pisać.
Agent programistyczny może korzystać z API VocalStack tak jak każdy program: przeczytać dokumentację API, napisać kilka linii z użyciem SDK i je uruchomić. To właściwa droga dla czegoś, co będzie działać bez agenta.
MCP (Model Context Protocol) służy do drugiego przypadku: rozmawiasz z asystentem i chcesz, żeby od razu coś przetranskrybował, bez kodu. Serwer MCP udostępnia krótką listę nazwanych narzędzi, każde z opisem i schematem JSON dla argumentów. Agent czyta listę raz i wywołuje narzędzie po nazwie, gdy prośba do niego pasuje. „Przetranskrybuj ten podcast i powiedz mi, co mówili o cenach” staje się trzema wywołaniami narzędzi, a agent nigdy nie widzi trasy HTTP.
Serwery występują w dwóch rodzajach. Serwer lokalny działa jako podproces klienta i komunikuje się przez stdio; tak działa większość serwerów plików i baz danych. Serwer zdalny znajduje się za adresem URL i mówi przez Streamable HTTP, transport, który w wydaniu specyfikacji z marca 2025 zastąpił starszy transport HTTP-plus-SSE (server-sent events). Klient wysyła każde żądanie, a serwer odpowiada na tym samym połączeniu; wszystko, co chce powiedzieć przed ostatecznym wynikiem, jest strumieniowane wcześniej. Dowolny klient napisany zgodnie z obecną specyfikacją może korzystać z obu rodzajów.
Serwer VocalStack jest zdalny i działa pod adresem {{api}}/v1/mcp. Korzystanie z niego kosztuje tyle, co API. Potrzebujesz tylko adresu URL.
Otwórz obszar Developers w panelu, pod adresem {{app}}/developers. Pierwsza zakładka, Connect an AI agent, pokazuje adres serwera i fragment konfiguracji dla każdego klienta. Trzy fragmenty poniżej są zgodne z tymi, które tam widzisz.
Uruchom to w terminalu:
claude mcp add --transport http vocalstack {{api}}/v1/mcp
Dodaj to do pliku .cursor/mcp.json w swoim projekcie albo do ~/.cursor/mcp.json, by działało we wszystkich projektach:
{"mcpServers":{"vocalstack":{"url":"{{api}}/v1/mcp"}}}
Każdy klient obsługujący Streamable HTTP może dodać serwer pod tym adresem URL. To ogólna postać, którą pokazuje panel:
{
"vocalstack": {
"type": "streamable-http",
"url": "{{api}}/v1/mcp"
}
}
Do startu nie potrzebujesz klucza API. Przy pierwszym połączeniu klienta logujesz się na swoje konto VocalStack w przeglądarce, a klient zachowuje token. Panel mówi to w jednym zdaniu: „Za pierwszym razem zalogujesz się na swoje konto VocalStack. Klucz nie jest potrzebny.”
To działanie specyfikacji autoryzacji MCP, a nie sztuczka VocalStack. Zdalny serwer odpowiada na nieuwierzytelnione żądanie kodem 401, który wskazuje na metadane zasobu chronionego: mały dokument JSON, podający serwer autoryzacji i zakresy wymagane przez serwer. Klient go odczytuje, przeprowadza w przeglądarce standardowy przepływ OAuth 2.1 i wraca z tokenem wydanym wyłącznie dla tego serwera. Każdy zdalny serwer MCP zgodny ze specyfikacją loguje w ten sam sposób, dlatego wymienieni wyżej klienci potrafią to zrobić, nic nie wiedząc o VocalStack.
Działa też klucz API, dla klienta uruchomionego na serwerze lub w skrypcie. Wysyłaj go jako Authorization: Bearer vs_key_..., czyli w tym samym nagłówku, którego przyjmuje REST API. Klucze tworzy się w Developers → API keys. Dwa narzędzia transkrypcji wymagają uprawnień Write i Stream audio. Drugie brzmi dziwnie dla pliku, ale narzędzia przechodzą przez ten sam punkt tworzenia co każda transkrypcja, także na żywo, a ten punkt sprawdza oba. Narzędzia odczytu potrzebują Read; list_voices wymaga tylko ważnego poświadczenia.
Gdy jesteś zalogowany, agent widzi dziewięć narzędzi. Rzadko będziesz je wymieniać samodzielnie, ale ich znajomość wyjaśnia, co agent zrobi dalej.
Każde narzędzie przyjmuje i zwraca JSON w camelCase, z tymi samymi nazwami pól co typy wire /v1; uchwytem transkrypcji jest jej transcriptionId.
transcribe_url uruchamia transkrypcję audio lub wideo pod publicznym adresem URL: linku do pliku, odcinka podcastu, filmu z YouTube. Transmisji na żywo nie przyjmuje. Opcjonalne argumenty: name, spokenLanguage (pomiń, by wykryć język), speakerLabels (auto, on lub off) oraz startS/endS, by przetranskrybować tylko fragment nagrania.transcribe_file robi to samo dla pliku, który ma agent, przesłanego jako fileBase64 z jego filename. Zdekodowany rozmiar jest ograniczony do 10 MiB, czyli mniej więcej dziesięciu minut MP3 o przepływności 128 kb/s; w przypadku większych plików podaj agentowi link.Oba natychmiast zwracają transcriptionId, state: "queued" i podpowiedź next wskazującą narzędzie czekania. Transkrypcje utworzone przez agenta zaczynają się jako prywatne, bez linku do udostępnienia.
Agent nie wytrzyma transmisji na żywo cierpliwiej niż ty; wywoływałby narzędzie czekania, dopóki ktoś nie zabrałby mu laptopa. Zakończone nagranie ma koniec i na niego czeka następna para narzędzi.
Wywołanie narzędzia to jedno żądanie HTTP, a żądania HTTP nie są stworzone do trwania godzinę. Klienci się poddają, proxy je zamykają, a model zablokowany na jednym narzędziu nie może zrobić nic innego. Dlatego wzorzec dla każdego długiego zadania za MCP jest ten sam, którego używa REST API: uruchom zadanie i dostań uchwyt, czekaj na nie przez ograniczony czas, a jeśli nie jest gotowe, wywołaj ponownie. Stan przenosi uchwyt, a nie połączenie.
wait_for_transcription blokuje, aż zadanie będzie done lub failed, albo aż minie timeoutS (domyślnie 50 sekund, maksymalnie 60, dzięki czemu wywołanie mieści się w limitach czasu, jakie stosuje większość klientów i proxy). Jeśli wynik mówi timedOut: true, zadanie wciąż trwa i agent wywołuje narzędzie ponownie. Podczas czekania serwer wysyła powiadomienia postępu MCP, jeśli klient o nie poprosił: procent i fazę, na przykład "fetching 3.1 / 8.0 MB" lub "transcribing 01:25 of 02:00".get_transcription zwraca status, a po zakończeniu także tekst. format: "text" daje jedną linię na segment w postaci [mm:ss] Speaker 1: ...; "segments" daje linie z czasem, z polami start, end, speaker i speakerName; includeWords: true dodaje czasy słów. Wyniki są stronicowane (offset, limit, domyślnie 500 segmentów), a gdy zostaje więcej, pojawia się nextOffset.Stronicowanie służy modelowi, a nie sieci. Wszystko, co zwraca narzędzie, trafia do okna kontekstu agenta, gdzie konkuruje z rozmową i kosztuje tokeny przy każdej kolejnej turze. Dwugodzinne spotkanie to dziesiątki tysięcy słów; zwrócenie wszystkiego naraz wypchnęłoby pytanie, które zadałeś, poza kontekst. Dobre narzędzia MCP zwracają stronę i kursor i pozwalają agentowi zdecydować, ile potrzebuje.
Rozłączenie albo przekroczenie czasu nigdy nie anuluje zadania, bo zadanie żyje na serwerze, a nie w żądaniu MCP. Po zakończeniu zadanie to kolejny wpis w twojej bibliotece, a następne narzędzia traktują go jak każdy inny.
list_transcriptions wypisuje transkrypcje konta, od najnowszych, ze statusem i czasem trwania; lifecycle to active, archived lub all.search_transcriptions przeszukuje to, co powiedziano we wszystkich transkrypcjach, w dowolnym języku, i zwraca pasujące linie, każdą z jej transkrypcją i sekundą, w której padły. transcriptionId zawęża wyszukiwanie do jednej transkrypcji; lang dodaje tłumaczenie każdego trafienia.Znalezienie linii to łatwiejsza połowa. Dwa kolejne narzędzia ustalają, co powiedziano w całości.
get_summary zwraca tytuł i podsumowanie AI zakończonej transkrypcji, opcjonalnie przetłumaczone przez lang. state: "pending" oznacza, że podsumowanie wciąż powstaje (zwykle jest gotowe w ciągu kilku sekund od zakończenia zadania), i agent pyta ponownie.translate_transcription zwraca gotową transkrypcję w innym języku, jako tekst albo segmenty z czasem, stronicowane jak get_transcription. Tłumaczenia są zapisywane, więc ponowne pytanie nie powtarza pracy.list_voices wypisuje głosy, które mogą odczytać transkrypcję w danym języku: id, nazwę, płeć i akcent, gdy są znane, ocenę jakości oraz to, czy to głos domyślny, czy jeden z twoich sklonowanych głosów. Opisuje głosy; nie sprawia, że któryś mówi (więcej poniżej, o tym, czego serwer nie robi).Oto, jak narzędzia łączą się w praktyce.
Gdy serwer jest dodany, rozmowa w Claude Code wygląda tak. Wklejasz link do podcastu i prosisz o najważniejsze wątki po francusku.
Agent wywołuje transcribe_url:
{ "url": "https://example.org/episodes/42.mp3", "name": "Episode 42", "speakerLabels": "auto" }
Dostaje transcriptionId i state: "queued" i podąża za podpowiedzią next:
{ "transcriptionId": "4f1c...", "timeoutS": 50 }
Pięćdziesięciominutowy odcinek transkrybuje się wielokrotnie szybciej, niż trwa jego odtwarzanie, ale nie w ramach jednego czekania. Pierwsze czekanie zwraca timedOut: true z postępem na przykład 61 procent, więc agent wywołuje narzędzie jeszcze raz i dostaje state: "done".
Teraz agent wywołuje get_summary z lang: "fr":
{ "transcriptionId": "4f1c...", "lang": "fr" }
Jeśli podsumowanie wciąż jest pending, agent czeka kilka sekund; w przeciwnym razie podaje ci tytuł i podsumowanie po francusku. Zapytaj: „gdzie mówili o cenach?”, a agent wywoła search_transcriptions z query: "pricing" i tym samym transcriptionId i zacytuje pasujące linie z ich znacznikami czasu. Poproś o całość po francusku, a wywoła translate_transcription.
Kilka wywołań narzędzi, bez kodu, i transkrypcja w twojej bibliotece. Każde z tych wywołań przeszło przez te same bramki co żądanie REST, a to te bramki wyznaczają rachunek i limity.
Serwer MCP to API przez inne wejście: te same limity, ten sam rachunek.
POST /v1/transcriptions: obowiązują limit tworzenia planu (10, 100 lub własna liczba transkrypcji uruchamianych na godzinę), limit równoczesnych transkrypcji (1, 5 lub bez limitu) i środki na koncie. Bonus powitalny $5 wystarcza na pierwszą sesję, bez karty.isError: true z kodem błędu REST API, zdaniem, na którym model może działać, i polami retryable oraz retryAfterS. insufficient_credit niesie topUpUrl; rate_limited mówi, jak długo czekać. To ważniejsze, niż brzmi: model czyta tekst błędu, więc zdanie, na którym może działać, zamienia ślepy zaułek w następne wywołanie narzędzia./v1/mcp: zapętlony agent dostaje HTTP 429 z Retry-After, zanim uruchomi się jakiekolwiek narzędzie.idempotencyKey: ponowne użycie klucza zakończonego wywołania odtwarza pierwszy wynik, a ponowne użycie go z innymi argumentami jest odrzucane, więc agent, który ponawia sam z siebie, nigdy nie uruchamia drugiego zadania. Każde narzędzie, które wydaje pieniądze, powinno to oferować; agenci ponawiają znacznie swobodniej niż ludzie.To granice tego, co robi serwer. Dwie rzeczy celowo leżą poza nimi.
Serwer nie ma narzędzia, które zamienia dowolny tekst na mowę, i takiego nie planujemy. VocalStack mówi transkrypcjami i ich tłumaczeniami, głosem standardowym lub sklonowanym, i niczym więcej. list_voices mówi agentowi, które głosy mogą odczytać transkrypcję w danym języku, a nie jak sprawić, by głos powiedział coś nowego.
Narzędzia transkrypcji odrzucają też transmisje na żywo. Transmisja na żywo z YouTube albo stream radiowy wymaga transkrypcji na żywo, uruchomionej z panelu lub przez POST /v1/transcriptions/live w dokumentacji API. Zakończony film z YouTube to plik, a transcribe_url go przyjmuje.
Jeśli wolisz napisać kod samodzielnie, transkrypcja pliku przez API przechodzi przez te same kroki co wywołania HTTP, a samouczek o czasie rzeczywistym omawia WebSocket.