Um servidor MCP transforma uma API em algumas ferramentas com nome que um agente chama no meio da conversa, e um trabalho longo cabe nele quando a ferramenta devolve um identificador que o agente aguarda em turnos limitados. Cole o link de um podcast, peça o resumo em francês e nenhum código precisa ser escrito.
Um agente de programação pode usar a API do VocalStack da mesma forma que qualquer programa: ler a referência da API, escrever algumas linhas com o SDK e executá-las. Esse é o caminho certo para algo que vai rodar sem o agente.
MCP (Model Context Protocol) serve para o outro caso: você está conversando com um assistente e quer que ele transcreva algo agora, sem código. Um servidor MCP publica uma lista curta de ferramentas com nome, cada uma com uma descrição e um esquema JSON para seus argumentos. O agente lê a lista uma vez e chama uma ferramenta pelo nome quando um pedido corresponde a ela. "Transcreva este podcast e me diga o que falaram sobre preços" vira três chamadas de ferramenta, e o agente nunca vê uma rota HTTP.
Há dois tipos de servidor. Um servidor local roda como subprocesso do cliente e se comunica por stdio, que é como funcionam a maioria dos servidores de sistema de arquivos e de banco de dados. Um servidor remoto fica atrás de uma URL e fala Streamable HTTP, o transporte que substituiu o antigo HTTP com SSE (eventos enviados pelo servidor) na revisão da especificação de março de 2025. O cliente envia cada requisição, e o servidor responde na mesma conexão; tudo o que ele tiver a dizer antes do resultado final é transmitido antes dele. Qualquer cliente escrito conforme a especificação atual pode usar qualquer um dos dois tipos.
O servidor do VocalStack é do tipo remoto, em {{api}}/v1/mcp, e usá-lo custa o mesmo que a API. Tudo o que você precisa é da URL.
Abra a área Developers do Painel, em {{app}}/developers. A primeira aba, Connect an AI agent, mostra a URL do servidor e um trecho de configuração para cada cliente. Os três trechos abaixo correspondem aos exibidos ali.
Execute isto no seu terminal:
claude mcp add --transport http vocalstack {{api}}/v1/mcp
Adicione isto a .cursor/mcp.json no seu projeto, ou a ~/.cursor/mcp.json para todos os projetos:
{"mcpServers":{"vocalstack":{"url":"{{api}}/v1/mcp"}}}
Qualquer cliente que suporte Streamable HTTP pode adicionar o servidor com esta URL. Esta é a forma genérica exibida no Painel:
{
"vocalstack": {
"type": "streamable-http",
"url": "{{api}}/v1/mcp"
}
}
Você não precisa de uma chave de API para começar. Na primeira vez que o cliente se conectar, você entra com sua conta do VocalStack no navegador, e o cliente guarda o token. O Painel resume isso em uma linha: “Você vai entrar com sua conta do VocalStack na primeira vez. Não é preciso nenhuma chave.”
Isto é a especificação de autorização do MCP em ação, não um truque do VocalStack. Um servidor remoto responde a uma requisição não autenticada com um 401 que aponta para seus metadados de recurso protegido: um pequeno documento JSON que indica o servidor de autorização e os escopos exigidos pelo servidor. O cliente lê esse documento, executa um fluxo OAuth 2.1 padrão no seu navegador e volta com um token emitido apenas para aquele servidor. Qualquer servidor MCP remoto que siga a especificação permite entrar do mesmo jeito, por isso os clientes acima conseguem fazer isso sem saber nada sobre o VocalStack.
Uma chave de API também funciona, para um cliente que roda em um servidor ou em um script. Envie-a como Authorization: Bearer vs_key_..., o mesmo cabeçalho que a API REST aceita. As chaves são criadas em Developers → API keys. As duas ferramentas de transcrição precisam das permissões Write e Stream audio. A segunda parece estranha para um arquivo, mas as ferramentas passam pelo mesmo ponto de criação de qualquer transcrição, inclusive as ao vivo, e esse ponto verifica as duas. As ferramentas de leitura precisam de Read; list_voices precisa apenas de uma credencial válida.
Depois que você entra, o agente enxerga nove ferramentas. Você raramente vai citá-las pelo nome, mas conhecê-las ajuda a entender o que o agente faz em seguida.
Toda ferramenta recebe e devolve JSON em camelCase, com os mesmos nomes de campo dos tipos da API /v1; o identificador de uma transcrição é seu transcriptionId.
transcribe_url inicia a transcrição de áudio ou vídeo em uma URL pública: um link de arquivo, um episódio de podcast, um vídeo do YouTube. Transmissões ao vivo não são aceitas. Argumentos opcionais: name, spokenLanguage (omita para detectar o idioma), speakerLabels (auto, on ou off) e startS/endS para transcrever apenas parte do áudio.transcribe_file faz o mesmo para um arquivo que o agente tem, enviado como fileBase64 com seu filename. O tamanho decodificado é limitado a 10 MiB, aproximadamente dez minutos de MP3 a 128 kbps; para algo maior, dê ao agente um link.Ambas retornam imediatamente com o transcriptionId, state: "queued" e uma dica next indicando a ferramenta de espera. As transcrições criadas pelo agente começam privadas, sem link de compartilhamento.
Um agente não consegue esperar uma transmissão ao vivo com mais paciência do que você; ele ficaria chamando a ferramenta de espera até alguém tirar o notebook de perto dele. Uma gravação finalizada tem um fim, e é isso que o próximo par de ferramentas espera.
Uma chamada de ferramenta é uma requisição HTTP, e requisições HTTP não foram feitas para durar uma hora. Os clientes desistem delas, os proxies as fecham, e um modelo bloqueado em uma ferramenta não consegue fazer mais nada. Por isso, o padrão para qualquer trabalho longo atrás do MCP é o mesmo que a API REST usa: iniciar o trabalho e obter um identificador, aguardar por um tempo limitado e chamar de novo se ele ainda não tiver terminado. O estado fica no identificador, não na conexão.
wait_for_transcription bloqueia até o trabalho ficar done ou failed, ou até que timeoutS passe (padrão de 50 segundos, máximo de 60, o que mantém a chamada abaixo dos tempos limite da maioria dos clientes e proxies). Se o resultado disser timedOut: true, o trabalho ainda está em execução e o agente chama a ferramenta de novo. Enquanto a ferramenta espera, o servidor envia notificações de progresso do MCP, se o cliente as tiver solicitado: uma porcentagem e uma fase, como "baixando 3,1 / 8,0 MB" ou "transcrevendo 01:25 de 02:00".get_transcription retorna o status e, quando concluído, o texto. format: "text" dá uma linha por segmento no formato [mm:ss] Speaker 1: ...; "segments" dá linhas com tempo, com start, end, speaker e speakerName; includeWords: true acrescenta os tempos das palavras. Os resultados são paginados (offset, limit, padrão de 500 segmentos), com um nextOffset quando ainda restam mais.A paginação existe para o modelo, não para a rede. Tudo o que uma ferramenta devolve é colado na janela de contexto do agente, onde disputa espaço com a sua conversa e custa tokens em cada turno seguinte. Uma reunião de duas horas são dezenas de milhares de palavras; devolver tudo de uma vez empurraria para fora do contexto a pergunta que você fez. Boas ferramentas MCP devolvem uma página e um cursor, e deixam o agente decidir quanto ele precisa.
Uma desconexão ou um tempo esgotado nunca cancela o trabalho, porque o trabalho vive no servidor, não na requisição MCP. Quando termina, ele vira mais uma entrada na sua biblioteca, e as ferramentas seguintes o tratam como qualquer outro.
list_transcriptions lista as transcrições da conta, das mais recentes para as mais antigas, com estado e duração; lifecycle pode ser active, archived ou all.search_transcriptions pesquisa o que foi dito em todas as transcrições, em qualquer idioma, e devolve as linhas correspondentes, cada uma com sua transcrição e o segundo em que foi falada. transcriptionId restringe a pesquisa a uma transcrição; lang acrescenta uma tradução de cada resultado.Encontrar uma linha é a parte barata. Duas outras ferramentas descobrem o que tudo disse.
get_summary retorna o título e o resumo gerados por IA de uma transcrição concluída, opcionalmente traduzidos com lang. state: "pending" significa que o resumo ainda está sendo escrito (costuma ficar pronto em poucos segundos após o término do trabalho), e o agente pergunta de novo.translate_transcription devolve uma transcrição concluída em outro idioma, como texto ou segmentos com tempo, paginada como get_transcription. As traduções são armazenadas, então pedir de novo não repete o trabalho.list_voices lista as vozes que podem ler uma transcrição em um idioma: id, nome, gênero e sotaque quando conhecidos, uma avaliação de qualidade e se é a voz padrão ou uma das suas vozes clonadas. Ela descreve vozes; não faz uma voz falar (mais sobre o que o servidor não faz adiante).Veja a seguir como as ferramentas se encadeiam na prática.
Com o servidor adicionado, uma conversa no Claude Code acontece assim. Você cola o link de um podcast e pede o resumo em francês.
O agente chama transcribe_url:
{ "url": "https://example.org/episodes/42.mp3", "name": "Episode 42", "speakerLabels": "auto" }
Ele recebe um transcriptionId e state: "queued", e segue a dica next:
{ "transcriptionId": "4f1c...", "timeoutS": 50 }
Um episódio de cinquenta minutos é transcrito muitas vezes mais rápido do que toca, mas não dentro de uma única espera. A primeira espera retorna timedOut: true com progresso de, digamos, 61 por cento, então o agente chama a ferramenta mais uma vez e recebe state: "done".
Agora o agente chama get_summary com lang: "fr":
{ "transcriptionId": "4f1c...", "lang": "fr" }
Se o resumo ainda estiver pending, o agente espera alguns segundos; caso contrário, entrega a você um título e um resumo em francês. Se você perguntar "onde falaram sobre preços?", ele chama search_transcriptions com query: "pricing" e o mesmo transcriptionId, e cita as linhas correspondentes com seus horários. Se pedir o texto inteiro em francês, ele chama translate_transcription.
Algumas chamadas de ferramenta, nenhum código e uma transcrição na sua biblioteca. Cada uma dessas chamadas passou pelas mesmas barreiras de uma requisição REST, e são essas barreiras que definem a cobrança e os limites.
O servidor MCP é a API por outra porta de entrada: mesmos limites, mesma cobrança.
POST /v1/transcriptions: valem a taxa de criação do plano (10, 100 ou um número personalizado de transcrições iniciadas por hora), o limite de transcrições simultâneas (1, 5 ou ilimitado) e o seu crédito. O crédito de cadastro de $5 cobre uma primeira sessão, sem precisar de cartão.isError: true com o código de erro da API REST, uma frase que o modelo pode usar e os campos retryable e retryAfterS. insufficient_credit traz um topUpUrl; rate_limited informa quanto tempo esperar. Isso importa mais do que parece: um modelo lê o texto do erro, então uma frase que ele pode usar transforma um beco sem saída na próxima chamada de ferramenta./v1/mcp: um agente em loop recebe um HTTP 429 com Retry-After antes de qualquer ferramenta ser executada.idempotencyKey: reutilizar a chave de uma chamada concluída reproduz o primeiro resultado, e reutilizá-la com argumentos diferentes é recusado, então um agente que tenta de novo por conta própria nunca inicia um segundo trabalho. Qualquer ferramenta que gaste dinheiro deve oferecer isso; agentes repetem tentativas com muito mais liberdade do que as pessoas.Esses são os limites do que o servidor faz. Duas coisas ficam de fora deles de propósito.
O servidor não tem nenhuma ferramenta que transforme texto arbitrário em fala, e nenhuma está prevista. O VocalStack fala transcrições e suas traduções, com uma voz padrão ou clonada, e mais nada. list_voices informa a um agente quais vozes podem ler uma transcrição em um idioma, não como fazer uma voz dizer algo novo.
As ferramentas de transcrição também recusam transmissões ao vivo. Uma transmissão ao vivo do YouTube ou uma rádio online precisa de uma transcrição ao vivo, iniciada pelo Painel ou por meio de POST /v1/transcriptions/live na referência da API. Um vídeo finalizado do YouTube é um arquivo, e transcribe_url o aceita.
Se preferir escrever o código você mesmo, transcrever um arquivo com a API mostra os mesmos passos como chamadas HTTP, e o tutorial de tempo real cobre o WebSocket.