Ένας server MCP μετατρέπει ένα API σε λίγα ονομασμένα εργαλεία που ο πράκτορας καλεί μέσα στη συνομιλία, και μια μακρά εργασία χωράει πίσω από ένα τέτοιο, όταν το εργαλείο επιστρέφει ένα αναγνωριστικό που ο πράκτορας περιμένει σε περιορισμένους γύρους. Επικολλήστε έναν σύνδεσμο podcast, ζητήστε τη σύνοψη στα γαλλικά, και δεν γράφεται κώδικας.
Ένας πράκτορας προγραμματισμού μπορεί να χρησιμοποιήσει το API του VocalStack όπως κάθε πρόγραμμα: διαβάζει την Τεκμηρίωση API, γράφει μερικές γραμμές με το SDK και τις εκτελεί. Αυτός είναι ο σωστός δρόμος για κάτι που θα τρέχει χωρίς τον πράκτορα.
Το MCP (Model Context Protocol) προορίζεται για την άλλη περίπτωση: μιλάτε με έναν βοηθό και θέλετε να απομαγνητοφωνήσει κάτι τώρα, χωρίς κώδικα. Ένας server MCP δημοσιεύει μια σύντομη λίστα ονομασμένων εργαλείων, το καθένα με περιγραφή και ένα σχήμα JSON για τα ορίσματά του. Ο πράκτορας διαβάζει τη λίστα μία φορά και καλεί ένα εργαλείο με το όνομά του όταν ένα αίτημα ταιριάζει με αυτό. Το «Απομαγνητοφώνησε αυτό το podcast και πες μου τι είπαν για τις τιμές» γίνεται τρεις κλήσεις εργαλείων, και ο πράκτορας δεν βλέπει ποτέ μια διαδρομή HTTP.
Οι server είναι δύο ειδών. Ένας τοπικός server τρέχει ως υποδιεργασία του client και επικοινωνεί μέσω stdio, που είναι ο τρόπος λειτουργίας των περισσότερων server συστημάτων αρχείων και βάσεων δεδομένων. Ένας απομακρυσμένος server βρίσκεται πίσω από ένα URL και μιλά Streamable HTTP, το transport που αντικατέστησε το παλαιότερο transport HTTP-plus-SSE (server-sent events) στην αναθεώρηση της προδιαγραφής τον Μάρτιο του 2025. Ο client στέλνει κάθε αίτημα, και ο server απαντά στην ίδια σύνδεση· ό,τι έχει να πει πριν από το τελικό αποτέλεσμα μεταδίδεται πριν από αυτό. Κάθε client γραμμένος με βάση την τρέχουσα προδιαγραφή μπορεί να χρησιμοποιήσει και τα δύο είδη.
Ο server του VocalStack είναι του απομακρυσμένου είδους, στη διεύθυνση {{api}}/v1/mcp, και η χρήση του κοστίζει όσο κοστίζει και το API. Χρειάζεστε μόνο το URL.
Ανοίξτε την περιοχή Developers του Dashboard στο {{app}}/developers. Η πρώτη καρτέλα, Connect an AI agent, εμφανίζει το URL του server και ένα απόσπασμα ρύθμισης για κάθε client. Τα τρία αποσπάσματα παρακάτω ταιριάζουν με εκείνα που εμφανίζονται εκεί.
Εκτελέστε αυτό στο τερματικό σας:
claude mcp add --transport http vocalstack {{api}}/v1/mcp
Προσθέστε αυτό στο .cursor/mcp.json του έργου σας, ή στο ~/.cursor/mcp.json για κάθε έργο:
{"mcpServers":{"vocalstack":{"url":"{{api}}/v1/mcp"}}}
Κάθε client που υποστηρίζει Streamable HTTP μπορεί να προσθέσει τον server με αυτό το URL. Αυτή είναι η γενική μορφή που εμφανίζει το Dashboard:
{
"vocalstack": {
"type": "streamable-http",
"url": "{{api}}/v1/mcp"
}
}
Δεν χρειάζεστε κλειδί API για να ξεκινήσετε. Την πρώτη φορά που θα συνδεθεί ο client, συνδέεστε με τον λογαριασμό σας VocalStack στο πρόγραμμα περιήγησης, και ο client κρατά το διακριτικό (token). Το Dashboard το λέει σε μία γραμμή: «Θα συνδεθείτε με τον λογαριασμό σας VocalStack την πρώτη φορά. Δεν χρειάζεται κλειδί.»
Αυτή είναι η εφαρμογή της προδιαγραφής εξουσιοδότησης του MCP, όχι κάποιο τέχνασμα του VocalStack. Ένας απομακρυσμένος server απαντά σε ένα μη ταυτοποιημένο αίτημα με 401 που δείχνει στα μεταδεδομένα του προστατευόμενου πόρου: ένα μικρό έγγραφο JSON που ονομάζει τον διακομιστή εξουσιοδότησης και τα πεδία δικαιωμάτων (scope) που απαιτεί ο server. Ο client το διαβάζει, εκτελεί στον περιηγητή μια τυπική ροή OAuth 2.1 και επιστρέφει με ένα διακριτικό που εκδίδεται μόνο για αυτόν τον server. Κάθε απομακρυσμένος server MCP που ακολουθεί την προδιαγραφή σάς συνδέει με τον ίδιο τρόπο, γι' αυτό οι client που αναφέρθηκαν μπορούν να το κάνουν χωρίς να γνωρίζουν τίποτα για το VocalStack.
Ένα κλειδί API λειτουργεί επίσης, για έναν client που τρέχει σε διακομιστή ή σε σενάριο. Στείλτε το ως Authorization: Bearer vs_key_..., την ίδια κεφαλίδα που δέχεται και το REST API. Τα κλειδιά δημιουργούνται στο Developers → API keys. Τα δύο εργαλεία απομαγνητοφώνησης χρειάζονται τα δικαιώματα Write και Stream audio. Το δεύτερο ακούγεται περίεργο για αρχείο, αλλά τα εργαλεία περνούν από το ίδιο σημείο δημιουργίας με κάθε απομαγνητοφώνηση, και τις ζωντανές, και το σημείο αυτό ελέγχει και τα δύο. Τα εργαλεία ανάγνωσης χρειάζονται το Read· το list_voices χρειάζεται μόνο έγκυρο διαπιστευτήριο.
Μόλις συνδεθείτε, ο πράκτορας βλέπει εννέα εργαλεία. Σπάνια θα τα ονομάσετε εσείς, αλλά η γνώση τους εξηγεί τι κάνει ο πράκτορας στη συνέχεια.
Κάθε εργαλείο δέχεται και επιστρέφει JSON σε camelCase, με τα ίδια ονόματα πεδίων με τους τύπους του /v1· το αναγνωριστικό μιας απομαγνητοφώνησης είναι το transcriptionId της.
transcribe_url ξεκινά την απομαγνητοφώνηση ήχου ή βίντεο σε δημόσιο URL: σύνδεσμο αρχείου, επεισόδιο podcast, βίντεο YouTube. Οι ζωντανές μεταδόσεις δεν γίνονται δεκτές. Προαιρετικά ορίσματα: name, spokenLanguage (παραλείψτε το για αυτόματη ανίχνευση της γλώσσας), speakerLabels (auto, on ή off) και startS/endS για απομαγνητοφώνηση μόνο ενός τμήματος του ήχου.transcribe_file κάνει το ίδιο για αρχείο που έχει ο πράκτορας, το οποίο στέλνεται ως fileBase64 με το filename του. Το αποκωδικοποιημένο μέγεθος περιορίζεται στα 10 MiB, περίπου δέκα λεπτά MP3 των 128 kbps· για μεγαλύτερα, δώστε στον πράκτορα έναν σύνδεσμο.Και τα δύο επιστρέφουν αμέσως το transcriptionId, το state: "queued" και μια υπόδειξη next που ονομάζει το εργαλείο αναμονής. Οι απομαγνητοφωνήσεις που δημιουργούνται από πράκτορα ξεκινούν ιδιωτικές, χωρίς σύνδεσμο κοινοποίησης.
Ένας πράκτορας δεν μπορεί να περιμένει μια ζωντανή μετάδοση με περισσότερη υπομονή από ό,τι εσείς· θα καλούσε συνεχώς το εργαλείο αναμονής, ώσπου να του κλείσει κάποιος το laptop. Μια ολοκληρωμένη εγγραφή έχει τέλος, και αυτό περιμένουν τα επόμενα δύο εργαλεία.
Μια κλήση εργαλείου είναι ένα αίτημα HTTP, και τα αιτήματα HTTP δεν προορίζονται να κρατούν μία ώρα. Οι client τα εγκαταλείπουν, οι proxy τα κλείνουν, και ένα μοντέλο που περιμένει σε ένα εργαλείο δεν μπορεί να κάνει τίποτε άλλο. Επομένως το μοτίβο για κάθε μακρά εργασία πίσω από το MCP είναι εκείνο που χρησιμοποιεί και το REST API: ξεκινάτε την εργασία και παίρνετε ένα αναγνωριστικό, περιμένετε σε αυτό για περιορισμένο χρόνο, και καλείτε ξανά αν δεν έχει ολοκληρωθεί. Το αναγνωριστικό, όχι η σύνδεση, φέρει την κατάσταση.
wait_for_transcription περιμένει έως ότου η εργασία γίνει done ή failed, ή έως ότου περάσει το timeoutS (προεπιλογή 50 δευτερόλεπτα, μέγιστο 60, ώστε η κλήση να μένει μέσα στα χρονικά όρια που εφαρμόζουν οι περισσότεροι client και proxy). Αν το αποτέλεσμα λέει timedOut: true, η εργασία εξακολουθεί να τρέχει και ο πράκτορας καλεί ξανά το εργαλείο. Όσο το εργαλείο περιμένει, ο server στέλνει ειδοποιήσεις προόδου MCP, αν τις ζήτησε ο client: ένα ποσοστό και μια φάση, όπως «λήψη 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 επιστρέφουν μια σελίδα και έναν δείκτη, και αφήνουν τον πράκτορα να αποφασίσει πόσα χρειάζεται.
Η αποσύνδεση ή το timeout δεν ακυρώνει ποτέ την εργασία, γιατί η εργασία ζει στον server, όχι στο αίτημα MCP. Μόλις ολοκληρωθεί, η εργασία είναι μία ακόμη καταχώρηση στη βιβλιοθήκη σας, και τα επόμενα εργαλεία την αντιμετωπίζουν όπως κάθε άλλη.
list_transcriptions εμφανίζει τις απομαγνητοφωνήσεις του λογαριασμού, από τη νεότερη, με κατάσταση και διάρκεια· το lifecycle είναι active, archived ή all.search_transcriptions αναζητά τα λεχθέντα σε όλες τις απομαγνητοφωνήσεις, σε οποιαδήποτε γλώσσα, και επιστρέφει τις αντίστοιχες γραμμές, καθεμία με την απομαγνητοφώνηση και το δευτερόλεπτο που ειπώθηκε. Το transcriptionId περιορίζει την αναζήτηση σε μία απομαγνητοφώνηση· το lang προσθέτει μετάφραση κάθε αποτελέσματος.Η εύρεση μιας γραμμής είναι το εύκολο μισό. Δύο ακόμη εργαλεία βρίσκουν τι είπε όλη η απομαγνητοφώνηση.
get_summary επιστρέφει τον τίτλο και τη σύνοψη AI μιας ολοκληρωμένης απομαγνητοφώνησης, προαιρετικά μεταφρασμένα με το lang. Το state: "pending" σημαίνει ότι η σύνοψη γράφεται ακόμη (συνήθως είναι έτοιμη μέσα σε δευτερόλεπτα από την ολοκλήρωση της εργασίας), και ο πράκτορας ρωτά ξανά.translate_transcription επιστρέφει ένα ολοκληρωμένο απομαγνητοφωνημένο κείμενο σε άλλη γλώσσα, ως κείμενο ή ως χρονισμένα τμήματα, σε σελίδες όπως το get_transcription. Οι μεταφράσεις αποθηκεύονται, οπότε η δεύτερη ερώτηση δεν επαναλαμβάνει τη δουλειά.list_voices εμφανίζει τις φωνές που μπορούν να διαβάσουν ένα κείμενο σε μια γλώσσα: αναγνωριστικό, όνομα, φύλο και προφορά όταν είναι γνωστά, βαθμολογία ποιότητας, και αν είναι η προεπιλογή ή μία από τις κλωνοποιημένες φωνές σας. Περιγράφει φωνές· δεν κάνει καμία να πει κάτι καινούργιο (περισσότερα παρακάτω για το τι δεν κάνει ο server).Ακολουθεί πώς συνδέονται τα εργαλεία στην πράξη.
Αφού προσθέσετε τον server, μια συνομιλία στο Claude Code πηγαίνει ως εξής. Επικολλάτε έναν σύνδεσμο podcast και ζητάτε τη σύνοψη στα γαλλικά.
Ο πράκτορας καλεί το 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".
Τώρα ο πράκτορας καλεί το get_summary με lang: "fr":
{ "transcriptionId": "4f1c...", "lang": "fr" }
Αν η σύνοψη είναι ακόμη pending, ο πράκτορας περιμένει λίγα δευτερόλεπτα· αλλιώς σας δίνει τίτλο και σύνοψη στα γαλλικά. Αν ρωτήσετε «πού μίλησαν για τις τιμές;», καλεί το search_transcriptions με query: "pricing" και το ίδιο transcriptionId, και παραθέτει τις αντίστοιχες γραμμές με τα χρονικά σημεία τους. Αν ζητήσετε ολόκληρο το κείμενο στα γαλλικά, καλεί το translate_transcription.
Λίγες κλήσεις εργαλείων, χωρίς κώδικα, και μία απομαγνητοφώνηση στη βιβλιοθήκη σας. Κάθε μία από αυτές τις κλήσεις πέρασε από τις ίδιες πύλες με ένα αίτημα REST, και αυτές οι πύλες ορίζουν τη χρέωση και τα όρια.
Ο server MCP είναι το API από άλλη είσοδο: ίδια όρια, ίδια χρέωση.
POST /v1/transcriptions: ισχύουν ο ρυθμός δημιουργίας του προγράμματος (10, 100 ή έναν προσαρμοσμένο αριθμό απομαγνητοφωνήσεων που ξεκινούν την ώρα), το όριο ταυτόχρονων απομαγνητοφωνήσεων (1, 5 ή απεριόριστο) και η πίστωσή του. Η πίστωση εγγραφής $5 καλύπτει μια πρώτη συνεδρία, χωρίς να χρειάζεται κάρτα.isError: true με τον κωδικό σφάλματος του REST API, μια πρόταση που το μοντέλο μπορεί να εφαρμόσει, και τα πεδία retryable και retryAfterS. Το insufficient_credit συνοδεύεται από topUpUrl· το rate_limited λέει πόση ώρα να περιμένετε. Αυτό έχει μεγαλύτερη σημασία απ' όσο φαίνεται: ένα μοντέλο διαβάζει το κείμενο του σφάλματος, και μια πρόταση που μπορεί να εφαρμόσει μετατρέπει ένα αδιέξοδο στην επόμενη κλήση εργαλείου./v1/mcp: ένας πράκτορας σε βρόχο παίρνει HTTP 429 με Retry-After πριν εκτελεστεί οποιοδήποτε εργαλείο.idempotencyKey: η επαναχρησιμοποίηση του κλειδιού μιας ολοκληρωμένης κλήσης επαναλαμβάνει το πρώτο αποτέλεσμα, και η επαναχρησιμοποίησή του με διαφορετικά ορίσματα απορρίπτεται, ώστε ένας πράκτορας που ξαναδοκιμάζει μόνος του να μην ξεκινά ποτέ δεύτερη εργασία. Κάθε εργαλείο που ξοδεύει χρήματα πρέπει να προσφέρει αυτή τη λειτουργία· οι πράκτορες ξαναδοκιμάζουν πολύ πιο ελεύθερα από τους ανθρώπους.Αυτά είναι τα όρια του server. Δύο πράγματα βρίσκονται εκτός τους, επιτηδέως.
Ο server δεν έχει εργαλείο που μετατρέπει ελεύθερο κείμενο σε ομιλία, και δεν προγραμματίζεται κάποιο. Το VocalStack αποδίδει φωνητικά απομαγνητοφωνήσεις και τις μεταφράσεις τους, με έτοιμη ή κλωνοποιημένη φωνή, και τίποτα άλλο. Το list_voices λέει σε έναν πράκτορα ποιες φωνές μπορούν να διαβάσουν ένα κείμενο σε μια γλώσσα, όχι πώς να κάνει μια φωνή να πει κάτι καινούργιο.
Τα εργαλεία απομαγνητοφώνησης απορρίπτουν επίσης τις ζωντανές ροές. Μια ζωντανή ροή YouTube ή ένας ραδιοφωνικός σταθμός χρειάζονται ζωντανή απομαγνητοφώνηση, που ξεκινά από το Dashboard ή μέσω του POST /v1/transcriptions/live στην τεκμηρίωση API. Ένα ολοκληρωμένο βίντεο YouTube είναι αρχείο, και το transcribe_url το δέχεται.
Αν προτιμάτε να γράψετε τον κώδικα μόνοι σας, η απομαγνητοφώνηση ενός αρχείου με το API περιγράφει τα ίδια βήματα ως κλήσεις HTTP, και το σεμινάριο πραγματικού χρόνου καλύπτει το WebSocket.