A text-to-speech MCP server powered by Kokoro — gives Claude Code a voice
Project description
Soliloquy
A text-to-speech MCP server powered by Kokoro — gives Claude Code a voice.
One command to install. No config, no API keys, no cloud.
Why Soliloquy?
| Cloud TTS (ElevenLabs, OpenAI, etc.) | Soliloquy | |
|---|---|---|
| Privacy | Text sent to third-party servers | Runs entirely on your machine |
| Cost | $0.18-15/1M chars | Free forever |
| Offline | No | Yes |
| Usage Limits | Quotas / rate limits | Unlimited |
| Latency | 200-500ms (network) | ~50-100ms (local) |
| AI Integration | Developer calls API from code | AI agent decides when to speak |
| Setup | API keys + billing | One command, no config |
What You Can Do
Once installed, just talk to Claude naturally:
- "turn on auto speak" — automatically voice conversational responses
- "read this file aloud" — listen to docs, chapters, or articles (text, markdown, PDF, EPUB)
- "read this book" — EPUBs are treated as audiobooks: chapters announced, resume on next call
- "pick up where we left off" — resume any book you've started
- "jump to chapter 5" / "read the preface" / "next chapter" — navigate around
- "speak aloud" — voice a specific response
- "stop" — stop audio playback
Auto-Speak
The flagship feature. Auto-speak voices every Claude conversational response automatically using a background hook — no tool call needed, zero token overhead. It just works.
"Turn on auto speak"
From that point on, everything Claude says, you hear. Toggle it off just as easily:
"Turn off auto speak"
When you use read_aloud or speak explicitly, auto-speak steps aside and lets the explicit playback finish.
Speech Normalization
Soliloquy doesn't just read text literally — it understands what sounds natural:
- Code blocks become "See the code below" instead of reading syntax aloud
- Tables are summarized ("There's a table here with 5 rows")
- Symbols are spoken naturally (arrows become "to", URLs are simplified)
- Lists are enumerated ("First... Second... Third...")
- Paragraph breaks produce natural pauses between sections
Technical content and markdown-heavy responses sound like a person reading them to you, not a robot parsing characters.
Audiobook Mode (Beta)
🧪 Beta feature. Works well on cleanly-authored EPUBs (O'Reilly, Manning, Standard Ebooks, most professional publishers). EPUB tagging varies wildly in the wild — please open an issue if a specific EPUB misclassifies chapters or sounds wrong.
Pass an EPUB to read_aloud and Soliloquy treats it as an audiobook. Each chapter is announced by its title, frontmatter (cover, preface, "About the Author") is skipped by default, and playback resumes from where you left off on the next call.
pip install 'soliloquy-tts[epub]' # EPUB only
pip install 'soliloquy-tts[documents]' # PDF + EPUB
Talk to Claude naturally:
| You say… | What happens |
|---|---|
| "Read this book" | Starts a fresh book, or resumes if you've read it before |
| "What chapters are in this book?" | Shows the table of contents |
| "Where am I?" | Reports your current chapter and progress |
| "Jump to chapter 5" | Skip to that chapter (chapter=5) |
| "Read 'The Forest'" | Match a chapter by its title (chapter="The Forest") |
| "Next chapter" / "previous chapter" | Move ±1 chapter |
| "Restart this chapter" | Replay from the chapter's first sentence |
| "Start over" | Wipe the bookmark and restart from chapter 1 |
| "Show me the frontmatter too" | Include cover, preface, etc. (include_frontmatter=True) |
How resume works
Bookmarks live as JSON files under ~/.soliloquy/library/, keyed by the SHA256 content hash of the source file. A book moved to a new folder keeps its place; two identical copies share one bookmark. Atomic writes (tempfile + rename) mean a crash mid-write can never corrupt your position.
The bookmark layer uses a hybrid update strategy that tracks actual audio playback — not synthesis-ahead. Your position is saved every few audio chunks during playback and again on stop, so resume replays at most one short batch of audio. You'll never skip ahead and miss content.
Smart frontmatter detection
Four cascading signals identify cover, dedication, preface, appendix, index, and similar non-body content:
- EPUB3 nav doc entries marked
epub:type="frontmatter|backmatter" - Spine entries with
linear="no" - Spine idrefs starting with semantic names (
cover,titlepage,preface,appendix, ...) - Chapter titles matching frontmatter patterns (
"Preface","Index","Appendix A: …")
Professional publishers tag spine entries cleanly — heuristics handle them well. Hobby or scraped EPUBs sometimes mislabel title pages or backmatter as body chapters. When that happens, pass include_frontmatter=True to play everything in spine order, or use chapter="<title>" to jump straight to the right content by name.
Known limitations
- EPUB only. PDF and text files read as one-shot only — page-level book mode for PDFs is a future iteration.
- Chapter numbers aren't spoken. The internal chapter index is the EPUB spine position (an implementation detail), not the "story chapter N" a reader would recognize. Only the title is announced. The index is still used for navigation (
chapter=5,bookmark_status, etc.). - No multi-language detection. All chapters use the configured
lang.
For non-book use cases, read_aloud still works as a one-shot reader for .txt, .md, and .pdf files (PDFs require the [pdf] extra).
Requirements
- macOS, Windows, or Linux
- Python 3.10+
- PortAudio (audio output library)
| Platform | Install PortAudio |
|---|---|
| macOS | brew install portaudio |
| Windows | Bundled with sounddevice (no action needed) |
| Linux | sudo apt install libportaudio2 |
Note: First install downloads ~2GB of dependencies (PyTorch, model weights). First run also downloads the Kokoro-82M model from HuggingFace.
Optional: PDF and EPUB support
To read PDFs and EPUBs (including audiobook-mode resume on EPUBs), install the document extras:
pip install 'soliloquy-tts[documents]' # both PDF and EPUB
pip install 'soliloquy-tts[pdf]' # PDF only
pip install 'soliloquy-tts[epub]' # EPUB only
With uvx, replace soliloquy-tts in your setup command (e.g. uvx 'soliloquy-tts[documents]').
Optional: macOS Menu Bar Control
On macOS, you can install rumps for a menu bar icon that lets you stop playback instantly — no need to go through Claude Code:
pip install rumps
Without it, everything still works — you just use the stop command through Claude Code instead.
Quick Start
Make sure PortAudio is installed (see above), then:
uvx soliloquy-tts
That's it. This registers the MCP server, configures auto-speak, and sets everything up. Restart Claude Code afterward and you're good to go.
Requires uv. Install it with
brew install uv(macOS),sudo apt install uv(Linux), or see the uv docs.
What happens when you run it
- Registers Soliloquy as an MCP server with Claude Code
- Writes a hook script for automatic voicing
- Configures the Claude Code Stop hook
You only need to do this once. After that, Claude Code starts Soliloquy automatically in the background whenever you open a session.
With pip
pip install soliloquy-tts
soliloquy
Same setup flow. Run soliloquy from your terminal and it handles the rest.
How It Works
Soliloquy uses a hybrid architecture to share a single model across multiple Claude Code sessions:
- First session loads the Kokoro model and starts a local backend server
- Additional sessions detect the running backend and connect as lightweight proxies (near-instant startup, no extra memory)
- If the backend exits, the next session automatically takes over
This is completely transparent — no configuration needed.
Reference
Tools
speak — Synthesize and play text aloud.
| Parameter | Default | Description |
|---|---|---|
text |
(required) | Text to speak |
voice |
af_heart |
Voice ID |
speed |
1.0 |
Speed multiplier (0.5 - 2.0) |
lang |
en-us |
Language code |
read_aloud — Read a file aloud directly. Supports plain text, markdown, PDF (with [pdf]), and EPUB (with [epub]). EPUBs become audiobooks by default.
| Parameter | Default | Description |
|---|---|---|
path |
(required) | Path to the file to read |
voice |
af_heart |
Voice ID |
speed |
1.0 |
Speed multiplier (0.5 - 2.0) |
lang |
en-us |
Language code |
pages |
(none) | PDF page range, e.g. "1-3" or "5" |
chapter |
(none) | EPUB navigation: integer, title substring, "next", "prev" |
restart |
False |
EPUB: start at chapter 1, reset bookmark |
restart_chapter |
False |
EPUB: restart current chapter from the beginning |
as_book |
(auto) | Force book mode on/off (default: on for EPUB, off otherwise) |
include_frontmatter |
False |
EPUB: include cover, preface, etc. in playback |
bookmark_status — Show your current position in a book.
list_chapters — Show the table of contents for an EPUB. Pass include_frontmatter=True to also list cover, preface, etc.
stop — Stop audio playback immediately.
auto_speak — Toggle automatic voicing on or off.
list_voices — List all available voices.
Voices
28 voices across American and British English. Default is af_heart.
View all voices
| Voice | Accent | Gender |
| af_heart | American | Female |
| af_alloy | American | Female |
| af_aoede | American | Female |
| af_bella | American | Female |
| af_jessica | American | Female |
| af_kore | American | Female |
| af_nicole | American | Female |
| af_nova | American | Female |
| af_river | American | Female |
| af_sarah | American | Female |
| af_sky | American | Female |
| am_adam | American | Male |
| am_echo | American | Male |
| am_eric | American | Male |
| am_fenrir | American | Male |
| am_liam | American | Male |
| am_michael | American | Male |
| am_onyx | American | Male |
| am_puck | American | Male |
| am_santa | American | Male |
| bf_alice | British | Female |
| bf_emma | British | Female |
| bf_isabella | British | Female |
| bf_lily | British | Female |
| bm_daniel | British | Male |
| bm_fable | British | Male |
| bm_george | British | Male |
| bm_lewis | British | Male |
Languages
en-us (default), en-gb, ja, zh, es, fr, hi, it, pt-br
Library Usage (StreamingSession)
Soliloquy can also be used as a Python library for streaming TTS — no MCP server needed. Push text as it arrives (from an LLM, WebSocket, etc.) and Soliloquy handles buffering, batching, and gapless playback.
from soliloquy.streaming import StreamingSession
session = StreamingSession(voice="af_heart", speed=1.0)
# Push text as it arrives
session.push("Here's the first sentence.")
session.push("And here's another one.")
session.push("The model is still generating...")
# Signal end of input — flushes remaining text and waits for audio
session.finish()
# Or cancel immediately
session.stop()
StreamingSession adapts batch size to audio buffer health — synthesizing immediately when the buffer is low, and batching efficiently when it's healthy. All the same speech normalization, adaptive chunking, and gapless playback from the MCP tools, with a simple push-based API.
Uninstall
soliloquy --uninstall
This removes the MCP server registration, auto-speak hook, and all config files. Works with uvx soliloquy-tts --uninstall too.
Development
git clone https://gitlab.com/bw-stovall/soliloquy.git
cd soliloquy
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e .[dev,pdf,epub]
pytest tests/ -v
License
MIT
Project details
Release history Release notifications | RSS feed
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 soliloquy_tts-0.9.0.tar.gz.
File metadata
- Download URL: soliloquy_tts-0.9.0.tar.gz
- Upload date:
- Size: 81.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0ac6502f5467b61617f39ae07d2d29c0e53690e05b2ed9e40929a76d5977532
|
|
| MD5 |
17fbd65eed10496feb14bd4568b06cd7
|
|
| BLAKE2b-256 |
17e315fe779e9a8501122c2d684ee2a9fe81e55d4aa50011914e260deadadcb1
|
File details
Details for the file soliloquy_tts-0.9.0-py3-none-any.whl.
File metadata
- Download URL: soliloquy_tts-0.9.0-py3-none-any.whl
- Upload date:
- Size: 46.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9119dda09eef79845be862252872467a39d638315394c3773c1c1d01777e8fab
|
|
| MD5 |
0ea3ea8f2d802b8ca0854d6141add06b
|
|
| BLAKE2b-256 |
2b056c2906b3a91f2ae1cc3eec854941c19ce76fd76ed3bb84905843f248a34a
|