Un servidor MCP convierte una API en unas pocas herramientas con nombre que un agente invoca en mitad de una conversación, y un trabajo largo cabe detrás de una de ellas cuando la herramienta devuelve un identificador que el agente consulta en turnos acotados. Pega el enlace de un pódcast, pide el resumen en francés y no hay que escribir código.
Un agente de programación puede usar la API de VocalStack como lo haría cualquier programa: leer la referencia de la API, escribir unas líneas con el SDK y ejecutarlas. Esa es la vía adecuada para algo que se ejecutará sin el agente.
MCP (el Model Context Protocol) sirve para el otro caso: estás hablando con un asistente y quieres que transcriba algo ahora mismo, sin código. Un servidor MCP publica una lista corta de herramientas con nombre, cada una con una descripción y un esquema JSON para sus argumentos. El agente lee la lista una vez y llama a una herramienta por su nombre cuando una petición encaja con ella. «Transcribe este pódcast y dime qué dijeron sobre los precios» se convierte en tres llamadas a herramientas, y el agente nunca ve una ruta HTTP.
Hay dos tipos de servidores. Un servidor local se ejecuta como subproceso del cliente y se comunica por stdio, que es como funcionan la mayoría de los servidores de sistema de archivos y de bases de datos. Un servidor remoto está detrás de una URL y habla Streamable HTTP, el transporte que reemplazó al antiguo transporte HTTP-plus-SSE (eventos enviados por el servidor) en la revisión de marzo de 2025 de la especificación. El cliente envía cada petición y el servidor responde por la misma conexión; cualquier cosa que tenga que decir antes del resultado final se transmite antes que él. Cualquier cliente escrito según la especificación vigente puede usar cualquiera de los dos tipos.
El servidor de VocalStack es del tipo remoto, en {{api}}/v1/mcp, y usarlo cuesta lo mismo que la API. Lo único que necesitas es la URL.
Abre el área Developers del panel de VocalStack en {{app}}/developers. La primera pestaña, Connect an AI agent, muestra la URL del servidor y un fragmento de configuración para cada cliente. Los tres fragmentos de abajo coinciden con los que aparecen allí.
Ejecuta esto en tu terminal:
claude mcp add --transport http vocalstack {{api}}/v1/mcp
Añade esto a .cursor/mcp.json en tu proyecto, o a ~/.cursor/mcp.json para todos los proyectos:
{"mcpServers":{"vocalstack":{"url":"{{api}}/v1/mcp"}}}
Cualquier cliente que admita Streamable HTTP puede añadir el servidor con esta URL. Esta es la forma genérica que muestra el panel:
{
"vocalstack": {
"type": "streamable-http",
"url": "{{api}}/v1/mcp"
}
}
No necesitas una clave de API para empezar. La primera vez que el cliente se conecte, iniciarás sesión con tu cuenta de VocalStack en el navegador, y el cliente guarda el token. El panel lo resume en una línea: «You'll sign in with your VocalStack account the first time. No key needed.»
Esto es la especificación de autorización de MCP en acción, no un truco de VocalStack. Un servidor remoto responde a una petición sin autenticar con un 401 que apunta a sus metadatos de recurso protegido: un pequeño documento JSON que indica el servidor de autorización y los ámbitos que requiere el servidor. El cliente lee ese documento, ejecuta un flujo OAuth 2.1 estándar en tu navegador y vuelve con un token emitido solo para ese servidor. Cualquier servidor MCP remoto que siga la especificación te autentica de la misma manera, por eso los clientes de arriba pueden hacerlo sin saber nada de VocalStack.
También funciona una clave de API, para un cliente que se ejecuta en un servidor o en un script. Envíala como Authorization: Bearer vs_key_..., la misma cabecera que acepta la API REST. Las claves se crean en Developers → API keys. Las dos herramientas de transcripción necesitan los permisos Write y Stream audio. El segundo suena raro para un archivo, pero las herramientas pasan por el mismo punto de creación que cualquier transcripción, incluidas las en directo, y ese punto comprueba ambos. Las herramientas de lectura necesitan Read; list_voices solo necesita una credencial válida.
Una vez que hayas iniciado sesión, el agente ve nueve herramientas. Rara vez las nombrarás tú mismo, pero conocerlas explica lo que el agente hace después.
Cada herramienta recibe y devuelve JSON en camelCase, con los mismos nombres de campo que los tipos de /v1; el identificador de una transcripción es su transcriptionId.
transcribe_url inicia la transcripción de audio o vídeo en una URL pública: un enlace a un archivo, un episodio de pódcast, un vídeo de YouTube. No se aceptan transmisiones en directo. Argumentos opcionales: name, spokenLanguage (omítelo para detectar el idioma), speakerLabels (auto, on u off) y startS/endS para transcribir solo una parte del audio.transcribe_file hace lo mismo con un archivo que tiene el agente, enviado como fileBase64 con su filename. El tamaño decodificado está limitado a 10 MiB, unos diez minutos de MP3 a 128 kbps; para algo más grande, dale al agente un enlace.Ambas devuelven de inmediato el transcriptionId, state: "queued" y una pista next que nombra la herramienta de espera. Las transcripciones creadas por el agente empiezan privadas, sin enlace para compartir.
Un agente no puede aguantar una emisión en directo con más paciencia que tú; seguiría llamando a la herramienta de espera hasta que alguien le quitara el portátil. Una grabación terminada tiene un final, y eso es lo que espera el siguiente par de herramientas.
Una llamada a una herramienta es una petición HTTP, y las peticiones HTTP no están pensadas para durar una hora. Los clientes las abandonan, los proxies las cierran y un modelo bloqueado en una herramienta no puede hacer nada más. Por eso el patrón para cualquier trabajo largo detrás de MCP es el mismo que usa también la API REST: iniciar el trabajo y obtener un identificador, esperar por él un tiempo acotado y volver a llamar si aún no ha terminado. El estado lo lleva el identificador, no la conexión.
wait_for_transcription se bloquea hasta que el trabajo esté done o failed, o hasta que pase timeoutS (por defecto 50 segundos, máximo 60, lo que mantiene la llamada por debajo de los tiempos de espera que aplican la mayoría de clientes y proxies). Si el resultado dice timedOut: true, el trabajo sigue en marcha y el agente vuelve a llamar a la herramienta. Mientras espera, el servidor envía notificaciones de progreso de MCP si el cliente las ha pedido: un porcentaje y una fase, como "fetching 3.1 / 8.0 MB" o "transcribing 01:25 of 02:00".get_transcription devuelve el estado y, una vez terminado, el texto. format: "text" da una línea por segmento con el formato [mm:ss] Speaker 1: ...; "segments" da líneas con tiempos, con start, end, speaker y speakerName; includeWords: true añade los tiempos de cada palabra. Los resultados se paginan (offset, limit, por defecto 500 segmentos) con un nextOffset cuando quedan más.La paginación está pensada para el modelo, no para la red. Todo lo que devuelve una herramienta se pega en la ventana de contexto del agente, donde compite con tu conversación y cuesta tokens en cada turno posterior. Una reunión de dos horas son decenas de miles de palabras; devolverlas todas de una vez empujaría fuera de contexto la pregunta que hiciste. Las buenas herramientas MCP devuelven una página y un cursor y dejan que el agente decida cuánto necesita.
Una desconexión o un tiempo de espera nunca cancela el trabajo, porque el trabajo vive en el servidor, no en la petición MCP. Cuando termina, es una entrada más de tu biblioteca, y las siguientes herramientas la tratan como a cualquier otra.
list_transcriptions lista las transcripciones de la cuenta, de la más reciente a la más antigua, con estado y duración; lifecycle puede ser active, archived o all.search_transcriptions busca lo dicho en todas las transcripciones, en cualquier idioma, y devuelve las líneas coincidentes, cada una con su transcripción y el segundo en que se dijo. transcriptionId limita la búsqueda a una sola transcripción; lang añade una traducción de cada resultado.Encontrar una línea es la mitad fácil. Otras dos herramientas averiguan qué dijo todo el conjunto.
get_summary devuelve el título y el resumen generados por IA de una transcripción terminada, opcionalmente traducidos con lang. state: "pending" significa que el resumen aún se está escribiendo (suele estar listo en pocos segundos tras terminar el trabajo), y el agente vuelve a preguntar.translate_transcription devuelve una transcripción terminada en otro idioma, como texto o como segmentos con tiempos, paginada igual que get_transcription. Las traducciones se guardan, así que volver a pedirla no repite el trabajo.list_voices lista las voces que pueden leer una transcripción en un idioma: id, nombre, género y acento cuando se conocen, una calificación de calidad, y si es la voz predeterminada o una de tus voces clonadas. Describe voces; no hace que una hable (más abajo, lo que el servidor no hace).Así encadenan las herramientas en la práctica.
Una vez añadido el servidor, una conversación en Claude Code sigue este curso. Pegas el enlace de un pódcast y pides el resumen en francés.
El agente llama a transcribe_url:
{ "url": "https://example.org/episodes/42.mp3", "name": "Episode 42", "speakerLabels": "auto" }
Recibe un transcriptionId y state: "queued", y sigue la pista next:
{ "transcriptionId": "4f1c...", "timeoutS": 50 }
Un episodio de cincuenta minutos se transcribe muchas veces más rápido de lo que dura, pero no en una sola espera. La primera espera devuelve timedOut: true con el progreso, digamos, al 61 por ciento, así que el agente vuelve a llamar a la herramienta una vez más y obtiene state: "done".
Ahora el agente llama a get_summary con lang: "fr":
{ "transcriptionId": "4f1c...", "lang": "fr" }
Si el resumen sigue en pending, el agente espera unos segundos; si no, te entrega un título y un resumen en francés. Si preguntas «¿dónde hablaron de los precios?», llama a search_transcriptions con query: "pricing" y el mismo transcriptionId, y cita las líneas coincidentes con sus marcas de tiempo. Si pides todo en francés, llama a translate_transcription.
Unas pocas llamadas a herramientas, sin código, y una transcripción en tu biblioteca. Cada una de esas llamadas pasó por las mismas puertas que una petición REST, y esas puertas son las que fijan la factura y los límites.
El servidor MCP es la API por otra puerta: mismos límites, misma factura.
POST /v1/transcriptions: se aplican la tasa de creación del plan (10, 100 o un número personalizado de transcripciones iniciadas por hora), su límite de transcripciones simultáneas (1, 5 o ilimitado) y su crédito. El crédito de $5 de registro cubre una primera sesión, sin tarjeta.isError: true con el código de error de la API REST, una frase que el modelo puede usar y los campos retryable y retryAfterS. insufficient_credit incluye un topUpUrl; rate_limited indica cuánto esperar. Esto importa más de lo que parece: un modelo lee el texto del error, así que una frase que pueda aprovechar convierte un callejón sin salida en la siguiente llamada a una herramienta./v1/mcp: un agente en bucle recibe un HTTP 429 con Retry-After antes de que se ejecute ninguna herramienta.idempotencyKey: reutilizar la clave de una llamada completada repite el primer resultado, y reutilizarla con argumentos distintos se rechaza, así que un agente que reintenta por su cuenta nunca inicia un segundo trabajo. Cualquier herramienta que gaste dinero debería ofrecer esto; los agentes reintentan mucho más libremente que las personas.Estos son los límites de lo que hace el servidor. Dos cosas quedan fuera de ellos a propósito.
El servidor no tiene ninguna herramienta que convierta texto arbitrario en voz, y no hay ninguna prevista. VocalStack habla transcripciones y sus traducciones, con una voz predefinida o clonada, y nada más. list_voices indica a un agente qué voces pueden leer una transcripción en un idioma, no cómo hacer que una voz diga algo nuevo.
Las herramientas de transcripción también rechazan las transmisiones en directo. Una transmisión en directo de YouTube o una emisora de radio necesita una transcripción en directo, iniciada desde el panel o mediante POST /v1/transcriptions/live en la referencia de la API. Un vídeo de YouTube ya terminado es un archivo, y transcribe_url lo acepta.
Si prefieres escribir el código tú mismo, transcribir un archivo con la API recorre los mismos pasos como llamadas HTTP, y el tutorial de tiempo real cubre el WebSocket.