Skip to main content
Glama

voice-io-mcp

License: MIT Python 3.10+ MCP Server Cost

Text-to-speech and speech-to-text as two small MCP tools — Groq's free hosted endpoints first, a fully local, keyless model if Groq isn't reachable or configured at all.

Every other tool in this ecosystem's nvidia-nim-mcp wraps image/text/vision/safety/embedding models behind a "try a real provider, fall back if it fails" contract. Audio was the one capability nothing covered — this fills that gap, same philosophy: a model being slow, rate-limited, or unconfigured should never take a tool down.

šŸ“– Table of Contents

Related MCP server: MCP TTS Server

🧰 Tools

Tool

What it does

Hosted tier (Groq, free)

Local fallback

šŸ”Š text_to_speech

Text → audio file, saved to output/

playai-tts

Kokoro-82M (Apache-2.0)

šŸŽ™ļø speech_to_text

Audio file → transcript (rejects non-audio extensions and files over 25MB before ever reading them)

whisper-large-v3-turbo

faster-whisper (MIT)

šŸ—£ļø list_voices

List known Groq PlayAI voice names for text_to_speech's voice argument

— (static list)

—

🩺 check_provider_health

Liveness probe for both hosted endpoints + local-dependency availability check

both

both

šŸ”„ The fallback chain

text_to_speech(text)
  ā”œā”€ 1. Groq playai-tts        (needs GROQ_API_KEY — free, no credit card)
  └─ 2. Kokoro-82M, local      (needs `uv sync --extra local-tts` — no key, no network)

speech_to_text(audio_path)
  ā”œā”€ 1. Groq whisper-large-v3-turbo   (needs GROQ_API_KEY)
  └─ 2. faster-whisper, local          (needs `uv sync --extra local-stt`)

Both tools try Groq first only if GROQ_API_KEY is set in .env — if it isn't, or if the Groq call fails for any reason, they drop straight to the local model. This is the one meaningful difference from nvidia-nim-mcp's own pattern: every tool here works with zero API keys configured at all, as long as the relevant optional extra is installed — a hosted key is a speed/quality upgrade, not a hard requirement.

The local tiers are genuinely last-resort: Kokoro always writes a .wav file regardless of the requested output_format (its native output; encoding straight to mp3 depends on the local libsndfile build, which isn't guaranteed cross-platform), and the tool's return message says so explicitly rather than silently substituting formats.

On model names: playai-tts and whisper-large-v3-turbo follow Groq's public API documentation, but neither was live-verified with a real key while building this repo (no key was available in the build environment). Run check_provider_health once GROQ_API_KEY is set to confirm they're still current — Groq's free-tier model lineup shifts over time, the same "don't trust a name from memory" discipline nvidia-nim-mcp documents for its own model list.

āš™ļø Setup

1. Install the base package (this project uses uv, not bare pip/venv):

uv sync

2. (Optional) Enable Groq's hosted tier. Create a .env file in the project root:

GROQ_API_KEY=your-key-here

Get one free at console.groq.com/keys — no credit card. Without it, both tools go straight to their local fallback.

3. (Optional) Enable the local fallbacks — each is an independent extra, install either or both:

uv sync --extra local-tts   # Kokoro-82M — also needs the `espeak-ng` system package
uv sync --extra local-stt   # faster-whisper

espeak-ng is used by Kokoro's phonemizer for out-of-distribution English and non-English text; straightforward English text works without it, but full quality/robustness wants it on PATH (apt install espeak-ng / choco install espeak-ng / brew install espeak-ng).

4. Register it as an MCP server with Claude Code (project or user scope):

claude mcp add --transport stdio voice-io -- uv run --project /path/to/this/repo voice_io.py

5. Run check_provider_health once, after setting GROQ_API_KEY. The model/voice names this server wires in (playai-tts, whisper-large-v3-turbo) were transcribed from Groq's public docs but never live-verified with a real key while building this — confirm they're still current before relying on the hosted tier, the same "don't trust a name from memory" discipline nvidia-nim-mcp documents for its own model list. If a name has drifted, the local fallback still works regardless (once its extra is installed).

ā–¶ļø Example usage

"Read this changelog entry out loud"
→ text_to_speech  → saved to output/speech_20260901_120000.mp3 (model: groq/playai-tts)

"Transcribe this voice memo at C:\Users\me\Desktop\note.wav"
→ speech_to_text  → returns the transcript (model: groq/whisper-large-v3-turbo)

"What voices can I use for text_to_speech?"
→ list_voices     → returns the known Groq PlayAI voice names, one per line

"Is voice-io's Groq connection actually working right now?"
→ check_provider_health → per-endpoint OK/FAIL report, plus whether the local
                           extras are installed

šŸ— Architecture

Single-file MCP server (voice_io.py), same shape as nvidia-nim-mcp's nvidia_image.py and mini-creative-toolkit's toolkit.py — one module, @mcp.tool()-decorated functions, no framework beyond the mcp package itself.

  • Hosted calls go through litellm (aspeech / atranscription), the same library nvidia-nim-mcp and model-comparison-harness already use for their own multi-provider chat chains — one dependency covering chat, TTS, and STT uniformly across providers, rather than hand-rolling Groq's HTTP shape directly.

  • Local fallbacks are lazy-loaded singletons (loaded once, on first real use, not at import time) guarded by a threading.Lock — a lesson carried over from a real bug caught in nvidia-nim-mcp's own local-embedding fallback: without the lock, two concurrent calls could both start loading the same large model at once.

  • The STT health probe builds a valid ~0.1s silent WAV in-memory using only Python's stdlib wave module — no binary audio fixture shipped in the repo, no extra dependency just to construct a liveness-check payload.

  • speech_to_text validates before it reads. It reads whatever local path it's given and uploads the bytes to Groq (a third party) — an extension allow-list and a 25MB size cap run before the file is opened, so a wrong or maliciously-crafted path (e.g. an agent instructed to "transcribe the audio at .env") is rejected locally instead of silently uploaded. Any captured Groq error text also has the API key scrubbed out before it's returned or logged, as defense-in-depth against an underlying HTTP client embedding it in an exception message.

šŸ›  Development

uv sync --group dev
uv run pytest

The suite (tests/) mocks every litellm call — no GROQ_API_KEY or real network access needed. It also exercises the real, unmocked local-fallback code paths against this repo's base test environment (where kokoro/faster-whisper are deliberately not installed, being optional extras), confirming both fallbacks fail closed — returning False/None, never raising — when their dependency is absent. CI (.github/workflows/ci.yml) runs the same command on every push/PR.

🚧 Known limitations / roadmap

  • Voice cloning is deliberately out of scope for v1. Kokoro's own upstream ecosystem and other open models (e.g. Chatterbox) support zero-shot voice cloning from a few seconds of reference audio — genuinely useful, but also the most misuse-prone capability in this space. If it's added later, it should ship with a mandatory consent-confirmation step and audio watermarking (Chatterbox bundles Perth, a watermarker, for exactly this reason) — not as an afterthought.

  • Groq's Gemini-Flash TTS tier was researched but not wired in. Its free tier exists but is restricted to non-commercial/personal use per Google's terms, and its request/response shape wasn't verified during this build — a clean second hosted fallback tier to add later once both are confirmed.

  • No streaming. Both tools return a complete file/transcript, not a chunked stream — fine for short clips and voice memos, a real limitation for long-form audio.

  • Kokoro's local fallback always emits .wav, ignoring output_format (see The fallback chain) — a deliberate cross-platform-safety tradeoff, not an oversight.

šŸ“„ License

MIT — see LICENSE. Kokoro-82M's weights are Apache-2.0; faster-whisper is MIT. Neither is vendored in this repo — both are optional dependencies, fetched from their own sources on install/first-use.

Available Tools

4 tools
check_provider_healthA

Check whether Groq's hosted TTS/STT endpoints are currently reachable and whether each local fallback's optional dependency is installed - without running a full local model load (kokoro/faster-whisper can take real time and disk space on first use, which would defeat the point of a quick health check).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It explicitly states the tool avoids loading kokoro/faster-whisper models, which is a key behavioral trait that prevents surprise time/disk costs. It also indicates that the check covers both network reachability and dependency installation, adding useful detail beyond a simple status check.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that front-loads the core purpose ('Check whether...') and then adds a parenthetical rationale for avoiding heavy model loads. Every clause earns its place; there is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter health check with an output schema, the description covers all necessary context: what is checked, why it avoids model loading, and what aspect of fallback dependencies it verifies. It does not need to explain return values because the output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the baseline is 4. The description need not explain parameter meaning because there are none. It focuses instead on the tool's purpose and behavior, which is appropriate here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('check') and resource ('Groq's hosted TTS/STT endpoints' and 'local fallback's optional dependency'), and clearly distinguishes itself from the sibling tools by focusing on health/readiness rather than performing TTS/STT operations. It leaves no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description conveys a clear context: this is a quick health check meant to verify reachability and dependency installation before heavier operations. It does not explicitly name sibling alternatives or state 'use before text_to_speech', but the purpose and the warning against model loading imply when it should be used. The absence of explicit exclusions keeps it at a 4 rather than a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_voicesA

List known Groq PlayAI voice names usable with text_to_speech's voice argument. Static list transcribed from Groq's public API docs, not fetched live - like the model names this server wires in, it can drift; check_provider_health confirms the default voice still works, not the full list.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full behavioral disclosure. It explicitly warns that the list is static, transcribed from public docs, not fetched live, and can drift. It also clarifies the scope of the health check sibling, which is valuable beyond the function's obvious purpose.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the tool's purpose, followed by essential caveats about staleness and health checking. Every clause adds value; there is no filler or redundant restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with an output schema, the description covers the essential context: what the tool lists, where the data comes from, its limitation, and how to verify current functionality via a sibling tool. Nothing important is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the schema already fully covers parameter semantics. The description adds useful context about what the returned voice names are and how they relate to text_to_speech, which meets the baseline for a no-parameter tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: it lists known Groq PlayAI voice names for use with text_to_speech's voice argument. It clearly distinguishes this from sibling tools by tying the list directly to another tool's parameter.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context that this is a static list and advises that check_provider_health only verifies the default voice, not the full list. This implies when to use this tool and when to use the health-check sibling, though it does not explicitly state exclusions for speech_to_text.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

speech_to_textA

Transcribe a local audio file to text.

Tries Groq's whisper-large-v3-turbo first (free tier, no credit card - requires GROQ_API_KEY), falling back to a fully local, keyless model (faster-whisper, MIT) if Groq is unavailable or the key isn't set. The local fallback requires the optional local-stt extra (uv sync --extra local-stt) and auto-downloads its model weights on first use.

Args: audio_path: Absolute path to a local audio file (mp3/wav/m4a/flac/ ogg/webm/mp4/mpeg/mpga), max 25MB. language: Optional ISO-639-1 language hint (e.g. "en"). Ignored by the local fallback, which auto-detects language.

ParametersJSON Schema
NameRequiredDescriptionDefault
languageNo
audio_pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full transparency burden. It discloses the Groq-first fallback, the GROQ_API_KEY requirement, the optional local-stt extra, first-use model weight download, and that the local fallback ignores language hints. It does not mention error handling or network assumptions, but the core operational behavior is well covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately concise and front-loaded with the main purpose, followed by a compact Args block. Every sentence adds useful operational or parameter detail; there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has a fallback architecture and conditional setup requirements, and the description covers all of these: provider order, fallback trigger, setup extra, model weight download, and input constraints. Since an output schema exists, the absence of an explicit return-value description is acceptable, and an agent has enough information to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides no descriptions for parameters, so the description must compensate. It fully explains audio_path as an absolute path with supported formats and max size, and language as an optional ISO-639-1 hint with example and fallback-specific behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action and resource: 'Transcribe a local audio file to text.' This is unambiguous and clearly different from sibling tools like text_to_speech, list_voices, and check_provider_health.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context: it is for local audio files, lists supported formats and the 25MB limit, and explains the optional language hint. It does not explicitly name sibling alternatives or state 'when not to use,' but the transcription versus speech-synthesis distinction is obvious from the sibling names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

text_to_speechA

Convert text to speech, saved to output/.

Tries Groq's playai-tts first (free tier, no credit card - requires GROQ_API_KEY), falling back to a fully local, keyless model (Kokoro-82M, Apache-2.0) if Groq is unavailable or the key isn't set. The local fallback always produces a .wav file regardless of output_format (Kokoro's native output), and requires the optional local-tts extra (uv sync --extra local-tts) plus the espeak-ng system package for full quality on non-trivial or non-English text.

Args: text: Text to speak. voice: Groq PlayAI voice name (e.g. "Fritz-PlayAI") - ignored by the local fallback, which always uses Kokoro's "af_heart" voice. output_format: "mp3" or "wav". Only honored on the Groq tier.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYes
voiceNoFritz-PlayAI
output_formatNomp3

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so thoroughly: it discloses provider fallback order, that the local fallback always emits .wav regardless of output_format, that voice is ignored on the local tier, and exact prerequisite setup (local-tts extra and espeak-ng).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The content is front-loaded with the one-line summary, followed by dense but relevant provider/fallback details and an Args section. Every sentence adds operational value with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no annotations and no parameter descriptions, the description covers provider selection, key requirements, output-directory behavior, and per-parameter semantics. An agent has enough information to invoke it correctly without inspecting sibling tools or external docs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description manually documents all three parameters: text, voice (with example and fallback behavior), and output_format (with allowed values and the caveat that it is only honored on Groq). This fully compensates for the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Convert text to speech, saved to output/.' This makes the tool's function immediately clear and distinguishes it from siblings such as speech_to_text (reverse direction) and list_voices/check_provider_health (support tools).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly states the primary purpose and the conditions under which each provider path is used: Groq first when available and the key is set, local fallback otherwise. It doesn't explicitly name when-not-to-use cases, but no sibling tool competes for this task, so clearer context would be marginal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.7/5.0
Disambiguation5/5

Each tool has a distinct role: text_to_speech and speech_to_text are inverse operations, list_voices specifically supports voice selection, and check_provider_health handles environment/endpoint diagnostics. There is no meaningful overlap or ambiguity between any two tools.

Naming Consistency4/5

All names are snake_case and readable. text_to_speech and speech_to_text form a consistent directional pair, while list_voices and check_provider_health follow a verb_noun pattern; the slight mix is minor and does not hinder prediction.

Tool Count5/5

Four tools is a reasonable, focused footprint for a voice I/O server: TTS, STT, voice enumeration, and health checks. Each tool earns its place without unnecessary redundancy.

Completeness5/5

The server covers the full core lifecycle of text-to-speech and speech-to-text, plus support for voice discovery and provider/dependency health. No major operations are missing for the stated scope.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Furkiozknn/voice-io-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server