mcp-voice-studio
This server provides MCP tools for local voice cloning and text-to-speech synthesis using OmniVoice, plus voice profile management and an optional ASMR post-processing DSP pipeline.
Clone voices from audio: Save a voice profile from a local WAV file (5–30s reference + transcript) or from a YouTube/URL clip via yt-dlp + ffmpeg slicing.
Synthesize speech: Generate TTS audio using a cloned voice, voice design keywords (e.g.
whisper, female, low pitch), or a hybrid of both.Design one-off voices: Use
design_voicewith style keywords without creating a permanent profile.Manage voice profiles: List all saved voices, inspect detailed metadata (ref audio, transcript, timestamps), and delete voices with their reference audio.
Apply ASMR effects: Enhance generated audio with stereo panning, silence padding, reverb, binaural beats, highpass/lowpass filters — controllable per request.
Control synthesis parameters: Adjust speed, language, diffusion steps, guidance scale, output path, and more.
Run locally for free: All inference runs on your GPU via VoiceStudio/OmniVoice; no API costs.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-voice-studio Synthesize speech with voice claudia_asmr saying 'Good evening, friends.'"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
VoiceStudio_mcp
MCP server wrapper for VoiceStudio (debpalash) — local voice cloning & TTS via the OmniVoice engine.
Exposes 6 tools to any MCP client (Trae IDE, Claude Desktop, etc.):
Tool | What it does |
| Save a voice profile from 5-30s of reference audio + transcript |
| Generate speech with a cloned voice OR voice design keywords (or both) |
| Generate speech using only voice design (no cloned voice) |
| List all saved voice profiles |
| Get metadata of a single voice profile |
| Delete a voice profile and its ref audio |
Free & local. No API costs, all inference runs on your GPU (tested on NVIDIA GB10 sm_120 / DGX Spark). Uses OmniVoice (Apache 2.0) + higgs-audio-v2-tokenizer (MIT).
Parent project
This repo is a thin MCP wrapper around debpalash/VoiceStudio (AGPL-3.0) — the upstream local voice-cloning / TTS engine. All heavy inference (torch + CUDA) runs inside VoiceStudio's venv; this repo only exposes it over MCP. The underlying model is k2-fsa/OmniVoice.
Related MCP server: Local Voice MCP
Why this exists
VoiceStudio is a great local ElevenLabs alternative (AGPL-3.0, 1.3k+ stars) but it ships as a CLI + Gradio UI. This wrapper exposes it as an MCP server so you can:
Call voice cloning / TTS from any MCP-compatible agent
Programmatically manage voice profiles (create, list, delete)
Reuse a single VoiceStudio venv across multiple tools without spawning Gradio
Install (DGX Spark / aarch64+CUDA)
1. Clone this repo + VoiceStudio (sibling)
mkdir -p ~/Repositories
cd ~/Repositories
git clone https://github.com/debpalash/VoiceStudio.git
git clone https://github.com/jagones84/VoiceStudio_mcp.git VoiceStudio_mcp2. Build VoiceStudio venv (one-time, ~5min)
Run the following steps to build VoiceStudio's venv:
cd VoiceStudio
# patch pyproject (remove aarch64 marker, pin torch 2.11+cu128, etc.)
bash /home/jagones/Repositories/trash/patch_pyproject.sh
bash /home/jagones/Repositories/trash/fix_torchvision_pin.sh
# build venv
export PATH="$HOME/.local/bin:$PATH"
rm -rf .venv uv.lock
uv lock && uv sync --python 3.12
# install torchcodec + cu12 NPP
source .venv/bin/activate
bash /home/jagones/Repositories/trash/install_torchcodec.sh
bash /home/jagones/Repositories/trash/install_nvidia_cu12.sh
bash /home/jagones/Repositories/trash/upgrade_nvidia_cu128.sh
# verify
python -c "import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))"
# True NVIDIA GB103. Build this MCP venv (lightweight, ~30s)
cd ../VoiceStudio_mcp
cp .env.template .env
# edit .env: set HF_TOKEN (free at https://huggingface.co/settings/tokens)
export PATH="$HOME/.local/bin:$PATH"
uv syncThe MCP venv reuses the heavy torch+CUDA libs from VoiceStudio's venv via the engine wrapper (mcp_voice_studio/core/engine.py). The MCP venv only needs mcp + pydantic.
4. Test
uv run python -c "from mcp_voice_studio.server import mcp; print('tools:', [t.name for t in mcp._tool_manager._tools.values()])"Expected:
tools: ['tool_clone_voice_from_audio', 'tool_synthesize_speech', 'tool_design_voice', 'tool_list_voices', 'tool_get_voice_info', 'tool_delete_voice']Register in MCP clients
Trae IDE (Windows)
Add to .mcp.json (project root or ~/.trae/mcp.json):
{
"mcpServers": {
"voice-studio": {
"command": "ssh",
"args": [
"dgx",
"cd /home/jagones/Repositories/VoiceStudio_mcp && /home/jagones/.local/bin/uv run --no-sync python -m mcp_voice_studio"
],
"env": {
"HF_TOKEN": "hf_xxx",
"VOICESTUDIO_VENV": "/home/jagones/Repositories/VoiceStudio/.venv"
}
}
}
}Replace dgx with your SSH host alias, and hf_xxx with your real HF token (free).
Claude Desktop
claude_desktop_config.json:
{
"mcpServers": {
"voice-studio": {
"command": "ssh",
"args": ["dgx", "cd /home/jagones/Repositories/VoiceStudio_mcp && /home/jagones/.local/bin/uv run --no-sync python -m mcp_voice_studio"]
}
}
}Usage examples (from an MCP client)
Clone a voice from a 6-second sample
> Use clone_voice_from_audio to save a voice called "claudia_asmr"
> from /home/jagones/Repositories/VoiceStudio/inputs/asmr_sample.wav
> with ref_text "Hola, soy Claudia. Esta es una muestra de mi voz en estilo ASMR."Tool response:
{
"status": "ok",
"voice_name": "claudia_asmr",
"profile_path": "/home/jagones/Repositories/VoiceStudio_mcp/mcp_voice_studio/data/voices/claudia_asmr/profile.json",
"ref_audio_path": ".../data/voices/claudia_asmr/ref_audio.wav"
}Generate ASMR speech with the cloned voice
> Use synthesize_speech with voice_name="claudia_asmr", text="Benvenuto, chiudi gli occhi, fai un respiro profondo..."Tool response:
{
"output_path": "/home/jagones/Repositories/VoiceStudio_mcp/mcp_voice_studio/data/outputs/synth_1757062500.wav",
"duration_s": 24.04,
"sample_rate": 24000,
"channels": 1,
"model": "k2-fsa/OmniVoice",
"voice_name": "claudia_asmr",
"generation_time_s": 47.3
}ASMR enhancements (post-synth DSP pipeline)
synthesize_speech and design_voice accept 5 optional ASMR parameters. All are applied as a deterministic post-processing pipeline on the generated mono WAV (numpy + scipy, no extra GPU). The output is stereo whenever any pan/reverb effect is active.
The pipeline runs in this order: highpass (60Hz) → lowpass → stereo_pan → reverb (with HF damping) → binaural_beat → silence_padding. The highpass is always on by default to remove DC offset and sub-bass rumble that synthetic voices can carry.
Param | Type | Effect | ASMR sweet spot |
|
| Stereo panning law (constant-power). |
|
| int (0–5000) | Inserts ms of silence at every | 400–800 ms |
|
| Schroeder reverb (4 comb + 2 allpass filters, 18 % mix) with HF damping filter (damping=0.5 default) on each comb to avoid the classic "metallic" ring. |
|
| float (0–40) | Adds a sine wave to L (200 Hz) and a slightly-detuned sine to R. Perceived as a brainwave entrainment tone. Amplitude is fixed at 0.0005 (-66dBFS, true sub-audible carrier) — only the 4–8 Hz pulsation is heard, never the 200 Hz tone itself. OFF by default to keep the output clean; pass a positive value to enable. | 4–8 Hz (theta-alpha) |
| float (0–20000) | 2nd-order Butterworth lowpass for "warmth" / intimacy. | 5000–7000 Hz |
Example — full ASMR stack:
> Use synthesize_speech with:
voice_name="claudia_asmr"
text="Ascolta il mio respiro. Lascia andare ogni tensione. Sei al sicuro."
stereo_pan="L<->R"
silence_padding_ms=600
reverb="small_room"
lowpass_cutoff_hz=6500.0Response:
{
"output_path": ".../synth_1757064500.wav",
"duration_s": 8.83,
"sample_rate": 24000,
"channels": 2,
"asmr_applied": [
"lowpass(6500Hz)", "stereo_pan(L<->R)", "reverb(small_room)",
"binaural_beat(6Hz)", "silence_padding(600ms)"
],
"generation_time_s": 17.6
}The asmr_applied list reports exactly which effects ran (so you can distinguish "nothing applied" from "applied but no audible effect"). Order in the pipeline: lowpass → pan → reverb → binaural → silence padding.
Voice design without cloning
> Use design_voice with instruct="whisper, female, low pitch", text="Hello world"Combine cloning + design
> Use synthesize_speech with voice_name="claudia_asmr", instruct="whisper", text="..."(cloned voice + extra style instruction)
List / inspect / delete
> list_voices
> get_voice_info(voice_name="claudia_asmr")
> delete_voice(voice_name="claudia_asmr")Voice design keywords (OmniVoice)
Only these are accepted by OmniVoice's --instruct (case-sensitive, comma+space separated, English OR Chinese, never mix):
English: american accent, australian accent, british accent, canadian accent, child, chinese accent, elderly, female, high pitch, indian accent, japanese accent, korean accent, low pitch, male, middle-aged, moderate pitch, portuguese accent, russian accent, teenager, very high pitch, very low pitch, whisper, young adult
Chinese (full-width comma ,): 东北话,中年,中音调,云南话,低音调,儿童,四川话,女,宁夏话,少年,极低音调,极高音调,桂林话,河南话,济南话,甘肃话,男,石家庄话,老年,耳语,贵州话,陕西话,青岛话,青年,高音调
For ASMR whisper: whisper, female, low pitch
Architecture
VoiceStudio_mcp/
├── pyproject.toml # mcp + pydantic + numpy + scipy (no torch!)
├── mcp_voice_studio/
│ ├── server.py # FastMCP entry, registers 6 tools
│ ├── core/
│ │ ├── config.py # paths, env (HF_TOKEN, VOICESTUDIO_VENV, CUDA_VISIBLE_DEVICES)
│ │ ├── models.py # Pydantic: VoiceProfile, SynthRequest, SynthResult
│ │ ├── storage.py # JSON+ref_audio persistence per voice profile
│ │ ├── engine.py # auto-fallback: subprocess omnivoice-infer → inproc import
│ │ └── asmr.py # DSP post-processor: pan, padding, reverb, binaural, lowpass
│ ├── tools/
│ │ ├── clone_voice.py # clone_voice_from_audio
│ │ ├── synthesize.py # synthesize_speech, design_voice
│ │ └── manage.py # list_voices, get_voice_info, delete_voice
│ └── data/ # gitignored runtime data
│ ├── voices/<name>/ # per-voice: ref_audio.wav, ref_text.txt, profile.json
│ ├── outputs/ # generated WAVs
│ ├── logs/ # synthesis logs
│ └── inputs/ # default reference audio
├── tests/ # pytest
├── examples/ # usage examples + mcp_config.json
└── docs/ # architecture, APIEngine wrapper: auto-fallback
mcp_voice_studio/core/engine.py tries two execution modes:
Subprocess (default): spawns
uv run --no-sync omnivoice-infer ...from VoiceStudio's venv.Pro: isolates GPU state, most robust, no version coupling
Con: ~1s spawn overhead per call
In-process (fallback): adds VoiceStudio's site-packages to
sys.pathand importsomnivoicedirectly.Pro: faster (no spawn)
Con: requires VoiceStudio venv to be importable in this venv
Auto-fallback: if subprocess fails because the binary is missing, switches to in-process.
LD_LIBRARY_PATH for cu12 NPP
torchcodec (used by torchaudio 2.11) loads libnppicc.so.12. DGX Spark only has CUDA 13 system libs. The engine wrapper sets LD_LIBRARY_PATH to point at the pip-installed nvidia-npp-cu12==12.4.1.87 (from VoiceStudio venv) BEFORE the system CUDA 13 path. This avoids the TLS clash caused by symlinks.
Standalone scripts (no MCP client needed)
Two scripts under scripts/ let you run the cloning + ASMR pipeline from a terminal (useful for batch jobs or quick testing).
apply_asmr_effects.py — DSP-only on an existing WAV (no GPU, runs anywhere)
python scripts/apply_asmr_effects.py INPUT.wav OUTPUT.wav --text "..." [options]Flag | Default | Effect |
| off |
|
| 2.0 | L<->R/L->R period in seconds |
| 0 | silence padding at sentence boundaries (0-5000) |
| off |
|
| 0.5 | HF damping 0..1 (0=classic Schroeder) |
| 0.0 | 0=off, 4-8=theta-alpha |
| 0.0005 | carrier peak (default -66dBFS sub-audible) |
| 0 | 0=off, 5000-7000 sweet spot |
| 60.0 | 0=off, 60Hz = DC/sub-bass cleanup |
Example:
python scripts/apply_asmr_effects.py voice.wav out.wav \
--text "Benvenuto. Chiudi gli occhi. Respira." \
--stereo-pan "L<->R" --period-s 2.5 \
--silence-padding-ms 600 \
--reverb small_room \
--lowpass-cutoff-hz 6500.0clone_and_speak.py — E2E: clone/design + synthesize + ASMR (needs DGX/GPU)
# Cloned voice
python scripts/clone_and_speak.py --voice claudia_asmr \
--text "Ascolta il mio respiro. Sei al sicuro." \
--out out.wav \
--stereo-pan "L<->R" --silence-padding-ms 600 --reverb small_room
# Voice design (no clone)
python scripts/clone_and_speak.py --instruct "whisper, female, low pitch" \
--text "Hello world" --out out.wav --reverb small_roomBoth scripts call the same code paths the MCP tools use (synthesize_speech for TTS, apply_asmr_pipeline for DSP), so output is identical to what you'd get from an MCP client.
License
Copyright (c) 2026 jagones84.
AGPL-3.0 — this wrapper is licensed under the GNU Affero General Public License v3.0, the same license as the upstream debpalash/VoiceStudio it drives. See LICENSE and THIRD_PARTY_LICENSES.md for the full picture.
TL;DR for publishing on GitHub:
This repo (
VoiceStudio_mcp) is AGPL-3.0 — if you run it (or a modified version) as a network service, AGPL section 13 requires you to offer the corresponding source to your users.VoiceStudio is AGPL-3.0 — installed separately via
git clone, NOT bundled here. It is the upstream engine this wrapper exposes over MCP.OmniVoice is Apache 2.0, higgs-audio-v2-tokenizer is MIT — both downloaded from Hugging Face at runtime, NOT bundled.
Available Tools
6 toolstool_clone_voice_from_audioA
Save a voice profile from a reference audio (5-30s WAV ideal).
Two input modes (EITHER ref_audio_path OR audio_url must be provided, not both): A) Local file: pass ref_audio_path='/path/to/sample.wav'. B) URL clip: pass audio_url='https://youtu.be/...', ts=30, tf=45. yt-dlp downloads the audio and ffmpeg slices [ts, tf] into a 24kHz mono 16-bit PCM WAV, which is then used as the reference.
Workflow:
Pick a clean 5-30s speech sample (local file OR URL clip).
Write the exact transcript in ref_text.
Pick a memorable voice_name (used later as voice_name= in synthesize_speech).
Returns a dict with 'status', 'voice_name', 'profile_path', 'ref_audio_path', and (for URL mode) 'source_url', 'ts', 'tf', 'clip_duration_s'.
Common errors:
both ref_audio_path and audio_url provided: pick one.
voice_exists: pass overwrite=True or pick a different voice_name.
bad local path: check the path exists and is readable.
bad URL: yt-dlp/ffmpeg failure will be reported in the raised RuntimeError.
Inputs: ref_text (required), voice_name (required), tf, ts, +5 more.
tool_delete_voiceA
Delete a voice profile and its reference audio file. Cannot be undone.
Use this to free disk space or clean up test voices. The voice will no longer appear in list_voices and synthesize_speech with this voice_name will fail.
Inputs: voice_name (required).
tool_design_voiceA
Generate speech using voice design keywords only (no cloned voice).
Same ASMR params as synthesize_speech. Use this when you want a one-off voice without persisting a profile. For reusable voices, clone first with clone_voice_from_audio then call synthesize_speech with voice_name.
Inputs: text (required), instruct (required), speed, reverb, +11 more.
tool_get_voice_infoA
Get full metadata of a single saved voice profile: name, description, language, ref_audio_path, ref_text, created_at.
Use this to verify a profile exists and inspect its reference audio path before calling synthesize_speech with that voice_name.
Inputs: voice_name (required).
tool_list_voicesA
List all saved voice profiles.
Returns: list of dicts, each with 'name', 'description', 'language', 'source', 'created_at'. Use this to discover available voice_name values before calling synthesize_speech.
Inputs: no named parameters. Returns: result
tool_synthesize_speechA
Generate speech audio with a cloned voice (from voice_name) OR voice design (from instruct), or both.
Three usage modes:
Cloned voice: pass voice_name='claudia_asmr', omit instruct.
Voice design: pass instruct='whisper, female, low pitch', omit voice_name.
Hybrid: pass both voice_name AND instruct to add style to a cloned voice.
Returns dict with: output_path, duration_s, sample_rate, channels, model, voice_name, generation_time_s, and (if any ASMR effect ran) asmr_applied.
ASMR pipeline: highpass(60Hz) -> lowpass -> stereo_pan -> reverb -> binaural -> padding. All ASMR params default to OFF (passthrough). Output is stereo whenever any stereo-capable effect (stereo_pan, reverb, binaural_beat_hz) is active.
Inputs: text (required), speed, reverb, instruct, +12 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
Profile management tools (list/get/delete) are clearly distinct, and clone/synthesize have clear roles. However, design_voice overlaps with synthesize_speech because synthesize_speech also supports voice design via the instruct parameter; the descriptions mitigate this, but an agent could still be unsure which to call.
All tool names follow a consistent tool_verb_noun snake_case pattern, with each verb clearly indicating the action. The minor noun variation between 'voice' and 'speech' is natural and does not create confusion.
Six tools is a well-scoped size for a voice cloning and synthesis server. Each tool contributes to a clear lifecycle: profile creation, inspection, deletion, and audio generation.
The server covers the full voice-profile lifecycle: create via clone, read via list and get info, delete, and use for speech synthesis. It also offers a one-off design path, leaving no obvious critical gaps for its stated purpose.
Maintenance
Related MCP Connectors
AI voice generation: text-to-speech and voice cloning from any MCP client.
Official MCP server for OmniDimension. Drive voice agents, dispatch calls, and run bulk campaigns.
MCP server exposing the AceDataCloud Fish Audio API (text-to-speech with voice conditioning)
Hosted text-to-speech MCP server: 66 voices in 9 languages, long-form narration, podcasts.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceA local voice interface providing high-performance speech recognition and natural text-to-speech with voice cloning capabilities. It enables AI assistants to speak, listen, and engage in character-based voice conversations through integrated MCP tools.-
- AlicenseNot gradedqualityDmaintenanceEnables MCP clients to speak by running local voice models using Chatterbox Turbo TTS or Kokoro TTS, with support for voice cloning, paralinguistic tags, and multiple voices.71 npm13MIT
- AlicenseNot gradedqualityBmaintenanceProvides local speech-to-text and text-to-speech through MCP and HTTP, enabling transcription, voice output, and standalone voice workflows without a gateway.MIT
- AlicenseNot gradedqualityAmaintenanceEnables MCP-compatible clients to generate images and videos, synthesize speech, clone voices, and design custom voices through integrated AI APIs, with configurable output modes and local or cloud transports.493 npmMIT