MCP сервер претвара API у неколико именованих алата које агент позива усред разговора, а дуг посао може да стане иза једног кад алат врати ручку на коју агент чека у ограниченим корацима. Залепите линк ка подкасту, затражите суштину на француском, и не мора да се напише ниједан код.
Агент за кодирање може да користи VocalStack API онако како то ради било који програм: прочита 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.
Отворите област за програмере на контролној табли, на {{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 документ који наводи сервер за ауторизацију и опсеге које сервер захтева. Клијент га прочита, покрене стандардни 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 враћа AI наслов и резиме завршене транскрипције, по жељи преведене помоћу 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, па citира одговарајуће линије са временским ознакама. Ако тражите цео текст на француском, позива 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.