Un servidor MCP converteix una API en unes quantes eines amb nom que un agent crida enmig d'una conversa, i una feina llarga hi cap quan l'eina retorna un identificador que l'agent espera en torns acotats. Enganxa l'enllaç d'un podcast, demana el resum en francès, i no cal escriure cap codi.
Un agent de programació pot usar l'API de VocalStack com ho fa qualsevol programa: llegir la referència de l'API, escriure unes quantes línies amb el SDK i executar-les. Aquest és el camí adequat per a alguna cosa que s'executarà sense l'agent.
MCP (el Model Context Protocol) és per a l'altre cas: parles amb un assistent i vols que transcrigui alguna cosa ara mateix, sense codi. Un servidor MCP publica una llista curta d'eines amb nom, cadascuna amb una descripció i un esquema JSON per als seus arguments. L'agent llegeix la llista una vegada i crida una eina pel nom quan una petició hi encaixa. «Transcriu aquest podcast i explica'm què van dir sobre els preus» es converteix en tres crides a eines, i l'agent mai no veu una ruta HTTP.
Els servidors són de dos tipus. Un servidor local s'executa com a subprocés del client i es comunica per stdio, que és com funcionen la majoria de servidors de sistema de fitxers i de bases de dades. Un servidor remot està darrere d'un URL i parla Streamable HTTP, el transport que va substituir l'antic HTTP-plus-SSE (esdeveniments enviats pel servidor) a la revisió de l'especificació de març de 2025. El client envia cada petició, i el servidor respon per la mateixa connexió; tot el que hagi de dir abans del resultat final s'envia en streaming just abans. Qualsevol client escrit segons l'especificació actual pot usar qualsevol dels dos tipus.
El servidor de VocalStack és del tipus remot, a {{api}}/v1/mcp, i usar-lo costa el mateix que costa l'API. Només necessites l'URL.
Obre l'àrea Developers del tauler a {{app}}/developers. La primera pestanya, Connect an AI agent, mostra l'URL del servidor i un fragment de configuració per a cada client. Els tres fragments de sota coincideixen amb els que hi apareixen.
Executa això al terminal:
claude mcp add --transport http vocalstack {{api}}/v1/mcp
Afegeix això a .cursor/mcp.json al teu projecte, o a ~/.cursor/mcp.json per a tots els projectes:
{"mcpServers":{"vocalstack":{"url":"{{api}}/v1/mcp"}}}
Qualsevol client que admeti Streamable HTTP pot afegir el servidor amb aquest URL. Aquesta és la forma genèrica que mostra el tauler:
{
"vocalstack": {
"type": "streamable-http",
"url": "{{api}}/v1/mcp"
}
}
No cal una clau d'API per començar. La primera vegada que el client es connecta, inicies la sessió al teu compte de VocalStack al navegador, i el client guarda el token. El tauler ho diu en una línia: «La primera vegada iniciaràs la sessió amb el teu compte de VocalStack. No cal cap clau.»
Això és l'especificació d'autorització de MCP en acció, no un truc de VocalStack. Un servidor remot respon a una petició sense autenticar amb un 401 que apunta a les seves metadades de recurs protegit: un document JSON petit que indica el servidor d'autorització i els àmbits que el servidor exigeix. El client les llegeix, executa un flux OAuth 2.1 estàndard al navegador i torna amb un token emès només per a aquest servidor. Qualsevol servidor MCP remot que segueixi l'especificació et fa iniciar la sessió de la mateixa manera, per això els clients de dalt ho poden fer sense saber res de VocalStack.
També funciona una clau d'API, per a un client que s'executa en un servidor o en un script. Envia-la com a Authorization: Bearer vs_key_..., la mateixa capçalera que accepta l'API REST. Les claus es creen a Developers → API keys. Les dues eines de transcripció necessiten els permisos Write i Stream audio. El segon sona estrany per a un fitxer, però les eines passen pel mateix punt de creació que totes les transcripcions, també les de directe, i aquest punt comprova els dos. Les eines de lectura necessiten Read; list_voices només necessita una credencial vàlida.
Un cop has iniciat la sessió, l'agent veu nou eines. Rarament les hauràs de nomenar tu, però conèixer-les explica què farà l'agent després.
Totes les eines reben i retornen JSON en camelCase, amb els mateixos noms de camp que els tipus de l'API /v1; l'identificador d'una transcripció és el seu transcriptionId.
transcribe_url inicia la transcripció d'àudio o vídeo en un URL públic: un enllaç a un fitxer, un episodi de podcast, un vídeo de YouTube. No s'accepten emissions en directe. Arguments opcionals: name, spokenLanguage (omet-lo per detectar l'idioma), speakerLabels (auto, on o off) i startS/endS per transcriure només una part de l'àudio.transcribe_file fa el mateix amb un fitxer que té l'agent, enviat com a fileBase64 amb el seu filename. La mida decodificada està limitada a 10 MiB, uns deu minuts d'MP3 a 128 kbps; per a quelcom més gran, dona a l'agent un enllaç.Totes dues retornen de seguida el transcriptionId, state: "queued" i una indicació next que anomena l'eina d'espera. Les transcripcions creades per l'agent comencen privades, sense enllaç per compartir.
Un agent no pot esperar una emissió en directe més pacientment del que ho pots fer tu; seguiria cridant l'eina d'espera fins que algú li tragués l'ordinador. Una gravació acabada té un final, i això és el que esperen les dues eines següents.
Una crida a una eina és una petició HTTP, i les peticions HTTP no estan pensades per durar una hora. Els clients les abandonen, els proxies les tanquen, i un model bloquejat en una eina no pot fer res més. Així que el patró per a qualsevol feina llarga darrere de MCP és el mateix que usa també l'API REST: inicia la feina i obtén un identificador, espera-la durant un temps acotat, i torna a cridar si no ha acabat. L'estat el porta l'identificador, no la connexió.
wait_for_transcription es bloqueja fins que la feina és done o failed, o fins que passa timeoutS (per defecte 50 segons, màxim 60, que manté la crida per sota dels temps límit que apliquen la majoria de clients i proxies). Si el resultat diu timedOut: true, la feina encara s'executa i l'agent torna a cridar l'eina. Mentre l'eina espera, el servidor envia notificacions de progrés de MCP si el client les ha demanat: un percentatge i una fase, com «descarregant 3.1 / 8.0 MB» o «transcrivint 01:25 de 02:00».get_transcription retorna l'estat i, un cop acabat, el text. format: "text" dona una línia per segment com [mm:ss] Speaker 1: ...; "segments" dona línies amb marca de temps amb start, end, speaker i speakerName; includeWords: true afegeix la temporització de les paraules. Els resultats es paginen (offset, limit, 500 segments per defecte) amb un nextOffset quan encara n'hi ha més.La paginació hi és per al model, no per a la xarxa. Tot el que retorna una eina s'enganxa a la finestra de context de l'agent, on competeix amb la conversa i costa tokens a cada torn posterior. Una reunió de dues hores són desenes de milers de paraules; retornar-les totes d'una vegada faria sortir la pregunta que vas fer del context. Les bones eines de MCP retornen una pàgina i un cursor, i deixen que l'agent decideixi quant en necessita.
Una desconnexió o un temps límit mai no cancel·la la feina, perquè la feina viu al servidor, no a la petició MCP. Quan acaba, la feina és una entrada més a la teva biblioteca, i les eines següents la tracten com qualsevol altra.
list_transcriptions llista les transcripcions del compte, de més noves a més antigues, amb estat i durada; lifecycle és active, archived o all.search_transcriptions cerca el que s'ha dit a totes les transcripcions, en qualsevol idioma, i retorna les línies coincidents, cadascuna amb la seva transcripció i el segon en què es va dir. transcriptionId limita la cerca a una sola transcripció; lang afegeix una traducció de cada resultat.Trobar una línia és la part fàcil. Dues eines més calculen què va dir tot el conjunt.
get_summary retorna el títol i el resum generats per IA d'una transcripció acabada, opcionalment traduïts amb lang. state: "pending" vol dir que el resum encara s'està escrivint (normalment està llest en pocs segons després que acabi la feina), i l'agent torna a preguntar.translate_transcription retorna una transcripció acabada en un altre idioma, com a text o com a segments amb temps, paginada com get_transcription. Les traduccions s'emmagatzemen, així que tornar a demanar-les no repeteix la feina.list_voices llista les veus que poden llegir una transcripció en un idioma: id, nom, gènere i accent quan es coneixen, una valoració de qualitat, i si és la predeterminada o una de les teves veus clonades. Descriu les veus; no fa que una d'elles digui res (més avall, què no fa el servidor).Així és com s'encadenen les eines a la pràctica.
Un cop afegit el servidor, una conversa a Claude Code va així. Enganxes l'enllaç d'un podcast i demanes el resum en francès.
L'agent crida transcribe_url:
{ "url": "https://example.org/episodes/42.mp3", "name": "Episode 42", "speakerLabels": "auto" }
Rep un transcriptionId i state: "queued", i segueix la indicació next:
{ "transcriptionId": "4f1c...", "timeoutS": 50 }
Un episodi de cinquanta minuts es transcriu moltes vegades més ràpid del que dura, però no dins d'una sola espera. La primera espera retorna timedOut: true amb el progrés al, posem, 61 per cent, així que l'agent torna a cridar l'eina una vegada més i obté state: "done".
Ara l'agent crida get_summary amb lang: "fr":
{ "transcriptionId": "4f1c...", "lang": "fr" }
Si el resum encara està pending, l'agent espera uns segons; altrament et lliura un títol i un resum en francès. Si preguntes «on van parlar dels preus?», crida search_transcriptions amb query: "pricing" i el mateix transcriptionId, i cita les línies coincidents amb les seves marques de temps. Si demanes tot el text en francès, crida translate_transcription.
Unes quantes crides a eines, sense codi, i una transcripció a la biblioteca. Cadascuna d'aquelles crides ha passat pels mateixos controls que una petició REST, i són aquests controls els que fixen la factura i els límits.
El servidor MCP és l'API per una altra porta: mateixos límits, mateixa factura.
POST /v1/transcriptions: s'apliquen la taxa de creació del pla (10, 100 o un nombre personalitzat de transcripcions iniciades per hora), el límit de transcripcions simultànies (1, 5 o il·limitades) i el seu crèdit. El crèdit de registre de $5 cobreix una primera sessió, sense targeta.isError: true amb el codi d'error de l'API REST, una frase que el model pot utilitzar, i els camps retryable i retryAfterS. insufficient_credit porta un topUpUrl; rate_limited indica quant cal esperar. Això importa més del que sembla: un model llegeix el text de l'error, així que una frase que pot aplicar converteix un carreró sense sortida en la següent crida a una eina./v1/mcp: un agent en bucle rep un HTTP 429 amb Retry-After abans que s'executi cap eina.idempotencyKey: reutilitzar la clau d'una crida completada reprodueix el primer resultat, i reutilitzar-la amb arguments diferents es refusa, de manera que un agent que reintenta pel seu compte mai no inicia una segona feina. Qualsevol eina que gasti diners hauria d'oferir-ho; els agents reintenten molt més lliurement que les persones.Aquests són els límits del que fa el servidor. Dues coses queden fora a propòsit.
El servidor no té cap eina que converteixi text arbitrari en veu, i no n'hi ha cap prevista. VocalStack parla transcripcions i les seves traduccions, amb una veu predefinida o clonada, i res més. list_voices diu a un agent quines veus poden llegir una transcripció en un idioma, no com fer que una veu digui alguna cosa de nou.
Les eines de transcripció també rebutgen les emissions en directe. Una emissió en directe de YouTube o una emissió de ràdio necessita una transcripció en directe, iniciada des del tauler o amb POST /v1/transcriptions/live a la referència de l'API. Un vídeo de YouTube ja acabat és un fitxer, i transcribe_url l'accepta.
Si preferiu escriure el codi vosaltres mateixos, transcriure un fitxer amb l'API explica els mateixos passos com a crides HTTP, i el tutorial de temps real tracta el WebSocket.