Content
# 🔊 TTS MCP Server
[](LICENSE)
[](https://www.python.org/)
[](https://modelcontextprotocol.io/)
[](Dockerfile)
A free, open-source, self-hosted **Text-to-Speech MCP server**. It synthesizes
speech with [`edge-tts`](https://github.com/rany2/edge-tts) (Microsoft Edge
online voices — **no API key required**) and exposes it to any MCP client
(claude.ai, Claude Code, Cursor, …) as a remote connector over
**streamable HTTP**.
Give your AI assistant a voice: ask it to read text aloud in **300+ voices
across 70+ languages**, and get back a playable MP3 link.
## 🌐 Live Demo
A public instance is hosted at **[tts.vurthex.com](https://tts.vurthex.com/)** —
you can try the server without deploying anything:
| | |
|---|---|
| **MCP endpoint** | `https://tts.vurthex.com/mcp` |
| **Transport** | Streamable HTTP |
| **Auth** | None (authless connector) |
Add it to claude.ai in under a minute:
1. Go to **Settings → Connectors → Add custom connector**.
2. **Name**: `TTS` (anything you like).
3. **Remote MCP server URL**: `https://tts.vurthex.com/mcp`
4. Leave authentication **empty** and save.
Then just ask Claude:
> *"Read this aloud with the en-US-AriaNeural voice: Hello world!"*
>
> *"Şu metni tr-TR-EmelNeural sesiyle seslendir: Merhaba dünya"*
Claude replies with a playable `https://tts.vurthex.com/audio/<uuid>.mp3` link.
> [!NOTE]
> The demo instance is provided for testing on a best-effort basis. Generated
> files are automatically deleted after 24 hours. For production use, please
> self-host — it takes a few minutes (see below).
## 🛠️ Tools
| Tool | Description |
|------|-------------|
| `text_to_speech(text, voice="tr-TR-EmelNeural", rate="+0%", pitch="+0Hz")` | Generates an MP3 and returns its public URL (`BASE_URL/audio/<uuid>.mp3`). |
| `list_voices(language="tr")` | Lists available voices (`ShortName`, `Gender`, `Locale`), filtered by locale prefix. Pass `""` for all voices. |
## ✨ Features
- 🎙️ **300+ neural voices, 70+ languages** via Microsoft Edge TTS
- 🔑 **Zero API keys** — edge-tts uses Microsoft's free online endpoint
- 🌍 **Remote MCP over streamable HTTP** — works with claude.ai custom connectors
- 🐳 **One-file Docker deploy** — Dockerfile included, Coolify-friendly
- 🧹 **Self-cleaning** — generated MP3s older than 24h are removed automatically
- ⚙️ **Configurable** — rate/pitch control, retention and cleanup intervals via env vars
## 🚀 Run Locally
```bash
git clone https://github.com/ismailcembabaoglu/TtsMcpServer.git
cd TtsMcpServer
pip install -r requirements.txt
export BASE_URL=http://localhost:8000
export AUDIO_DIR=./audio # /app/audio is the container default
python server.py
```
The MCP endpoint is now at `http://localhost:8000/mcp`. Verify it with a proper
MCP initialize handshake (a bare GET without MCP headers returns `406`/`400`,
which also confirms the route is live):
```bash
curl -i -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
```
A `200` response containing an `event: message` SSE payload means the server is
working.
### Docker
```bash
docker build -t tts-mcp-server .
docker run -p 8000:8000 -e BASE_URL=http://localhost:8000 tts-mcp-server
```
## ☁️ Self-Host (Coolify or any Docker host)
1. Fork or clone this repo to your Git provider.
2. In Coolify: **+ New → Resource → Application**, pick your Git repo.
3. Build pack: **Dockerfile** (auto-detected — this repo ships one).
4. **Port**: set the exposed port to `8000`.
5. **Domain**: assign a domain (e.g. `https://tts.example.com`). Coolify
provisions HTTPS automatically via its reverse proxy.
6. **Environment variables**: set `BASE_URL` to the exact domain you assigned,
**without a trailing slash**. See [`.env.example`](.env.example) for optional
overrides.
7. *(Optional but recommended)* Add a **persistent volume** mounted at
`/app/audio` so generated files survive restarts.
8. **Deploy**. Once healthy, your MCP endpoint is `https://tts.example.com/mcp`.
### Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `BASE_URL` | `http://localhost:8000` | Public base URL used to build MP3 links (no trailing slash) |
| `AUDIO_DIR` | `/app/audio` | Where generated MP3s are stored (served at `/audio/*`) |
| `AUDIO_MAX_AGE_SECONDS` | `86400` (24h) | Delete generated MP3s older than this |
| `CLEANUP_INTERVAL_SECONDS` | `3600` (1h) | How often the cleanup loop runs |
## 📝 Notes
- edge-tts requires outbound internet access from the container (it calls
Microsoft's Edge TTS endpoint). No credentials are needed.
- Generated files are throwaway: anything older than 24h is deleted. Tune with
`AUDIO_MAX_AGE_SECONDS` / `CLEANUP_INTERVAL_SECONDS`.
- This server is an **authless** connector by design. If you expose it publicly,
anyone who knows the URL can use it — put it behind a proxy with auth or rate
limiting if that's a concern.
## 🤝 Contributing
Issues and pull requests are welcome! If you find a bug or want a feature
(voice presets, auth support, other TTS engines…), open an issue.
## 📄 License
[MIT](LICENSE) — free to use, modify, and distribute.