Profile-driven MCP server for Google Cloud Text-to-Speech
Project description
tts-mcp
Profile-driven MCP server for Google Cloud Text-to-Speech: define one profile per app/client so each tool always speaks with the right voice and settings.
Exposes three tools to any MCP client:
tts_speak— synthesize text to audio and auto-play ittts_doctor— run diagnostics on auth, profile, and playbacktts_stop— stop any currently playing audio
Voice, language, model, and format are locked per profile — the LLM can only control text content, speaking rate, and pitch.
Install
pip install tts-mcp
Or with uvx (no install needed):
uvx tts-mcp --help
Prerequisites
- Python 3.11+
- A Google Cloud project with the Cloud Text-to-Speech API enabled
- Google offers a generous free tier — up to 4 million characters/month for Standard and WaveNet voices, and 1 million characters/month for Neural2, Polyglot, Chirp 3: HD, and Studio voices, more than enough for most individual use. See TTS pricing for details.
- Google Cloud CLI (
gcloud) for authentication - macOS uses
afplayfor playback by default (configurable via profile)
Setup
1. Authenticate with Google Cloud
gcloud auth application-default login
gcloud auth application-default set-quota-project YOUR_PROJECT_ID
This stores credentials at ~/.config/gcloud/application_default_credentials.json, which the TTS client discovers automatically. No environment variables needed.
2. Create a profiles file
tts-mcp --init
This creates a starter config at ~/.config/tts-mcp/profiles.json with example profiles for every Google TTS voice tier. Edit it to pick your voice, format, and playback settings.
The server finds the profiles file automatically — no --profiles flag needed for the common case. The search order is:
--profilesflag orTTS_MCP_PROFILES_PATHenv var (explicit override)~/.config/tts-mcp/profiles.json(XDG standard — created bytts-mcp --init)
MCP client setup
After running tts-mcp --init, no --profiles flag is needed — the server finds ~/.config/tts-mcp/profiles.json automatically. Just pass --profile to select which profile each client uses.
Claude Code
claude mcp add --transport stdio --scope user \
speech -- tts-mcp --profile claude
OpenCode
Edit ~/.config/opencode/opencode.jsonc:
{
"mcp": {
"speech": {
"type": "local",
"command": ["tts-mcp", "--profile", "opencode"],
"enabled": true,
"timeout": 120000
}
}
}
Codex CLI
Edit ~/.codex/config.toml:
[mcp_servers.speech]
command = "tts-mcp"
args = ["--profile", "codex"]
Using uvx (no global install)
Any client config can use uvx instead of installing globally:
{
"command": "uvx",
"args": ["tts-mcp", "--profile", "opencode"]
}
Usage
In any MCP-enabled client, prompt naturally:
Summarize this and read it aloud. use speechStop current playback. use speech
Tool names may appear prefixed by the client (e.g. speech_tts_speak, speech_tts_stop).
CLI reference
The package installs four commands. Each supports --help for full details.
tts-mcp — MCP server and management
tts-mcp --init # create starter config at ~/.config/tts-mcp/profiles.json
tts-mcp --init --force # overwrite existing config
tts-mcp --doctor # diagnostics: auth, profile, voice, player
tts-mcp --profile casual # start MCP server with a specific profile
Defaults:
--profiles:TTS_MCP_PROFILES_PATHenv var or""(then auto-discovery runs)--profile:TTS_MCP_PROFILE_NAMEenv var or""(thendefault_profileis used)--doctor,--init,--force:false
tts-speak — synthesize text to audio
tts-speak --text "Hello world" --voice en-US-Chirp3-HD-Fenrir --format wav --out hello.wav
tts-speak --text-file notes.txt --voice en-US-Neural2-D --format mp3 --out notes.mp3
tts-speak --ssml --text "<speak>Hello <break time='500ms'/> world</speak>" --out ssml.wav
echo "Piped text" | tts-speak --voice en-US-Casual-K --out piped.ogg
Options: --text, --text-file, --voice, --language, --model, --format (mp3/ogg/wav), --speaking-rate, --pitch, --out, --usage-log.
Defaults:
--voice:""--language:en-US--model:""--format:mp3--speaking-rate:1.0--pitch:0.0--out:""(auto-generatesYYYYMMDD-HHMMSS-ms.extin the current directory, local timezone)--usage-log:usage_log.csv- input: if neither
--textnor--text-fileis provided, the CLI reads piped stdin or prompts for text
tts-voices — list available voices
tts-voices # list en-US voices (default language)
tts-voices --language en-US # filter by language
tts-voices --language en-US --family Chirp3 # filter by family
tts-voices --limit 5 # limit results
Defaults:
--language:en-US--family:""(no family filter)--limit:0(no limit)
tts-batch — generate samples for multiple voices
tts-batch --text-file test.txt --out-dir ./samples
tts-batch --text-file test.txt --families Chirp3,Neural2 --language en-US --format wav
tts-batch --text-file test.txt --limit 3 # first 3 matching voices only
Defaults:
--families:""(no family filter)--language:en-US--format:mp3--out-dir:./out--speaking-rate:1.0--pitch:0.0--limit:0(all matching voices)--text-file: required
Profile system
Profiles are defined in a JSON file (see profiles.example.json):
{
"default_profile": "opencode",
"profiles": {
"opencode": {
"voice": "en-US-Chirp3-HD-Fenrir",
"language": "en-US",
"model": "models/chirp3-hd",
"format": "wav",
"speaking_rate": 1.0,
"pitch": 0.0,
"output_dir": "~/.local/share/tts-mcp/out",
"usage_log": "~/.local/share/tts-mcp/usage_log.csv",
"autoplay": true,
"player_command": ["afplay", "{file}"]
}
}
}
Each profile locks: voice, language, model, format, output_dir, usage_log, autoplay, and player_command. Only speaking_rate and pitch can be overridden per tool call.
Troubleshooting
- Auth errors — run
gcloud auth application-default login, or confirmGOOGLE_APPLICATION_CREDENTIALSis set. - No audio — verify the player binary (e.g.
afplay) exists, or changeplayer_commandin your profile. - Tool timeout — playback is non-blocking, but if timeouts persist, increase the client's
tool_timeout. - Run diagnostics —
tts-mcp --doctorchecks auth, profile, voice, and player.
Development
git clone git@github.com:that-lucas/tts-mcp.git
cd tts-mcp
make setup # creates venv, installs package + dev deps, sets git hooks
make test # run pytest
make lint # run ruff check + format check
See CONTRIBUTING.md for details.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tts_mcp-0.1.4.tar.gz.
File metadata
- Download URL: tts_mcp-0.1.4.tar.gz
- Upload date:
- Size: 29.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da08fbbcb91273f6d8e43baad7d689dd5488341a86cba4f6a1ab3b012a786251
|
|
| MD5 |
f4f12727b0afadcfde6d37bd5c21ea80
|
|
| BLAKE2b-256 |
5d7806f02f769536db28f50663bd86826039d7fac48cf9415d1452f9e01674d3
|
Provenance
The following attestation bundles were made for tts_mcp-0.1.4.tar.gz:
Publisher:
release.yml on that-lucas/tts-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tts_mcp-0.1.4.tar.gz -
Subject digest:
da08fbbcb91273f6d8e43baad7d689dd5488341a86cba4f6a1ab3b012a786251 - Sigstore transparency entry: 947245350
- Sigstore integration time:
-
Permalink:
that-lucas/tts-mcp@2927548aa5a455d71d6f69bd762f16ff5969db56 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/that-lucas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2927548aa5a455d71d6f69bd762f16ff5969db56 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tts_mcp-0.1.4-py3-none-any.whl.
File metadata
- Download URL: tts_mcp-0.1.4-py3-none-any.whl
- Upload date:
- Size: 19.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6bf8d9507345085e2239679672ea6e1dc8c3f3a4c088ed96117367ed20b3bf8
|
|
| MD5 |
c32aeb0c39a027d579f7858adef4766e
|
|
| BLAKE2b-256 |
afbb5beef455a1fc62ea77fa5728eedbf926e541604d794f1953fd11bd3aa690
|
Provenance
The following attestation bundles were made for tts_mcp-0.1.4-py3-none-any.whl:
Publisher:
release.yml on that-lucas/tts-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tts_mcp-0.1.4-py3-none-any.whl -
Subject digest:
c6bf8d9507345085e2239679672ea6e1dc8c3f3a4c088ed96117367ed20b3bf8 - Sigstore transparency entry: 947245352
- Sigstore integration time:
-
Permalink:
that-lucas/tts-mcp@2927548aa5a455d71d6f69bd762f16ff5969db56 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/that-lucas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2927548aa5a455d71d6f69bd762f16ff5969db56 -
Trigger Event:
push
-
Statement type: