Voice I/O MCP for AI coding agents — local TTS + STT, 2 tools (`voice_speak`, `voice_ask`) with ToolAnnotations
Overview
Your AI agent can't hear you and respond to you. VoiceLayer gives it ears and a voice. Press F5, speak to Claude Code, get on-device transcription in under 1.5 seconds. Your AI speaks back. Works with any MCP client. On a mouse with side buttons, button 5 (forward) works like F5 and button 4 (back) presses Return. Select text in any app and press to read it aloud; press it again to stop. re-pastes the last transcript. Option+F5 is ignored during dictation or transcription. Secure fields are never read. If a safe clipboard backup is unavailable, the shortcut asks you to retry and leaves the clipboard intact. No cloud APIs, no API keys, no data leaves your machine. — the tap ships the CLI/MCP package and the notarized notch app: Install the cask too — the formula alone gives you the CLI/MCP but no notch UI. Speech goes through the running VoiceLayer daemon, sharing Stop and the teleprompter.
README
VoiceLayer
Your AI agent can’t hear you and respond to you. VoiceLayer gives it ears and a voice.
Voice I/O for AI coding assistants. Press F5, speak to Claude Code, get on-device transcription in under 1.5 seconds. Your AI speaks back. Works with any MCP client.
On a mouse with side buttons, button 5 (forward) works like F5 and button 4 (back) presses Return.
Select text in any app and press Option+F5 to read it aloud; press it again to stop. Shift+F5 re-pastes the last transcript. Option+F5 is ignored during dictation or transcription. Secure fields are never read. If a safe clipboard backup is unavailable, the shortcut asks you to retry and leaves the clipboard intact.
You ──🎤──> whisper.cpp ──> Claude Code ──> edge-tts ──🔊──> You
STT (local) MCP tools TTS (free)
Local-first. Free. Open-source. No cloud APIs, no API keys, no data leaves your machine.
Install
macOS (recommended) — the tap ships the CLI/MCP package and the notarized notch app:
brew tap etanhey/layers
brew install etanhey/layers/voicelayer # CLI + MCP server
brew install --cask etanhey/layers/voicebar # VoiceBar notch app (owns the mic)
voicelayer setup # one-time runtime setup
Install the cask too — the formula alone gives you the CLI/MCP but no notch UI.
npm — if you only want the MCP server:
bun add -g voicelayer-mcp # or: npm i -g voicelayer-mcp
brew install sox socat && pip3 install edge-tts
brew install whisper-cpp # optional, for local STT
# whisper model (~1.5 GB) — needed for local STT
mkdir -p ~/.cache/whisper && curl -L -o ~/.cache/whisper/ggml-large-v3-turbo.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin
Speak from the terminal
voicelayer speak "Hello"
echo "Text to read" | voicelayer speak
voicelayer speak - --markdown
voicelayer speak --file notes.md --profile long --wait
voicelayer speak --stop
Speech goes through the running VoiceLayer daemon, sharing Stop and the teleprompter.
With the daemon, the command returns after the first audio starts; --wait waits for completion.
--profile auto is the default; short and long select the corresponding profile.
Auto selects the saved long profile above short_limit_chars and the short profile at or below
the threshold (default: 400 characters). --profile short|long overrides that choice.
Markdown conversion defaults on for .md files; literal text and stdin are plain unless
--markdown is supplied. Long reads stream chunks without the MCP tool’s text cap,
up to the shared 200,000-character safety limit.
If the daemon is unavailable, the CLI reports it on stderr and runs the same streaming
engine in the foreground, waiting for completion even without --wait. Ctrl-C stops
local synthesis/playback and waits for owned children to exit. Local fallback has no
teleprompter; --stop requires the daemon. Authentication, busy, synthesis and playback
failures return a nonzero exit code. Failures after an async daemon command has returned
are reported by the daemon;
use --wait when the final exit status matters. An older running daemon must be
updated/restarted to support this command.
Speech credentials resolve in this order: VOICELAYER_DAEMON_SECRET_PATH, isolated
VOICELAYER_STATE_DIR, an MCP socket override, VOICELAYER_TTS_DAEMON_SECRET_FILE,
VOICELAYER_TTS_AUTH_TOKEN_FILE, then ~/.voicelayer/daemon.secret. Isolation paths take
precedence over inherited TTS aliases. Secret files must be regular, nonempty, non-symlink
files with mode 0600.
Point your MCP client at the daemon
VoiceLayer runs as one persistent daemon on a Unix socket; every session connects through a
lightweight socat shim instead of spawning its own process. Add to .mcp.json:
{
"mcpServers": {
"voicelayer": {
"command": "socat",
"args": ["STDIO", "UNIX-CONNECT:/tmp/voicelayer-mcp.sock"]
}
}
}
Or migrate every repo at once: bash scripts/migrate-to-daemon.sh (--dry-run to preview).
On macOS, grant your terminal microphone access (System Settings → Privacy → Microphone).
Updates, kill-switches, and cross-machine setup: docs/install-and-update.md.
The two tools
| Tool | Behavior | Blocking |
|---|---|---|
voice_speak |
TTS with auto-mode (announce/brief/consult/think), replay, toggle | No |
voice_ask |
Speak a question, record the mic, transcribe the answer | Yes |
Both ship full MCP ToolAnnotations.
Neither is destructive; both set openWorldHint: false.
Daemon speech profiles, env overrides, and socket controls: docs/tts-settings.md.
How voice_ask works: waits for any playing audio to finish → speaks the question via
edge-tts → records the mic and resamples to 16kHz → Silero VAD detects when you stop talking →
whisper.cpp transcribes locally (~200-400ms on Apple Silicon) → returns the text to your agent.
Full tool parameters: docs/tools-reference.md.
VoiceBar — the notch surface (macOS)
The canonical UI (SwiftUI + AppKit). It tucks around the MacBook camera housing instead of floating over your work:
- Liquid-Glass wings flank the camera housing, with a graceful fallback on older macOS.
- Teleprompter with word-by-word karaoke highlighting as your agent speaks.
- Idle-hover to summon — collapsed it draws no pixels; hovering reveals the mic, History and Settings.
- Settings — General · Models · Dictionary · History. Open with ⌘, or right-click → Settings…,
or from a script:
open voicebar://settings/models. - Morph animations between idle ↔ recording ↔ speaking, Reduce-Motion aware.
STT backends
| Backend | Type | Latency | Setup |
|---|---|---|---|
| whisper.cpp | Local (default) | ~200-400ms | brew install whisper-cpp + model |
| Wispr Flow | Cloud (fallback) | ~500ms + network | Set QA_VOICE_WISPR_KEY |
Auto-detected. Override with QA_VOICE_STT_BACKEND=whisper|wispr|auto.
Platform support
| Platform | TTS | STT | Recording | VoiceBar |
|---|---|---|---|---|
| macOS | edge-tts + afplay | whisper.cpp (CoreML) | sox | SwiftUI app |
| Linux | edge-tts + mpv/ffplay | whisper.cpp | sox | — |
Part of Golems
| Server | What it does | Tools |
|---|---|---|
| BrainLayer | Persistent memory — knowledge graph + hybrid search | 12 |
| VoiceLayer | Voice I/O — local STT, neural TTS, notch VoiceBar, F5 recording | 2 |
| cmuxLayer | Terminal orchestration — spawn panes, read screens, coordinate agents | 22 |
Pair with BrainLayer to remember voice conversations across sessions.
More
- Architecture — why one daemon instead of a process per session
- Configuration — environment variables and test commands
- Contributing
License
Install
This server does not publish a one-line install command.
Open the repository installation guideConfiguration
{
"mcpServers": {
"voicelayer": {
"command": "socat",
"args": ["STDIO", "UNIX-CONNECT:/tmp/voicelayer-mcp.sock"]
}
}
}