claude-voice-mcp
Click on "Install 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., "@claude-voice-mcpEnable hands-free mode and start listening."
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.
claude-voice-mcp
Bidirectional local voice for Claude Code on Apple Silicon, built on
mlx-audio. Talk to Claude, and Claude
talks back — automatically, guaranteed by a Claude Code Stop hook rather
than by Claude remembering to call a speak() tool. Runs 100% locally and
free by default (Whisper + Kokoro), with an optional ElevenLabs backend for
more realistic voices.
Contents: Two ways to use this · Commands · Why a Stop hook · Setup · Scope · Configuration · Architecture
Two ways to use this
Option 1 — Claude Code's native dictation + /talkback for replies.
Claude Code has its own built-in push-to-talk dictation (tap Space in the
chat box) that types your speech into the input box — that's a separate
system from this project, not something we built. Use it for input, and run
/talkback on so this MCP speaks Claude's replies back via Kokoro. Our own
mic/STT pipeline (listen, /talk) is never used in this mode — only the TTS
half. Simplest option if you're happy with Claude Code's own dictation and
just want spoken replies on top of it.
Option 2 — /talk for a fully local, hands-free conversation.
/talk arms hands_free mode and starts recording through our own local
pipeline (Whisper in, Kokoro out): it records until you stop talking,
transcribes it, Claude responds, the Stop hook speaks the reply, then it
automatically starts recording again — a continuous loop with no typing and
no dictation button, until you say "stop listening", go quiet past
hands_free_idle_seconds, or run /talk off. Entirely local end-to-end.
/talkonly arms listening. If you've ever turned spoken replies off with/talkback off,/talkalone won't bring them back — run/talkback ontoo, or you'll be transcribed and continued but never hear a reply. Both default to on, so a fresh install gets the full experience automatically.
The two options mix freely — e.g. native dictation most of the time, /talk
when you want your hands off the keyboard.
Related MCP server: Voice Loop MCP
Commands
Command | Does |
| Toggles |
| Arms |
| Disarms |
| One-shot timed recording; doesn't touch |
| Toggles |
| Sets |
| Speaks the entire reply, no truncation |
| Speaks a short summary only, truncated to |
| Lists all 54 voices, grouped by language |
| Switches to that voice (e.g. |
| Teach Whisper a word/name it tends to mishear (app names, jargon, rare terms) |
| Remove a word from the taught vocabulary |
| Show the current taught vocabulary |
Say "stop listening" any time to end hands-free mode by voice instead of typing /talk off.
Why a Stop hook instead of a speak() tool?
Tool-call-based auto-speak (the common approach) only works if the model
chooses to call the tool after every reply — it can forget, get distracted,
or skip it under load. This project instead wires a Stop hook
(hooks/speak_on_stop.py) that Claude Code invokes after every turn,
independent of the MCP server and independent of Claude's cooperation. It
reads Claude's own final message for the turn, strips code/markdown/paths,
and speaks it (a short summary by default, or the whole thing with
/talkback full). Everything about this is tunable live via the
voice_config MCP tool or a config file, no restart required.
The same hook is also what makes hands-free mode work: when armed, it listens
again after speaking and feeds what you say back in via its decision: "block" output, so Claude Code continues the conversation without you
retyping anything.
Other capabilities
stop_speaking()— barge-in: interrupt playback mid-sentence.list_voices()— same as/voice, callable directly.voice_config()— get/set any setting live from Claude's console (see Configuration), persisted to~/.claude-voice-mcp/config.json(or a project-local.voice-mcp.json).vocabulary()//vocab— teach Whisper words it mishears (app names, jargon, rare terms), two layers deep: words are fed to it as aninitial_prompton every transcription (a standard Whisper biasing technique), and a fuzzy-correction pass (vocab_correct.py) catches near-misses the prompt alone didn't fix (e.g. "bido app" heard for "bedouapp") and swaps in the exact taught spelling. Neither layer is a hard guarantee, but together they measurably help with made-up names and jargon Whisper otherwise guesses wrong.Hallucination guard (
stt_guard.py) — Whisper occasionally hallucinates a repeating phrase from silence/noise (a known failure mode). Detected and trimmed automatically before it reaches the conversation.Echo guard (
stt_guard.is_echo_of) — in hands-free mode, the mic can pick up Claude's own TTS reply through the speakers and transcribe it back as if it were new user input, which without a check would let Claude reply to its own echo indefinitely. The hook compares what was just spoken against what the mic just heard and silently discards a match; a short settle delay before re-listening reduces how often this happens at all.Duplicate-hook guard — if the Stop hook ends up registered in more than one scope at once (e.g. both this project's
.claude/settings.jsonand a global~/.claude/settings.json, which both fire when working inside this repo), Claude Code runs every registered copy, and Claude would audibly speak the same reply twice. The hook atomically claims each turn'sprompt_idso only the first invocation for a given turn does anything; every duplicate silently no-ops.Warm-model daemon — the Stop hook is a fresh process every turn; without this it would reload Kokoro/Whisper from scratch each time (5+ seconds).
server.pykeeps a background daemon with both models warm so the hook stays fast.Optional ElevenLabs backend for more realistic voices: set
ELEVENLABS_API_KEYandvoice_config set tts_backend elevenlabs. If the key is missing or a call fails for any reason, it silently falls back to local Kokoro — voice never breaks because of the cloud.
Requirements
Apple Silicon Mac (M1 or later), macOS
Python 3.11+, uv
Working microphone and speakers
ffmpeg(optional, only needed for MP3/FLAC handling)
Setup on a new machine
Clone this repo somewhere permanent (its path gets baked into config below, so pick a final location, e.g.
~/tools/claude-voice-mcp):git clone git@github.com:Amaldeep98/Claude-realtime-voice-mcp.git cd Claude-realtime-voice-mcpRun setup:
./scripts/setup.shInstalls
uvif missing (via~/.local/bin), pins Python 3.12 (spaCy, one of Kokoro's text-processing dependencies, doesn't yet have wheels for newer Pythons), syncs the environment, and pre-downloads the default models (~2-3GB): Kokoro-82M (TTS) and Whisper large-v3-turbo (STT).The Stop hook is already configured — this repo ships its own
.claude/settings.jsonwith the hook wired up using Claude Code's${CLAUDE_PROJECT_DIR}placeholder, which resolves to wherever you cloned this repo, so nothing needs editing:{ "hooks": { "Stop": [ { "hooks": [ { "type": "command", "command": "uv --project ${CLAUDE_PROJECT_DIR} run python ${CLAUDE_PROJECT_DIR}/hooks/speak_on_stop.py", "timeout": 120 } ] } ] } }The 120s timeout matters: the hook speaks and then listens in hands-free mode, which can legitimately take over a minute — a shorter timeout silently kills it mid-listen with no error shown. If you start Claude Code fresh from a directory that already has this file (i.e. you
cd'd into the clone before launchingclaude), it's picked up automatically; if you were already mid-session when the clone appeared, run/hooksonce to reload.${CLAUDE_PROJECT_DIR}only resolves correctly for this project, though — if you register the hook globally instead (see Scope below), it needs a real absolute path, since a global hook fires from inside whatever project you're currently in, not from this one.Register the MCP server so Claude Code can see the
listen/speak/etc. tools — see Scope below for project-only vs. everywhere.
Scope: project-only vs. available everywhere
Three independent pieces, each defaulting to this project only, each with an "everywhere" option:
Piece | Default (project-only) | Make it global |
Voice settings (voice, speed, auto_speak, hands_free, ...) | Already global: | N/A — already global. Add a |
MCP server (the tools themselves) | This repo's |
|
Slash commands ( | This repo's | Copy the three |
Stop hook (auto-speak / hands-free) | This repo's | Put the same |
For everywhere-by-default, do the "global" option for all three of MCP
server, slash commands, and Stop hook. To opt in per-project instead, add
matching .mcp.json + .claude/commands/ + .claude/settings.json entries
to each project you want it in — e.g. for another project's .mcp.json:
{
"mcpServers": {
"voice": {
"type": "stdio",
"command": "uv",
"args": ["--directory", "/path/to/claude-voice-mcp", "run", "server.py"]
}
}
}Configuration
All settings live in ~/.claude-voice-mcp/config.json and can be changed
live via the voice_config MCP tool (voice_config(action="set", key="...", value="...")) — no restart required.
Key | Default | Meaning |
|
| Speak replies automatically via the Stop hook |
|
|
|
|
| Character cap for |
|
| Whether the Stop hook re-listens after speaking (armed by |
|
| How long hands-free waits for you to start talking before giving up |
|
| Trailing silence needed to end a recording once you've started talking |
|
|
|
|
| Kokoro voice ID — see |
|
| Voice ID to use when |
|
| Playback speed multiplier |
|
|
|
|
| Language code ( |
|
| Custom words/names Whisper is biased toward (see |
|
| Chime when listening starts/stops |
|
| macOS banner notifications for listening/speaking state |
Architecture
voice_mcp/
config.py # shared config, read by both the MCP server and the standalone hook
audio_io.py # mic capture + VAD, playback, cue tones, macOS notifications
sanitize.py # strip markdown/code/urls/paths before any TTS call
summarizer.py # turn a raw assistant turn into a short spoken summary
stt_guard.py # detect/trim Whisper hallucination (repeat loops) on noise/silence
vocab_correct.py # fuzzy-correct near-misses of taught vocabulary words (see /vocab)
stt/ # whisper_backend.py (default), voxtral_backend.py (opt-in)
tts/ # kokoro_backend.py (default), elevenlabs_backend.py (optional)
tools.py # tool implementations shared by server.py, the daemon, and the hook's fallback
daemon.py # background Unix-socket server (in server.py's process) keeping models warm
ipc_client.py # lightweight client the hook uses to reach the daemon, no heavy imports
server.py # FastMCP entrypoint: listen, speak, stop_speaking, list_voices, voice_config;
# also starts the daemon in a background thread
hooks/speak_on_stop.py # Stop hook: guaranteed auto-speak + hands-free, independent of the MCP server
# (talks to the daemon for speed, falls back to loading models directly)This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceEnables voice-based interactions with Claude by converting text to speech using Kokoro TTS and transcribing user responses using NVIDIA NeMo ASR, creating interactive voice dialogues.MIT
- Alicense-qualityDmaintenanceEnables hands-free voice conversations with Claude using real-time speech recognition and text-to-speech on macOS. Creates a self-sustaining conversation loop where Claude can autonomously listen, respond, and continue the interaction without keyboard input.MIT
- Flicense-qualityDmaintenanceEnables voice interaction with Claude Code through local speech-to-text (Whisper) and text-to-speech (Supertonic), allowing verbal input/output without external API calls.1
- Alicense-qualityDmaintenanceEnables bidirectional voice interaction for Claude Code using local speech-to-text and text-to-speech models optimized for Apple Silicon. It provides tools to listen to user speech via microphone and speak responses aloud through system speakers.16Apache 2.0
Related MCP Connectors
Let ChatGPT, Claude & Cursor use your Mac: email, calendar, iMessage, Teams, files. Local, free.
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/Amaldeep98/Claude-realtime-voice-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server