mcp-loudkit
OfficialAn offline text-to-speech engine exposed as three MCP tools: it lists available voices, turns text into speech in any of them, and reports the execution configuration it resolved.
list_voices — returns the names of every voice profile the server can speak in (no arguments).
synthesize — converts text into speech in a named voice, returning base64 audio plus duration and token count. Key options:
format:wav(default),flac(lossless, ~4x smaller), or lossymp3/opus.seedandspeed(0.5–2.0, pitch preserved; 1.0 is an exact bypass); same text/voice/seed gives the same audio.language: omit to use the voice's own language, pass to read text in another language.previous_tokens: pass the prior reply'scontinuationlist to join long text across calls without an audible restart.Response flags
truncated(hit the token cap, speech cut off) and structured errors (error_kind,supported/available,codefrom the same catalog the HTTP and gRPC doors use).
describe — reports the resolved algorithm and execution configuration (key/value strings), useful for diagnosing surprising synthesis output.
Ships a Speech Dispatcher module in integrations/, letting Linux screen readers drive loudkit's speech synthesis on the desktop.
Exposes an OpenAI-compatible /v1/audio/speech endpoint (streaming over Server-Sent Events) so agents that already speak OpenAI's speech API can use loudkit as their TTS backend with configuration alone.
loudkit
Natural-sounding text-to-speech that runs on your own hardware.
Twenty-eight voices in ten languages, voice cloning from about ten seconds of audio, and native SDKs for Python, Swift, Go, Rust and TypeScript. Download the model once and run offline, with no account, telemetry or usage bill.
loudkit is the speech engine inside LoudReader, a reading app that speaks articles, PDFs and books on device. The engine is here under Apache-2.0 for anyone who wants to build with it directly.
Hear the voices | Try it in the browser | Open in Colab | Model | Documentation
Hear a voice in one command
pip install "loudkit[torch,audio,hub]"
loudkit speak --voice joe "Hello from loudkit." --playThe first run downloads the 747 MB model and the 28 voices, then it runs
offline. --play uses the system player; add -o hello.wav to keep the file.
Every other voice works the same way: --voice kathleen, --voice dave.
Related MCP server: mcp-ai-voice
The same from Python
import loudkit as lk
engine = lk.load("loudreader/loudr-1")
voice = engine.voice("joe")
engine.synthesize("Hello from loudkit.", voice, seed=7).save("hello.wav")engine.voices() lists the 28 names. synthesize takes text of any
length, and engine.stream(...) delivers the same audio sentence by sentence
so playback can start early. All 28 voices, including Henry, Oliver, Oscar and
Sophie, are included in both model downloads and load by name.
Getting started is the page to read next.
The same in Swift, Go, Rust and TypeScript
Every port loads the model by name, fetches and verifies it on the first call, and runs offline after that. The snippets need version 0.1.1 of each package.
Swift (CoreML, macOS 14 or iOS 17). Add
.package(url: "https://github.com/loudreader/loudkit", from: "0.1.1") to
Package.swift. Guide.
import LoudKit
let engine = try await Engine.load("loudreader/loudr-1")
let voice = try engine.voice(named: "joe")
try engine.synthesize("Hello from loudkit.", voice: voice, seed: 7).saveWav("hello.wav")Go (ONNX Runtime). go get github.com/loudreader/loudkit/go@v0.1.1.
Guide.
eng, err := loudkit.Load("loudreader/loudr-1")
if err != nil { log.Fatal(err) }
defer eng.Close()
v, err := eng.Voice("joe")
if err != nil { log.Fatal(err) }
res, err := eng.Synthesize("Hello from loudkit.", v, loudkit.Options{Seed: 7})
if err != nil { log.Fatal(err) }
if err := res.SaveWav("hello.wav"); err != nil { log.Fatal(err) }Rust (ONNX Runtime). cargo add loudkit@0.1.1.
Guide.
use loudkit::{Engine, Options};
let mut engine = Engine::load("loudreader/loudr-1")?;
let voice = engine.voice("joe")?;
let options = Options { seed: 7, ..Default::default() };
engine.synthesize("Hello from loudkit.", &voice, &options)?.save_wav("hello.wav")?;TypeScript (ONNX Runtime, Node 20). npm install loudkit@0.1.1.
Guide.
import { Engine } from "loudkit";
const engine = await Engine.load("loudreader/loudr-1");
const voice = engine.voice("joe");
(await engine.synthesize("Hello from loudkit.", voice, { seed: 7 })).saveWav("hello.wav");
await engine.close();Go and Rust need libonnxruntime on the machine (brew install onnxruntime,
or a build from the ONNX Runtime releases); the guides say where each port
looks for it. The same text, voice and seed give the same speech tokens in all
five languages.
Two models
loudreader/loudr-1 is the default and runs on every backend and in every
language. loudreader/loudr-1-turbo is faster, at a small cost in
naturalness, and in 0.1.1 runs in all five SDKs. The string passed
to load is the whole choice:
Choosing a model.
Voices
The voice gallery plays all 28 voices next to the recording each was enrolled from. English, Spanish, French, German, Italian, Polish, Portuguese, Dutch, Swedish and Danish, ten English voices and two for each other language. VOICES.md records the source, licence and consent basis of every one; they come from recordings donated for speech technology or from CC0 and CC-BY corpora.
We have evaluated English by ear and do not speak the other nine languages well enough to judge them. If you do, please listen and tell us what sounds wrong.
Clone a voice
From a recording you own or have permission to use, five to ten seconds of one speaker:
pip install "loudkit[torch,audio,enroll,hub]"
loudkit clone my-recording.wav --checkpoint loudreader/loudr-1 --name my-voice --language en
loudkit speak --voice voices/my-voice.safetensors "Now in a cloned voice." -o cloned.wavThe result is a portable profile of about 150 KB, not another copy of the
model. In Python the same path is lk.enroll(...); every port has enroll.
See Cloning a voice
and Responsible use.
Measured speed
path | hardware | loudr-1 | loudr-1-turbo |
split PyTorch engine* | Apple M3 Pro | 3.29x | 5.77x |
Swift, native generator plus CoreML renderer | Apple M3 Pro | 2.49x | 3.44x |
ONNX Runtime, CPU provider | Apple M3 Pro | 1.14x | 1.59x |
PyTorch with CUDA graphs | RTX 3090 | 8.55x | 13.05x |
PyTorch with CUDA graphs | Jetson Orin Nano | 1.85x | 2.50x |
* "Split" describes device placement, not a different model or checkpoint. The token generator runs on the CPU while the mel and vocoder renderer runs on the Apple GPU through MPS. Adjacent windows can overlap across the two devices.
Higher is faster, and 1.0x means real time. Every row was measured on 0.1.1 (2026-09-06, both models): the Apple rows on one laptop in ordinary use, the NVIDIA rows on the named parts, with the same passage, voice and seed. The A100, L4 and T4 rows are on the benchmark page.
For batched workloads, the token generator reaches 16.7x aggregate throughput at batch 1 and 57.3x at batch 64 on the RTX 3090 with loudr-1, and 42.0x to 155.0x with loudr-1-turbo. The highest measured result is 223.6x, turbo on an A100 at batch 64 (85.3x with loudr-1), measured on 0.1.1. They are generator-only throughput numbers, not single-request latency or end-to-end RTF. Full commands, hardware and caveats are in Benchmarks.
Integrations
For a process that keeps one engine warm rather than paying the load cost per call. The contracts are in Server and agents.
loudkit serve: an HTTP server with loudkit's own routes and an OpenAI-compatible/v1/audio/speech, streaming over Server-Sent Events. Agents that speak OpenAI's speech API, Hermes Agent and OpenClaw among them, connect with configuration alone.loudkit serve --grpc: the same engine behind a typed schema with backpressure.loudkit serve --mcp: an MCP server on stdio for agent hosts (preview).A Speech Dispatcher module for Linux screen readers, in
integrations/.Docker images and compose for the server.
WAVs saved from Python and the server's replies carry a machine-readable note
about how the audio was made, naming the model, voice, seed and backend and
carrying a checksum that ties the note to the sound; the Go, Rust, JS and Swift
ports write plain PCM. loudkit writes that note and loudkit verify reads it.
It is not C2PA Content Credentials: nothing signs it and no C2PA tool reads it.
Scope
loudkit is an inference toolbox, not a hosted speech platform. It does not provide accounts, billing, multi-tenancy, model training or an emotion control. The local server expects you to provide any public-facing authentication, rate limits and TLS. It will not help with undisclosed impersonation, bypassing voice authentication or stripping the machine-readable note from generated audio. SUPPORTED.md states the boundary.
Documentation
The documentation index lists the twelve pages a user needs: getting started, one page per language, choosing a model, cloning, long text and streaming, servers, troubleshooting and the two model cards. The model card covers lineage, limits and what each download contains.
Licence
The code and the loudr-1 release are
Apache-2.0. The
tokenizer and speaker encoder keep their upstream MIT licence from Chatterbox.
NOTICE lists every
upstream component and licence.
Available Tools
3 toolsdescribeDescribe the engineA
The resolved algorithm and execution configuration. Log this whenever a synthesis surprises you: it is the line that tells you which mode was active.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It discloses that the tool returns the resolved algorithm and execution configuration, and frames it as a read-only diagnostic action ('Log this'). However, it doesn't describe what the output schema contains or any side effects, though the output schema exists and may cover return values.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose, and the usage guidance is embedded efficiently. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter diagnostic tool with an output schema, the description is largely complete. It explains what the tool returns and when to use it. It could be slightly stronger by noting that it's read-only or non-mutating, but the absence of parameters and the diagnostic framing make that less critical.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has 0 parameters, so there is no parameter semantics burden. The description adds meaning by explaining what the tool reports (resolved algorithm and execution configuration), which is useful context beyond the empty schema. Baseline 4 for 0 params is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Log this') and resource ('resolved algorithm and execution configuration'), and distinguishes it from siblings by framing it as a diagnostic/observability tool rather than a synthesis or voice-listing tool. It's not a perfect 5 because it doesn't explicitly name the sibling it is not, but the intent is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance on when to use it: 'Log this whenever a synthesis surprises you.' This is a clear context signal. It doesn't explicitly say when not to use it or name alternatives, but the sibling context (list_voices, synthesize) makes the usage boundary reasonably clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_voicesList voicesA
Names of every voice profile the server can speak in.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must disclose behavioral traits. It only states the functional purpose and does not mention that the operation is read-only, requires no authentication, has no side effects, or any potential rate limits. For a listing tool, the absence of such context is a notable gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, tightly worded sentence with no extraneous content. It is front-loaded with the core function, achieving maximum brevity without sacrificing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless tool with an output schema, the description is largely complete for invocation purposes. The output schema presumably details the return format, and the description covers the what and scope. However, it lacks usage routing context, which is more appropriately addressed under usage guidelines, so this dimension is adequately covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the input schema is empty. With no parameters to document, the description cannot add meaning beyond the schema, warranting the baseline score of 4. There is nothing to compensate for because there are no parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Names of every voice profile the server can speak in' clearly identifies the tool as a listing operation for voice profiles. The resource and scope are explicit, and it distinguishes itself from siblings 'synthesize' and 'describe' by its focus on enumeration rather than generation or analysis.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus its siblings. It does not mention that it should be called before 'synthesize' to select a voice, nor does it state any exclusions or conditions. An agent receives no strategic context for choosing this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
synthesizeSynthesize speechA
Turn text into speech in a named voice. Returns the audio as base64 plus the audio duration and token count. format is "wav" by default; "flac" is the same samples, losslessly, at about a quarter the size: worth asking for when the reply is saved to a file rather than played. "mp3" and "opus" are lossy and smaller still, for a reply sent on to a chat or a phone. Same text, voice and seed give the same audio, and the same bytes in every format but ogg and opus, whose container carries a random stream serial. Omit language to read the text in the voice's own language; pass one only to read text in a language the voice was not enrolled in. speed is playback speed in [0.5, 2.0] with the pitch preserved: 1.0, the default, is an exact bypass. To read a long text as several calls without an audible restart at each join, pass the previous reply's continuation list back as previous_tokens. Check truncated: when true the utterance hit the token cap and the speech is cut off mid-sentence. A refusal comes back as error with error_kind "bad_request": something about this call to fix, and supported or available listing what would have worked, and code from the same frozen catalog the HTTP and gRPC doors name the condition with.
| Name | Required | Description | Default |
|---|---|---|---|
| seed | No | ||
| text | Yes | ||
| speed | No | ||
| voice | Yes | ||
| format | No | wav | |
| language | No | ||
| previous_tokens | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It discloses determinism (same text/voice/seed gives same audio), format-specific container quirks (random stream serial for ogg/opus), speed behavior with pitch preservation, continuation semantics, truncation detection, and a detailed error structure with `error_kind`, `supported`/`available`, and `code`. This is exemplary transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, every sentence earns its place. The description leads with the core action and return value, then systematically covers formats, determinism, language, speed, continuation, truncation, and errors. There is no redundancy or fluff; the structure is logical and front-loaded with the most important facts.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (7 parameters, multiple formats, error cases, continuation), and the absence of any annotations, the description is remarkably complete. It explains what is returned, how parameters affect behavior, how to chain calls, and how to interpret errors. An output schema exists, so the return structure is likely further defined, but the description covers everything an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must explain every parameter. It does: `format` with defaults and size trade-offs, `language` with default behavior, `speed` with range and pitch preservation, `previous_tokens` with its continuation purpose, and `seed` via the determinism statement. `text` and `voice` are self-evident but still implied. The description adds meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a crisp verb+object pair ('Turn text into speech in a named voice') and then specifies the exact resource and the output shape (base64 audio, duration, token count). It clearly distinguishes itself from the siblings (list_voices, describe) by focusing on synthesis rather than enumeration or inspection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance for each format ('worth asking for when the reply is saved to a file rather than played', 'for a reply sent on to a chat or a phone'), explains when to omit or pass `language`, and describes the continuation mechanism for long texts. It even tells the caller to check `truncated` to detect cut-off speech. This is proactive, alternative-aware guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.1- First observed
describe - First observed
list_voices - First observed
synthesize
TDQS
Scored across 3 tools
Each tool has a clearly distinct responsibility: listing available voices, performing synthesis, and reporting configuration details. There is no overlap or ambiguity between their purposes.
All tool names are lowercase imperative verbs, but list_voices follows a verb_noun pattern while synthesize and describe are standalone verbs. The naming is still readable and predictable, with only a minor structural inconsistency.
Three tools is well-scoped for a text-to-speech server: discover voices, synthesize speech, and inspect configuration. Each tool earns its place without redundancy or bloat.
The surface covers the full core workflow: discovering available voices, generating audio from text, and inspecting the active configuration for debugging. No major gaps are apparent for the stated purpose.
Maintenance
Related MCP Connectors
Hosted pay-per-use TTS: 54 neural voices, 9 languages incl. Brazilian Portuguese. $10 free credits.
MCP server for Text-to-Speech
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/
Give your AI a real phone: place calls, send SMS, fetch recordings and transcripts. Local or hosted.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables natural language-driven speech synthesis using Fish Audio's Text-to-Speech API, supporting multiple voices, streaming, and flexible configuration.217MIT
- AlicenseAqualityDmaintenanceEnables AI agents to synthesize natural speech using either platform system voices or premium OpenAI TTS, with automatic engine selection and graceful fallback.118MIT
- AlicenseAqualityAmaintenanceText-to-speech MCP server that enables AI assistants to read text aloud on the user's computer using Windows SAPI, with no API key or cloud service required.11MIT
- AlicenseNot gradedqualityDmaintenanceEnables MCP clients to speak by running local voice models using Chatterbox Turbo TTS or Kokoro TTS, with support for voice cloning, paralinguistic tags, and multiple voices.7313MIT