एक MCP सर्वर किसी API को कुछ नामित टूल्स में बदल देता है, जिन्हें एजेंट बातचीत के बीच कॉल करता है। जब टूल एक हैंडल लौटाता है जिसका एजेंट सीमित बारी में इंतज़ार करता है, तो लंबा काम भी उसके पीछे फ़िट हो जाता है। कोई पॉडकास्ट लिंक चिपकाएँ, फ़्रेंच में सार माँगें, और कोई कोड नहीं लिखना पड़ता।
एक कोडिंग एजेंट VocalStack API का उपयोग वैसे ही कर सकता है जैसे कोई भी प्रोग्राम करता है: API संदर्भ पढ़ें, SDK के साथ कुछ पंक्तियाँ लिखें, और उन्हें चलाएँ। जो काम एजेंट के बिना चलेगा, उसके लिए यही सही रास्ता है।
MCP (Model Context Protocol) दूसरे मामले के लिए है: आप किसी असिस्टेंट से बात कर रहे हैं और चाहते हैं कि वह अभी, बिना कोड के, कुछ ट्रांसक्रिप्ट करे। MCP सर्वर नामित टूल्स की एक छोटी सूची प्रकाशित करता है, जिनमें से हर एक के साथ विवरण और उसके आर्गुमेंट्स के लिए एक JSON schema होता है। एजेंट सूची एक बार पढ़ता है, और अनुरोध मेल खाने पर टूल को उसके नाम से कॉल करता है। "इस पॉडकास्ट को ट्रांसक्रिप्ट करो और बताओ कि उन्होंने कीमतों के बारे में क्या कहा" तीन टूल कॉल बन जाता है, और एजेंट कभी HTTP रूट देखता ही नहीं।
सर्वर दो तरह के होते हैं। लोकल सर्वर क्लाइंट के सबप्रोसेस के रूप में चलता है और stdio पर बात करता है, जैसे ज़्यादातर फ़ाइल-सिस्टम और डेटाबेस सर्वर काम करते हैं। रिमोट सर्वर एक URL के पीछे रहता है और Streamable HTTP बोलता है, वह ट्रांसपोर्ट जिसने मार्च 2025 के स्पेक संशोधन में पुराने HTTP-plus-SSE (server-sent events) ट्रांसपोर्ट की जगह ली। क्लाइंट हर अनुरोध पोस्ट करता है, और सर्वर उसी कनेक्शन पर जवाब देता है; अंतिम परिणाम से पहले जो भी कहना हो, वह उसके आगे स्ट्रीम कर दिया जाता है। मौजूदा स्पेक के अनुसार लिखा कोई भी क्लाइंट दोनों में से किसी भी तरह के सर्वर का उपयोग कर सकता है।
VocalStack का सर्वर रिमोट वाला है, {{api}}/v1/mcp पर, और उसका उपयोग उतना ही खर्च होता है जितना API का। आपको बस URL चाहिए।
Dashboard के Developers एरिया को {{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 से सर्वर जोड़ सकता है। यह वह सामान्य रूप है जो Dashboard दिखाता है:
{
"vocalstack": {
"type": "streamable-http",
"url": "{{api}}/v1/mcp"
}
}
शुरू करने के लिए आपको API key की ज़रूरत नहीं है। क्लाइंट पहली बार कनेक्ट होने पर आप ब्राउज़र में अपने VocalStack अकाउंट से साइन इन करते हैं, और क्लाइंट टोकन अपने पास रख लेता है। Dashboard इसे एक लाइन में कहता है: "पहली बार आप अपने VocalStack अकाउंट से साइन इन करेंगे। कोई key नहीं चाहिए।"
यह VocalStack की कोई चाल नहीं, बल्कि MCP की authorization spec का काम है। रिमोट सर्वर बिना प्रमाणीकरण वाले अनुरोध का जवाब 401 से देता है, जो उसके protected-resource metadata की ओर इशारा करता है: एक छोटा JSON दस्तावेज़ जो authorization server और उन scopes के नाम बताता है जो सर्वर को चाहिए। क्लाइंट उसे पढ़ता है, आपके ब्राउज़र में एक मानक OAuth 2.1 फ़्लो चलाता है, और उस एक सर्वर के लिए जारी किया गया टोकन लेकर लौटता है। स्पेक का पालन करने वाला कोई भी रिमोट MCP सर्वर आपको इसी तरह साइन इन कराता है, इसीलिए ऊपर के क्लाइंट VocalStack के बारे में कुछ जाने बिना यह कर पाते हैं।
API key भी काम करती है, उस क्लाइंट के लिए जो किसी सर्वर या स्क्रिप्ट में चल रहा हो। उसे Authorization: Bearer vs_key_... के रूप में भेजें, वही हेडर जो REST API लेता है। Keys Developers → API keys के अंतर्गत बनाई जाती हैं। दोनों transcribe टूल्स को Write और Stream audio अनुमतियाँ चाहिए। दूसरी सुनने में अजीब लगती है, फ़ाइल के लिए, लेकिन ये टूल उसी creation point से गुज़रते हैं जहाँ से हर ट्रांसक्रिप्शन गुज़रता है, लाइव वाले भी, और वह point दोनों की जाँच करता है। पढ़ने वाले टूल्स को Read चाहिए; list_voices को बस एक वैध credential चाहिए।
एक बार साइन इन हो जाने पर एजेंट को नौ टूल दिखते हैं। आप उनके नाम शायद ही कभी खुद लेंगे, लेकिन उन्हें जानने से समझ आता है कि एजेंट आगे क्या करता है।
हर टूल camelCase JSON लेता और लौटाता है, उन्हीं फ़ील्ड नामों के साथ जो /v1 wire types में हैं; किसी ट्रांसक्रिप्शन का हैंडल उसका transcriptionId होता है।
transcribe_url किसी सार्वजनिक URL पर ऑडियो या वीडियो ट्रांसक्रिप्ट करना शुरू करता है: फ़ाइल लिंक, पॉडकास्ट एपिसोड, YouTube वीडियो। लाइव स्ट्रीम स्वीकार नहीं होतीं। वैकल्पिक आर्गुमेंट्स: name, spokenLanguage (भाषा पहचानने के लिए इसे छोड़ दें), speakerLabels (auto, on या off), और startS/endS, ताकि केवल ऑडियो का एक हिस्सा ट्रांसक्रिप्ट हो।transcribe_file यही काम उस फ़ाइल के लिए करता है जो एजेंट के पास है, जिसे fileBase64 में उसके filename के साथ भेजा जाता है। डिकोड किया हुआ आकार 10 MiB तक सीमित है, जो लगभग 128 kbps MP3 के दस मिनट के बराबर है; इससे बड़ी फ़ाइल के लिए एजेंट को लिंक दें।दोनों तुरंत लौटते हैं, transcriptionId, state: "queued" और उस wait टूल का नाम बताने वाले next संकेत के साथ। एजेंट द्वारा बनाए गए ट्रांसक्रिप्शन निजी शुरू होते हैं, बिना शेयर लिंक के।
एजेंट किसी लाइव प्रसारण को उतने धैर्य से नहीं झेल सकता जितना आप झेल सकते हैं; वह तब तक wait टूल को कॉल करता रहता, जब तक कोई उसका लैपटॉप छीन न ले। समाप्त रिकॉर्डिंग का अंत होता है, और अगले दो टूल उसी अंत का इंतज़ार करते हैं।
एक टूल कॉल एक HTTP अनुरोध है, और HTTP अनुरोध एक घंटे तक चलने के लिए नहीं बने हैं। क्लाइंट उन्हें छोड़ देते हैं, प्रॉक्सी उन्हें बंद कर देते हैं, और जो मॉडल किसी एक टूल पर अटका है, वह कुछ और नहीं कर सकता। इसलिए MCP के पीछे किसी भी लंबे काम का पैटर्न वही है जो REST API भी इस्तेमाल करता है: काम शुरू करें और एक हैंडल लें, उसके लिए सीमित समय तक इंतज़ार करें, और अगर वह पूरा न हुआ हो तो फिर से कॉल करें। राज्य (state) हैंडल में रहता है, कनेक्शन में नहीं।
wait_for_transcription तब तक रुकता है जब तक काम done या failed न हो जाए, या timeoutS (डिफ़ॉल्ट 50 सेकंड, अधिकतम 60, जो कॉल को उन timeouts के नीचे रखता है जो ज़्यादातर क्लाइंट और प्रॉक्सी लगाते हैं) न बीत जाए। अगर परिणाम में timedOut: true है, तो काम अभी चल रहा है और एजेंट टूल को फिर से कॉल करता है। इंतज़ार के दौरान, अगर क्लाइंट ने माँगा है, तो सर्वर MCP प्रोग्रेस नोटिफ़िकेशन भेजता है: एक प्रतिशत और एक चरण, जैसे "fetching 3.1 / 8.0 MB" या "transcribing 01:25 of 02:00"।get_transcription स्थिति लौटाता है और पूरा होने पर टेक्स्ट। format: "text" हर सेगमेंट के लिए एक पंक्ति देता है, [mm:ss] Speaker 1: ... के रूप में; "segments" start, end, speaker और speakerName वाली समय-चिह्नित पंक्तियाँ देता है; includeWords: true शब्दों के समय जोड़ता है। परिणाम पेज में आते हैं (offset, limit, डिफ़ॉल्ट 500 सेगमेंट), और जब और सेगमेंट बचे हों तो nextOffset के साथ।पेजिंग नेटवर्क के लिए नहीं, मॉडल के लिए है। टूल जो कुछ भी लौटाता है, वह एजेंट के context window में चिपका दिया जाता है, जहाँ वह आपकी बातचीत से होड़ करता है और हर बाद की बारी में टोकन खर्च करता है। दो घंटे की मीटिंग दसियों हज़ार शब्दों की होती है; सब एक साथ लौटाने से आपका सवाल context से बाहर धकेल दिया जाएगा। अच्छे MCP टूल एक पेज और एक cursor लौटाते हैं, और एजेंट तय करता है कि उसे कितना चाहिए।
डिस्कनेक्ट या timeout कभी काम को रद्द नहीं करता, क्योंकि काम सर्वर पर चलता है, 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 }
पचास मिनट का एपिसोड चलने की रफ़्तार से कई गुना तेज़ ट्रांसक्रिप्ट होता है, लेकिन एक इंतज़ार के भीतर नहीं। पहला इंतज़ार timedOut: true लौटाता है, प्रगति लगभग 61 प्रतिशत पर, इसलिए एजेंट टूल को एक बार और कॉल करता है और state: "done" पाता है।
अब एजेंट lang: "fr" के साथ get_summary कॉल करता है:
{ "transcriptionId": "4f1c...", "lang": "fr" }
अगर सारांश अभी pending है, तो एजेंट कुछ सेकंड इंतज़ार करता है; नहीं तो वह आपको फ़्रेंच में शीर्षक और सारांश देता है। पूछें "उन्होंने कीमतों के बारे में कहाँ बात की?" तो वह query: "pricing" और उसी transcriptionId के साथ search_transcriptions कॉल करता है, और मेल खाने वाली पंक्तियों को उनके समय-चिह्नों के साथ उद्धृत करता है। पूरी बात फ़्रेंच में चाहें तो वह translate_transcription कॉल करता है।
कुछ टूल कॉल, कोई कोड नहीं, और आपकी लाइब्रेरी में एक ट्रांसक्रिप्ट। इनमें से हर कॉल उन्हीं गेट्स से गुज़रा जिनसे REST अनुरोध गुज़रता है, और वही गेट्स बिल और सीमाएँ तय करते हैं।
MCP सर्वर एक अलग दरवाज़े से गुज़रने वाला API ही है: वही सीमाएँ, वही बिल।
POST /v1/transcriptions गुज़रता है: प्लान की creation rate (प्रति घंटा शुरू किए गए ट्रांसक्रिप्शन 10, 100 या एक कस्टम संख्या), उसकी समवर्ती ट्रांसक्रिप्शन सीमा (1, 5 या असीमित) और उसका क्रेडिट, सब लागू होते हैं। $5 का साइनअप क्रेडिट बिना कार्ड के पहले सत्र को कवर करता है।isError: true के साथ REST API का त्रुटि कोड, एक वाक्य जिस पर मॉडल कार्रवाई कर सके, और retryable व retryAfterS फ़ील्ड लौटाता है। insufficient_credit के साथ topUpUrl आता है; rate_limited बताता है कि कितना इंतज़ार करना है। यह जितना लगता है उससे ज़्यादा मायने रखता है: मॉडल त्रुटि का टेक्स्ट पढ़ता है, और कार्रवाई योग्य एक वाक्य बंद रास्ते को अगले टूल कॉल में बदल देता है।/v1/mcp अनुरोध पर भी लागू होती है: लूप में फँसा एजेंट किसी टूल के चलने से पहले Retry-After के साथ HTTP 429 पाता है।idempotencyKey लेते हैं: पूरे हो चुके कॉल की key दोबारा देने पर पहला परिणाम दोहराया जाता है, और उसी key को अलग आर्गुमेंट्स के साथ देने पर वह अस्वीकार होता है, ताकि अपने आप दोबारा कोशिश करने वाला एजेंट दूसरा काम शुरू न करे। जो भी टूल पैसा खर्च करता है, उसे यह देना चाहिए; एजेंट लोगों से कहीं ज़्यादा आसानी से दोबारा कोशिश करते हैं।ये सर्वर की हदें हैं। दो चीज़ें जान-बूझकर इनसे बाहर हैं।
सर्वर में ऐसा कोई टूल नहीं है जो मनमाने टेक्स्ट को बोली में बदले, और ऐसा कोई टूल आगे की योजना में भी नहीं है। VocalStack ट्रांसक्रिप्ट और उनके अनुवाद बोलता है, किसी तैयार या क्लोन की गई आवाज़ में, और बस इतना ही। list_voices एजेंट को बताता है कि किसी भाषा में कौन सी आवाज़ें ट्रांसक्रिप्ट पढ़ सकती हैं, यह नहीं कि किसी आवाज़ से कुछ नया कहलवाया जाए।
transcribe टूल लाइव स्ट्रीम को भी स्वीकार नहीं करते। YouTube लाइव स्ट्रीम या रेडियो स्ट्रीम के लिए लाइव ट्रांसक्रिप्शन चाहिए, जो Dashboard से या API संदर्भ में POST /v1/transcriptions/live के ज़रिए शुरू होता है। समाप्त YouTube वीडियो एक फ़ाइल है, और उसे transcribe_url लेता है।
अगर आप कोड खुद लिखना चाहते हैं, तो API से फ़ाइल ट्रांसक्रिप्ट करना वही चरण HTTP कॉल्स के रूप में समझाता है, और रियल-टाइम ट्यूटोरियल WebSocket को कवर करता है।