MCP サーバーは API を、エージェントが会話の途中で呼び出せる名前付きツールの少数の集まりに変えます。ツールが処理のハンドルを返し、エージェントがそれを有限のターンで待つ仕組みにすれば、長い処理もその中に収まります。ポッドキャストのリンクを貼り、フランス語で要点を頼むだけです。コードは一行も書きません。
コーディングエージェントも、他のプログラムと同じように VocalStack API を使えます。API リファレンスを読み、SDK で数行のコードを書いて実行します。エージェントを介さずに動くものを作るなら、この方法が適しています。
MCP(Model Context Protocol)は、別の場面のためのものです。アシスタントと会話していて、コードを書かずに今すぐ何かを文字起こししてほしいとき。MCP サーバーは、短い名前付きツールの一覧を公開します。各ツールには説明と、引数の JSON スキーマが付いています。エージェントは一覧を一度読み込み、依頼が合致したときにツールを名前で呼び出します。「このポッドキャストを文字起こしして、価格について何を話していたか教えて」という依頼は、三回のツール呼び出しになります。その間、エージェントが HTTP のルートを目にすることはありません。
サーバーには二種類あります。ローカルサーバーはクライアントのサブプロセスとして動き、stdio で通信します。ほとんどのファイルシステムやデータベースのサーバーがこの方式です。リモートサーバーは URL の向こう側にあり、Streamable HTTP で通信します。これは、2025年3月版の仕様で以前の HTTP + SSE(Server-Sent Events)トランスポートに替わったものです。クライアントは各リクエストを送り、サーバーは同じ接続で応答します。最終結果より前に伝えることがあれば、その前にストリームで送られます。現行の仕様に沿って書かれたクライアントなら、どちらの種類も使えます。
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 アカウントにサインインします。その後はクライアントがトークンを保持します。ダッシュボードには一行でこう書かれています。"You'll sign in with your VocalStack account the first time. No key needed."
これは VocalStack 独自の仕掛けではなく、MCP の認可仕様によるものです。リモートサーバーは、認証のないリクエストに 401 で応答します。その応答は、保護されたリソースのメタデータを指しています。これは、認可サーバーとサーバーが要求するスコープを示す小さな JSON 文書です。クライアントはそれを読み、標準の OAuth 2.1 フローをブラウザで実行して、そのサーバーのためだけに発行されたトークンを受け取ります。仕様に従うリモートの MCP サーバーなら、どれも同じ方法でサインインできます。上のクライアントが VocalStack について何も知らなくても動くのは、そのためです。
サーバーやスクリプト上で動くクライアントには、API キーも使えます。REST API と同じヘッダーで、Authorization: Bearer vs_key_... と送ってください。キーは Developers → API keys で作成します。文字起こしの二つのツールには Write と Stream audio の権限が必要です。ファイルに対して後者は奇妙に聞こえるかもしれません。しかし、これらのツールは、ライブを含むすべての文字起こしと同じ作成の入口を通り、その入口で両方の権限が確認されます。読み取りツールには Read が必要です。list_voices は有効な認証情報があれば十分です。
サインインすると、エージェントには九つのツールが見えるようになります。自分で名前を挙げることはほとんどないでしょうが、名前を知っておくと、エージェントが次に何をするのかが分かります。
すべてのツールは、camelCase の JSON を受け取り、返します。フィールド名は /v1 のワイヤー型と同じです。文字起こしのハンドルは transcriptionId です。
transcribe_url は、公開 URL にある音声または動画の文字起こしを開始します。ファイルのリンク、ポッドキャストのエピソード、YouTube 動画などが対象です。ライブ配信は受け付けません。任意の引数は、name、spokenLanguage(省略すると言語を自動検出)、speakerLabels(auto、on、off)、そして音声の一部だけを文字起こしする startS / endS です。transcribe_file は、エージェントが保持しているファイルに対して同じことをします。filename とともに fileBase64 で送ります。デコード後のサイズは 10 MiB が上限です。おおむね 128 kbps の MP3 で十分間に当たります。それより大きいものは、リンクをエージェントに渡してください。どちらのツールも、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 は、ある言語の文字起こしを読み上げられる音声を一覧にします。ID、名前、性別、わかっていればアクセント、品質の評価、そして既定の音声かあなたのクローン音声かが含まれます。これは音声を説明するだけで、何かを話させるものではありません。詳しくは後述します。ツールが実際にどう連携するかは、次のとおりです。
サーバーを追加すると、Claude Code での会話は次のように進みます。ポッドキャストのリンクを貼り、要点をフランス語で尋ねます。
エージェントは transcribe_url を呼び出します。
{ "url": "https://example.org/episodes/42.mp3", "name": "Episode 42", "speakerLabels": "auto" }
transcriptionId と state: "queued" が返ってくるので、エージェントは next のヒントに従います。
{ "transcriptionId": "4f1c...", "timeoutS": 50 }
50 分のエピソードは、再生される速さの何倍もの速さで文字起こしされますが、一回の待機の中では終わりません。最初の待機は、進捗が例えば 61% のところで timedOut: true を返します。そこでエージェントはもう一度呼び出し、state: "done" を得ます。
次に、エージェントは lang: "fr" を付けて get_summary を呼び出します。
{ "transcriptionId": "4f1c...", "lang": "fr" }
要約がまだ pending なら、エージェントは数秒待ちます。そうでなければ、フランス語のタイトルと要約を渡してくれます。「価格についてはどこで話していた?」と尋ねると、query: "pricing" と同じ transcriptionId を指定して search_transcriptions を呼び出し、一致した行をタイムスタンプ付きで引用します。全体をフランス語で欲しいと頼めば、translate_transcription を呼び出します。
ツールの呼び出しは数回、コードは不要で、文字起こしがライブラリに一つ加わります。それぞれの呼び出しは REST リクエストと同じゲートを通ります。そして、料金と上限を決めているのはそのゲートです。
MCP サーバーは、API への別の入口にすぎません。上限も料金も同じです。
POST /v1/transcriptions と同じ作成の入口を通ります。そのため、プランの作成レート(1時間あたり 10、100、またはカスタムの数の文字起こし開始数)、同時実行の文字起こしの上限(1、5、または無制限)、そしてクレジットがすべて適用されます。サインアップ時の $5 のクレジットは、最初のセッションを賄えます。カードの登録は不要です。isError: true を返します。REST API のエラーコード、モデルが行動できる一文、そして retryable と retryAfterS のフィールドが付きます。insufficient_credit には topUpUrl が付きます。rate_limited は待つべき時間を示します。これは思ったより重要です。モデルはエラーの文章を読むので、行動できる一文があれば、行き止まりが次のツール呼び出しに変わります。/v1/mcp へのリクエスト自体にも適用されます。暴走しているエージェントは、どのツールも動く前に、Retry-After 付きの HTTP 429 を受け取ります。idempotencyKey を受け取ります。完了した呼び出しのキーを再利用すると、最初の結果が再生されます。異なる引数と一緒に再利用すると拒否されます。そのため、自動で再試行するエージェントが二つ目の処理を始めることはありません。お金を使うツールには、どれも用意すべきです。エージェントは人よりはるかに気軽に再試行するからです。以上がサーバーの境界です。意図的に境界の外に置いているものが二つあります。
サーバーには、任意のテキストを音声にするツールはありません。今後も予定はありません。VocalStack が話すのは、文字起こしとその翻訳だけです。標準の音声かクローン音声で話します。それ以外は話しません。list_voices が伝えるのは、ある言語の文字起こしを読み上げられる音声であって、音声に新しい文章を話させる方法ではありません。
文字起こしツールはライブ配信も拒否します。YouTube のライブ配信やラジオのストリームには、ダッシュボードから、または API リファレンスの POST /v1/transcriptions/live を通じて、ライブの文字起こしを開始する必要があります。終了した YouTube 動画はファイルなので、transcribe_url で扱えます。
自分でコードを書きたい場合は、API でファイルを文字起こしするで同じ手順を HTTP 呼び出しとして説明しています。リアルタイムのチュートリアルでは WebSocket を扱っています。