voice-for-agent
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., "@voice-for-agentspeak this summary aloud: deployment completed successfully"
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.
voice-for-agent
Output-only text-to-speech for AI agents. The agent writes text; this tool cleans it, speaks it, and gets out of the way. There is no microphone, no speech-to-text, and no realtime duplex chat.
Primary engine:
edge-tts(online, natural voices).Offline fallback:
piperwith a local voice model.Playback:
mpv, thenffplay, thenpaplay/aplay.Interfaces: a small CLI and an MCP stdio server.
No API keys, GPU, paid service, or cloud account.
Requirements
Linux with working audio output. Tested on Debian/Kali-style Linux and WSL.
Python 3.10–3.13. Python 3.14 is not supported by the pinned piper/onnxruntime stack.
One playback program:
mpv(preferred),ffplay(from FFmpeg),paplay, oraplay.Network access for the first install and for
edge-tts. The piper fallback works offline after the voice model is installed.
install.sh never runs sudo. If a system package is missing, it prints the
apt command to run yourself.
Related MCP server: Voice MCP Server
Quick start
cd /path/to/voice-for-agent
bash install.sh
./.venv/bin/python speak.py "Build finished. All tests passed."bash install.sh creates .venv, installs the pinned Python packages,
downloads the default piper voice, and runs the smoke test. It is safe to run
again.
Stop current speech and clear the queue:
./.venv/bin/python speak.py stopSpeak in the background and return immediately:
./.venv/bin/python speak.py --async "Build finished. All tests passed."Menu and single entry point
If you do not want to remember individual commands, use menu.sh:
bash menu.shThat opens a numbered menu for install, speak, stop, status, voices, tests, config, and uninstall.
The same script works non-interactively, which is what agents should use:
bash menu.sh install
bash menu.sh speak "Build finished. All tests passed."
bash menu.sh async "Build finished. All tests passed."
bash menu.sh stop
bash menu.sh status
bash menu.sh voices
bash menu.sh test
bash menu.sh config
bash menu.sh uninstallRun bash menu.sh help for the full list.
Use as an agent skill
This repository is also a portable agent skill. Give an agent the repository
URL and tell it to read SKILL.md:
https://github.com/rishb0/voice-for-agentA folder URL such as /tree/main should be converted to the repository URL
ending in .git for cloning. If you fork this repository, replace rishb0 with
your own GitHub account or organization.
The skill tells the agent to install into:
${XDG_DATA_HOME:-$HOME/.local/share}/voice-for-agentManual agent install:
TARGET="${XDG_DATA_HOME:-$HOME/.local/share}/voice-for-agent"
if [ -d "$TARGET/.git" ]; then
git -C "$TARGET" pull --ff-only
else
git clone --depth 1 https://github.com/rishb0/voice-for-agent.git "$TARGET"
fi
cd "$TARGET"
bash install.sh
bash menu.sh statusOne-command bootstrap:
bash bootstrap.sh --repo https://github.com/rishb0/voice-for-agent.gitRegister the MCP server globally in OpenCode:
TARGET="${XDG_DATA_HOME:-$HOME/.local/share}/voice-for-agent"
opencode mcp add voice-for-agent --global -- \
"$TARGET/.venv/bin/python" "$TARGET/mcp_server.py"Or let the bootstrap do it:
bash bootstrap.sh \
--repo https://github.com/rishb0/voice-for-agent.git \
--register-opencodeFrom a raw URL:
curl -fsSL https://raw.githubusercontent.com/rishb0/voice-for-agent/main/bootstrap.sh \
| bash -s -- --repo https://github.com/rishb0/voice-for-agent.git --register-opencodeOpenCode automatically discovers the project skill at
.opencode/skills/voice-for-agent/SKILL.md when working inside this repository.
For other agents, point them at SKILL.md or AGENT_GUIDE.md.
How to read this repository
Path | What it is |
| Single entry point: interactive menu and |
| Clone or update from a Git URL, install, and optionally register OpenCode globally. |
| Portable agent-skill entry point for any agent that receives this repository URL. |
| OpenCode-discoverable skill definition. |
| CLI, text cleaner, chunker, synthesis, playback, queue, and stop logic. |
| Thin FastMCP stdio wrapper exposing |
| Idempotent setup and self-test. Does not use |
| Removes generated files, voices, and local config without touching source. |
| Pinned Python dependencies. |
| Example local configuration. |
| Pasteable rules that tell an agent when and how to speak. |
| Operations guide for any agent: install, remove, status, test, config, and safety. |
| Registration snippets for OpenCode, Claude Code, and Gemini CLI. |
| End-to-end tests for edge-tts, piper, text cleaning, MCP tools, and playback. |
| Public-repo CI: syntax checks and a text-cleaner smoke test. |
| MIT License for this project. |
| Dependency and voice-model license notes. |
| Generated locally and ignored by git. |
What install.sh does and where files go
bash install.sh performs these steps:
Finds a supported Python 3.10–3.13 and checks
python3-venv.Checks for an audio player:
mpv,ffplay,paplay, oraplay.Creates a local
.venv/if needed.Installs the pinned packages from
requirements.txtinto.venv/.Reads
piper_voicefromconfig.jsonif present; otherwise usesen_US-ljspeech-high.Downloads the piper
.onnxmodel and.onnx.jsonconfig intovoices/.Runs the five smoke tests.
Exits non-zero if a required step fails.
It does not run sudo, install system packages, change the system Python,
create a service, add a startup entry, or install anything globally. If a system
package is missing, it prints the apt command for you to run.
Everything persistent stays inside the install folder. The default bootstrap
install folder is ${XDG_DATA_HOME:-$HOME/.local/share}/voice-for-agent.
Path | Approximate size | Purpose |
| 284 MB | Local Python environment and packages. |
| 109 MB for the default voice | Downloaded piper model and config. |
| small | Locks, generation counter, async log. |
| small | Temporary audio, deleted after playback. |
| small | Optional local configuration. |
| small | Python bytecode, safe to delete. |
Pip caching is disabled with --no-cache-dir, so the install does not keep a
persistent package cache in ~/.cache/pip. Pip and the voice download may still
use temporary files under /tmp while running. The project does not write to
/usr, /opt, a system service directory, or other home-directory locations
outside the install folder.
To see the current sizes:
du -sh .venv voices .run .tmp 2>/dev/nullPlatform support
Linux: supported.
WSL: supported; audio depends on the WSL audio setup.
macOS: not supported by the current installer or player list. The Python code uses Unix features, but
install.shis Debian/apt-specific and there is noafplaysupport yet.Native Windows: not supported.
speak.pyusesfcntland Unix process groups for queueing and stop. Use WSL instead.
CLI usage
Speak text
./.venv/bin/python speak.py "Deployment finished. Two tests failed."The default engine is edge. If edge-tts fails (for example, no network), the
tool logs one line and falls back to piper automatically.
Read from a file or stdin
./.venv/bin/python speak.py --file notes.md
./.venv/bin/python speak.py --file - < notes.md
cat notes.md | ./.venv/bin/python speak.pyClean text without speaking
./.venv/bin/python speak.py --clean-only --file notes.mdThe cleaner removes fenced code blocks, markdown marks, URLs, file paths, hashes, tables, emoji, and ANSI escapes. It keeps the readable words.
Synthesize to a file instead of playing
./.venv/bin/python speak.py --engine edge --output speech.mp3 "Hello."
./.venv/bin/python speak.py --engine piper --output speech.wav "Hello."The output container follows the engine: edge writes MP3, piper writes WAV. If
you pass a different extension, it is corrected and the actual path is printed.
If edge-tts falls back to piper, the actual .wav path is printed.
List available voices
./.venv/bin/python speak.py --list-voicesThis lists edge-tts voices when online and every installed piper model in
voices/. The default piper voice is marked default.
Choose an engine, voice, or rate
./.venv/bin/python speak.py --engine piper --piper-voice en_US-ljspeech-high "Offline speech."
./.venv/bin/python speak.py --engine edge --voice en-US-AriaNeural --rate +10% "Faster speech."
./.venv/bin/python speak.py --rate -5% "Slower speech."--voice selects an edge-tts voice. --piper-voice selects an installed piper
model by its file stem. --rate accepts values such as +10%, -5%, or 0%.
CLI options
Option | Meaning |
| Text to speak. |
| Read text from a file. Use |
| Queue speech and return immediately. |
| Force one synthesis engine. |
| edge-tts voice name. |
| Installed piper voice name (file stem). |
| Speech rate adjustment. |
| Maximum characters spoken before "the rest is on screen". |
| Synthesize to a file instead of playing. |
| Print cleaned text and exit. |
| List edge-tts and installed piper voices. |
| Stop current speech and invalidate every queued job. |
Uninstall
Preview what will be removed:
bash uninstall.sh --dry-runRemove generated files with a confirmation prompt:
bash uninstall.shRemove without prompting, for an agent after the user confirms:
bash uninstall.sh --yesKeep downloaded voices and/or local config:
bash uninstall.sh --yes --keep-voices --keep-configuninstall.sh removes .venv/, voices/, .run/, .tmp/, config.json,
__pycache__/, and *.pyc. It never removes source files, documentation,
examples, tests, LICENSE, or THIRD_PARTY_NOTICES.md.
Configuration
Copy the example and edit it:
cp config.example.json config.json{
"engine": "edge",
"voice": "en-US-AriaNeural",
"piper_voice": "en_US-ljspeech-high",
"rate": "+0%",
"max_spoken_chars": 1200
}Precedence is: command-line option, then config.json, then built-in defaults.
config.json is ignored by git.
piper_voice is the stem of an .onnx file in voices/. The installer reads
this value and downloads that voice if it is missing. To add a voice later:
./.venv/bin/python -m piper.download_voices en_US-ljspeech-high --data-dir voicesCheck the voice's MODEL_CARD before using it commercially. Several Piper
voices have non-commercial or research-only terms.
MCP server
The MCP server exposes two tools:
speak(text)— queue a short spoken summary and return"queued"immediately.stop_speaking()— stop current speech and clear every queued job.
The server speaks with the same config.json as the CLI. It uses stdio, so it
does not open a network port.
OpenCode
From this folder:
opencode mcp add voice-for-agent -- \
"$PWD/.venv/bin/python" "$PWD/mcp_server.py"Or use the manual V2 configuration in examples/opencode.jsonc:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"servers": {
"voice-for-agent": {
"type": "local",
"command": [
"/ABSOLUTE/PATH/TO/voice-for-agent/.venv/bin/python",
"/ABSOLUTE/PATH/TO/voice-for-agent/mcp_server.py"
],
"codemode": false
}
}
}
}Claude Code
claude mcp add --scope user voice-for-agent -- \
"$PWD/.venv/bin/python" "$PWD/mcp_server.py"The same command is in examples/claude-code.sh.
Gemini CLI
Use the mcpServers block in examples/gemini-settings.json. Replace
/ABSOLUTE/PATH/TO/voice-for-agent with this folder's absolute path.
Tool names
The server name is voice-for-agent. Some clients prefix tool names, so the
tools may appear as voice-for-agent_speak and
voice-for-agent_stop_speaking. The underlying names are speak and
stop_speaking.
Agent rules
AGENTS.md contains the speaking policy. AGENT_GUIDE.md contains the
operations policy: install, uninstall, status, tests, config, and safety. Paste
AGENTS.md into the rules file of the agent you use, after registering the MCP
server. Tell the agent to read AGENT_GUIDE.md before running install, remove,
or repair commands.
AGENTS.md tells the agent to:
call
speakonce after finishing a task or answer;keep the spoken summary to 2–4 plain sentences;
avoid reading code, commands, paths, or long lists aloud;
call
stop_speakingwhen the user says "stop talking" or "mute".
The full answer stays on screen. Only the short summary is spoken.
How it works
Read text from arguments, a file, or stdin.
Clean markdown, URLs, code blocks, paths, hashes, tables, and emoji.
Limit the spoken text to
max_spoken_charsand append "The rest is on screen."Split the result into chunks of about 200 characters.
Synthesize each chunk with edge-tts, or piper after an edge failure.
Play the chunk through the first available player.
Delete the temporary audio and release the queue.
Speech jobs are serialized with flock, so two agents do not talk over each
other. stop increments a generation counter and kills the current worker and
player process group; queued workers see the new generation and exit without
speaking.
Runtime state lives in .run/. Temporary audio lives in .tmp/. Both are
ignored by git.
Tests
bash tests/smoke_test.shOr use the menu entry point:
bash menu.sh testThe smoke test checks:
edge-tts produces audio (requires network);
piper produces audio offline;
the text cleaner removes markdown, URLs, code, paths, hashes, tables, and emoji;
the MCP server starts and lists
speakandstop_speaking;real playback works, or an audio-file fallback passes when no audio device is available.
install.sh runs the same test at the end.
Troubleshooting
Start with:
bash menu.sh statusedge-tts failed, falling back to piper — edge-tts needs network access.
Piper still works offline. To force local speech, use --engine piper.
piper voice model missing — the selected piper_voice is not installed.
Run bash install.sh, or download it with
./.venv/bin/python -m piper.download_voices NAME --data-dir voices.
no audio player found — install mpv or FFmpeg:
sudo apt update && sudo apt install -y mpv ffmpegplayback failed — the player exists but cannot reach an audio device.
Check your desktop audio, PipeWire/PulseAudio, or WSL audio setup. ffplay is a
useful diagnostic because it prints errors when run manually.
No sound but no error — synthesize a file and play it with your normal audio player:
./.venv/bin/python speak.py --engine piper --output test.wav "test"nothing to speak — the input was empty, or the cleaner removed everything
(code blocks and URLs only). Check with --clean-only.
MCP client does not show the tools — use absolute paths to
.venv/bin/python and mcp_server.py, then run the command manually to see
startup errors. The server must run from an environment where mcp is installed.
install.sh cannot find a supported Python — install Python 3.11 or 3.12
and python3-venv. Python 3.14 is intentionally rejected by the piper stack.
A queued job will not stop — run ./.venv/bin/python speak.py stop. If a
stale process remains, inspect it with ps -ef | grep speak.py before killing
anything.
Privacy and security
edge-tts sends the text to Microsoft. Do not send secrets or private data through the edge engine.
piper runs locally. Use
--engine piperwhen the text must stay on the machine.There are no API keys, accounts, telemetry, or network listeners.
The MCP server uses stdio only.
Text is passed to subprocesses as argument lists, not through a shell.
--filereads any path the current user can read; treat it like any other file-reading CLI.Async fallback errors go to
.run/speak.log. Temporary audio is deleted after each chunk and bystop.
Limits
Output only: no microphone, no speech-to-text, no realtime duplex chat.
edge-tts needs internet; piper is offline but less expressive.
Long text is truncated for speech, not summarized. The agent's full answer stays on screen.
Speech is serialized. A second job waits for the first unless you call
stop.One piper voice is installed by default. Add more with the download command.
No native Windows or macOS installer is included. WSL/Linux is the tested path.
Voice models and licensing
The default piper voice is en_US-ljspeech-high:
trained from scratch on the LJ Speech dataset;
dataset license: public domain;
model card: https://huggingface.co/rhasspy/piper-voices/raw/main/en/en_US/ljspeech/high/MODEL_CARD.
The model files are downloaded by install.sh and are ignored by git. They are
not part of this repository.
Piper voice licensing is inconsistent. Many English voices are fine-tuned from
the Lessac voice and carry research-only or non-commercial terms. The older
en_US-lessac-medium voice, for example, uses the Blizzard 2013 research
license and is not suitable for commercial use. Check the MODEL_CARD of any
voice you redistribute or use commercially.
This project's own code is licensed under the MIT License. It uses
third-party dependencies under their own terms: edge-tts is LGPL-3.0,
piper-tts is GPL-3.0-or-later, and mcp and onnxruntime are MIT. See
LICENSE and THIRD_PARTY_NOTICES.md.
If you redistribute a combined package that includes piper-tts, follow the
GPL-3.0-or-later terms for that combined distribution.
Repository hygiene
The repository is set up so generated and private files are not committed:
.venv/— local Python environment;voices/*.onnxandvoices/*.onnx.json— downloaded voice models;.run/and.tmp/— runtime state and temporary audio;config.json— local configuration;__pycache__/,*.pyc, audio files, and logs.
Before publishing, run git status and confirm none of those appear. The
example registration files use /ABSOLUTE/PATH/TO/voice-for-agent placeholders;
replace them with your own absolute path locally, but do not commit machine-
specific paths.
Publish to GitHub
Create an empty public repository named voice-for-agent on GitHub. From a
fresh copy of this folder:
git init
git add .
git commit -m "Initial public release"
git branch -M main
git remote add origin https://github.com/rishb0/voice-for-agent.git
git push -u origin mainBefore committing, confirm git status does not show:
.venv/voices/*.onnx.run/.tmp/config.json
The documentation already uses rishb0 as the publishing account. If you push
to a different account or organization, replace rishb0 in README.md,
SKILL.md, AGENT_GUIDE.md, bootstrap.sh, and the .opencode skill. Set the
GitHub repository visibility to public, enable Issues, and add topics such as
text-to-speech, tts, mcp, opencode, piper, and edge-tts.
The included GitHub Actions workflow runs syntax checks and a text-cleaner smoke test on every push and pull request. It does not need network, audio hardware, or the piper voice model.
This server cannot be deployed
Maintenance
Related MCP Connectors
Audio for your agent: transcribe, speak, translate, summarise, plus sound effects and music.
Text to speech for your AI. Your AI can send text to Doc Player to read it aloud. You will see a reader window with the text and you can control the playback sentence by sentence. Find an example here: https://documentplayer.com/connect-ai/
Let cloud agents talk to you: progress updates spoken on your Mac, and replies you send back.
Ask other AI models and generate images, speech, music and video from your coding agent.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to synthesize natural speech using either platform system voices or premium OpenAI TTS, with automatic engine selection and graceful fallback.112 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to speak aloud by generating and playing audio through the system output. Supports multiple TTS providers, playback queue management, and configurable voice profiles.2 npm1MIT
- AlicenseAqualityBmaintenanceEnables an AI assistant to have its recent code actions summarized aloud through system speakers, using offline native voices or cloud neural voices. It supports asynchronous playback and voice listing so users can hear what the agent did without reading the full response.335 PyPIMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to give spoken output by synthesizing text into speech with an on-device neural model and playing it through the user's speakers, entirely offline. Agents can queue spoken summaries and stop playback on demand.1 npmMIT