Skip to main content
Glama
README.md
# text-to-speech-mcp

A local text-to-speech [MCP](https://modelcontextprotocol.io) server for Claude and other MCP clients.

- **English** narration with [Kokoro](https://huggingface.co/hexgrad/Kokoro-82M) (optional extra).
- **Malayalam** narration with Indic Parler-TTS, IndicF5 (including voices cloned from a sample you
  have permission to use), Piper, or MMS.
- **Edit-ready output:** Malayalam comes out as 48 kHz mono WAV, loudness-normalised to −14 LUFS
  with true peak ≤ −1 dBTP, with optional MP3.
- **Malayalam text front end:** expands numbers, ₹/AED amounts, % and acronyms to words; normalises
  Unicode chillu characters; supports your own pronunciation lexicon.
- **Async job queue:** one job at a time. A job can return a `job_id` immediately so agents can poll
  for progress, which avoids tool-call timeouts on long narrations.
- **CPU/GPU detection:** picks CUDA, Apple Silicon (MPS) or CPU and **asks you to confirm**, falling
  back to CPU if the accelerator isn't usable.
- **Runs entirely on your machine.** Models download from Hugging Face on first use.

## Install

macOS (Apple Silicon or Intel) and Linux:

```bash
curl -LsSf https://raw.githubusercontent.com/imaimai86/text-to-speech-mcp/main/install.sh | bash
```

The installer:

1. checks your system (OS, CPU, free disk);
2. installs [uv](https://docs.astral.sh/uv/), ffmpeg and espeak-ng if they're missing (**asks first**);
3. installs the server (`tts-mcp`) and the setup tool (`tts-mcp-setup`);
4. detects your CPU/GPU and **asks you to confirm** which device to use;
5. offers to register the server with Claude Desktop and Claude Code, backing up their config first;
6. runs a self-test.

It's safe to re-run. Useful flags:

| Flag | Effect |
|---|---|
| `--yes` | Unattended: accept every prompt |
| `--device cpu\|mps\|cuda` | Skip detection |
| `--no-english` | Malayalam only; avoids the GPL-licensed English phonemizer |
| `--no-claude` | Don't register the server with Claude |
| `--from .` | Install from a local checkout |
| `--upgrade` | Reinstall even if already installed |

**Gated models:** Parler and IndicF5 need a Hugging Face login, plus accepting their terms on
[indic-parler-tts](https://huggingface.co/ai4bharat/indic-parler-tts) and
[IndicF5](https://huggingface.co/ai4bharat/IndicF5):

```bash
uv tool run --from huggingface_hub hf auth login
```

## Use

Restart Claude Desktop, then ask, for example:

> *Narrate this in Malayalam with indicf5, voice anas, 20 steps, and export MP3:* …

### Tools

| Tool | What it does |
|---|---|
| `narrate_malayalam` | Malayalam text to WAV/MP3. Key inputs: `engine`, `voice`, `steps` (IndicF5 16–32, default 20), `speed`, `run_async`, `overwrite`, `filename` |
| `narrate` | English (Kokoro) text to WAV/MP3. Inputs: `voice`, `speed`, `pause`, `run_async`, `overwrite` |
| `estimate_narration` | Predicted audio length and runtime; `recommend_async` |
| `get_job_status` / `wait_for_job` | Progress, ETA, `poll_after_s`, result paths |
| `list_jobs` / `cancel_job` | Manage the queue |
| `list_voices` / `list_malayalam_engines` | Voices, per-job options with ranges, licence status |

**Sync or async:** `run_async=true` validates the request and returns a `job_id` in under a second.
A synchronous call whose estimated runtime exceeds about 45 s is queued automatically and also
returns a `job_id`, so it never times out. Invalid input (unknown voice, out-of-range `steps`, a file
that already exists without `overwrite`) returns an error immediately and queues nothing.

### Your data

Everything lives in `~/tts-mcp/` (override with `TTS_MCP_HOME`):

```
config.json    device and settings (written by tts-mcp-setup configure)
output/        generated audio; output/jobs/ holds job records
voices/        saved IndicF5 voices: <name>.wav (6–12 s of clean speech) + <name>.txt (exact transcript)
lexicon.json   your pronunciation overrides
```

### Setup commands

```bash
tts-mcp-setup configure [--device auto|cpu|mps|cuda] [--yes]   # re-detect and confirm the device
tts-mcp-setup register | unregister                             # Claude Desktop / Claude Code
tts-mcp-setup doctor                                            # show config, check dependencies
tts-mcp-setup uninstall [--purge]                               # remove the tool (--purge also deletes ~/tts-mcp)
tts-mcp --self-test [--full]                                    # end-to-end check (--full also synthesises English)
```

## Performance

Measured on an Apple M1 with 16 GB RAM. RTF is synthesis time ÷ audio length; lower is faster.

| Engine | RTF |
|---|---|
| IndicF5 on MPS, 16 / 20 / 32 steps | ≈ 1.2 / 1.5 / 2.6 |
| IndicF5 on CPU, 32 steps | ≈ 7 |
| Parler (Malayalam) | ≈ 3.9 |
| MMS | ≈ 0.13 |
| Piper | ≈ 0.02 |

The job queue refines its time estimates from your machine's actual runs.

## Licences

The code is MIT. Dependencies and models have their own licences, and **not every engine is safe for
monetised content**: see [THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md). In short, Parler is
fine, IndicF5 needs review (a non-commercial runtime dependency), and Piper and MMS are not allowed.

## Development

```bash
uv sync --locked --extra dev
uv run pytest
uv run python scripts/licence_report.py --check     # licence audit of the core install
```

### Limitations

- The CUDA path is covered by unit tests with mocks; it hasn't been run on NVIDIA hardware.
- Windows isn't supported.
- Cancelling a running job takes effect after the current chunk. For IndicF5 a chunk is one paragraph.