MCP Voice Soundboard
README.md
<p align="center">
<a href="README.ja.md">日本語</a> | <a href="README.zh.md">中文</a> | <a href="README.es.md">Español</a> | <a href="README.fr.md">Français</a> | <a href="README.hi.md">हिन्दी</a> | <a href="README.it.md">Italiano</a> | <a href="README.pt-BR.md">Português (BR)</a>
</p>
<p align="center">
<img src="https://raw.githubusercontent.com/mcp-tool-shop-org/brand/main/logos/mcp-voice-soundboard/readme.png" alt="MCP Voice Soundboard" width="400">
</p>
<p align="center">
<a href="https://github.com/mcp-tool-shop-org/mcp-voice-soundboard/actions/workflows/ci.yml"><img src="https://github.com/mcp-tool-shop-org/mcp-voice-soundboard/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://www.npmjs.com/package/@mcptoolshop/voice-soundboard-mcp"><img src="https://img.shields.io/npm/v/@mcptoolshop/voice-soundboard-mcp" alt="npm"></a>
<a href="https://codecov.io/gh/mcp-tool-shop-org/mcp-voice-soundboard"><img src="https://img.shields.io/codecov/c/github/mcp-tool-shop-org/mcp-voice-soundboard" alt="Coverage"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License"></a>
<a href="https://mcp-tool-shop-org.github.io/mcp-voice-soundboard/"><img src="https://img.shields.io/badge/Landing_Page-live-blue" alt="Landing Page"></a>
</p>
<p align="center">
48 voices • 9 languages • 5 presets • 8 emotions • SSML-lite • SFX tags • multi-speaker dialogue<br>
Swappable TTS backends. Guardrails built in. Ships as a single <code>npx</code> command.
</p>
---
## Highlights
- **MCP native** — stdio transport, works with Claude Desktop, Cursor, and any MCP client
- **5 tools** — `voice_speak`, `voice_dialogue`, `voice_status`, `voice_interrupt`, `voice_inner_monologue`
- **48 approved voices, 9 languages** — English (American + British), Japanese, Mandarin, Spanish, French, Hindi, Italian, Brazilian Portuguese. Curated presets: `narrator`, `announcer`, `whisper`, `storyteller`, `assistant`
- **Emotion spans** — 8 emotions via `{joy}...{/joy}` inline markup
- **SSML-lite** — `<break>`, `<emphasis>`, `<prosody>` without full SSML complexity
- **SFX tags** — `[ding]`, `[chime]`, `[whoosh]`, `[tada]`, `[pop]`, `[click]` inline sound effects
- **Multi-speaker dialogue** — `Speaker: line` format with auto-cast and pause directives
- **Guardrails** — rate limiting, concurrency semaphore, request timeouts, path traversal protection, secret redaction
- **Swappable backends** — Mock (built-in), HTTP proxy, Python bridge, or bring your own
## Quick Start
```bash
npx @mcptoolshop/voice-soundboard-mcp
```
Or install globally:
```bash
npm install -g @mcptoolshop/voice-soundboard-mcp
voice-soundboard-mcp
```
### Claude Desktop / MCP Client Config
Add to your MCP client configuration (e.g. `claude_desktop_config.json`):
```json
{
"mcpServers": {
"voice-soundboard": {
"command": "npx",
"args": ["-y", "@mcptoolshop/voice-soundboard-mcp"]
}
}
}
```
With options:
```json
{
"mcpServers": {
"voice-soundboard": {
"command": "npx",
"args": [
"-y", "@mcptoolshop/voice-soundboard-mcp",
"--artifact=path",
"--output-dir=/tmp/voice-output",
"--timeout=30000",
"--max-concurrent=2"
]
}
}
}
```
## MCP Tools
### `voice_speak`
Synthesize speech from text.
```
text: "Hello world!"
voice?: "am_fenrir" # Voice ID or preset name
speed?: 1.0 # 0.5 - 2.0
mood?: "dry" # Humor mood (sensor-humor integration)
format?: "wav" # wav | mp3 | ogg | raw
artifactMode?: "path" # path | base64
outputDir?: "subdir" # Subdirectory within output root
sfx?: true # Enable [ding], [chime] etc.
```
### `voice_dialogue`
Multi-speaker dialogue synthesis.
```
script: "Alice: Hello!\nBob: Hey there!"
cast?: { "Alice": "af_sky", "Bob": "am_fenrir" }
speed?: 1.0
concat?: true # Combine into single file
debug?: true # Include cue_sheet
artifactMode?: "path" # path | base64
outputDir?: "subdir" # Subdirectory within output root
```
### `voice_status`
Returns engine health, available voices, presets, and backend info. No arguments.
### `voice_interrupt`
Stop or rollback active synthesis.
```
streamId?: "stream-123"
reason?: "user_spoke" # user_spoke | context_change | timeout | manual
```
### `voice_inner_monologue`
Ephemeral micro-utterances for ambient narration. Requires `--ambient` flag or `VOICE_SOUNDBOARD_AMBIENT_ENABLED=1`.
```
text: "Interesting..." # Max 500 chars, auto-redacted
category?: "thinking" # general | thinking | observation | debug
```
## Voices
48 voices across 9 languages. Language is auto-inferred from the voice ID prefix — no configuration required.
| Prefix | Language |
|--------|----------|
| `af_` / `am_` | English (American) |
| `bf_` / `bm_` | English (British) |
| `jf_` / `jm_` | Japanese |
| `zf_` / `zm_` | Mandarin Chinese |
| `ef_` / `em_` | Spanish |
| `ff_` | French |
| `hf_` / `hm_` | Hindi |
| `if_` / `im_` | Italian |
| `pf_` / `pm_` | Brazilian Portuguese |
### English — American
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `af_aoede` | Aoede | Female | Musical |
| `af_bella` | Bella | Female | Warm |
| `af_heart` | Heart | Female | Caring |
| `af_jessica` | Jessica | Female | Professional |
| `af_kore` | Kore | Female | Youthful |
| `af_nicole` | Nicole | Female | Soft |
| `af_sarah` | Sarah | Female | Clear |
| `af_sky` | Sky | Female | Airy |
| `am_eric` | Eric | Male | Confident |
| `am_fenrir` | Fenrir | Male | Powerful |
| `am_liam` | Liam | Male | Friendly |
| `am_michael` | Michael | Male | Deep |
| `am_onyx` | Onyx | Male | Smooth |
| `am_puck` | Puck | Male | Playful |
### English — British
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `bf_alice` | Alice | Female | Proper |
| `bf_emma` | Emma | Female | Refined |
| `bf_isabella` | Isabella | Female | Warm |
| `bm_fable` | Fable | Male | Storytelling |
| `bm_george` | George | Male | Authoritative |
| `bm_lewis` | Lewis | Male | Friendly |
### Japanese
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `jf_alpha` | Alpha | Female | Clear |
| `jf_gongitsune` | Gongitsune | Female | Storytelling |
| `jf_nezuko` | Nezuko | Female | Gentle |
| `jf_tebukuro` | Tebukuro | Female | Warm |
| `jm_kumo` | Kumo | Male | Calm |
### Mandarin Chinese
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `zf_xiaobei` | Xiaobei | Female | Bright |
| `zf_xiaoni` | Xiaoni | Female | Gentle |
| `zf_xiaoxiao` | Xiaoxiao | Female | Clear |
| `zf_xiaoyi` | Xiaoyi | Female | Warm |
| `zm_yunjian` | Yunjian | Male | Authoritative |
| `zm_yunxi` | Yunxi | Male | Friendly |
| `zm_yunxia` | Yunxia | Male | Calm |
| `zm_yunyang` | Yunyang | Male | Confident |
### Spanish
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `ef_dora` | Dora | Female | Warm |
| `em_alex` | Alex | Male | Confident |
| `em_santa` | Santa | Male | Jolly |
### French
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `ff_siwis` | Siwis | Female | Refined |
### Hindi
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `hf_alpha` | Alpha | Female | Clear |
| `hf_beta` | Beta | Female | Warm |
| `hm_omega` | Omega | Male | Deep |
| `hm_psi` | Psi | Male | Calm |
### Italian
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `if_sara` | Sara | Female | Warm |
| `im_nicola` | Nicola | Male | Confident |
### Brazilian Portuguese
| ID | Name | Gender | Style |
|----|------|--------|-------|
| `pf_dora` | Dora | Female | Warm |
| `pm_alex` | Alex | Male | Confident |
| `pm_santa` | Santa | Male | Jolly |
### Presets
| Preset | Voice | Speed | Description |
|--------|-------|-------|-------------|
| `narrator` | `bm_george` | 0.95 | Calm, clear, documentary style |
| `announcer` | `am_eric` | 1.1 | Bold, energetic, broadcast style |
| `whisper` | `af_sky` | 0.85 | Soft, intimate, gentle |
| `storyteller` | `bf_emma` | 0.90 | Expressive, varied pacing |
| `assistant` | `af_jessica` | 1.0 | Friendly, helpful, conversational |
## Emotion Spans
Wrap text in emotion tags to control prosody and voice routing:
```
{joy}Great news!{/joy} But {calm}let me explain.{/calm}
```
Supported: `neutral`, `serious`, `friendly`, `professional`, `calm`, `joy`, `urgent`, `whisper`
## CLI Flags
| Flag | Default | Description |
|------|---------|-------------|
| `--artifact=path\|base64` | `path` | Audio delivery mode |
| `--output-dir=<path>` | `<tmpdir>/voice-soundboard/` | Output directory |
| `--backend=mock\|http\|python` | `mock` | Backend selection |
| `--ambient` | off | Enable inner-monologue system |
| `--max-concurrent=<n>` | `3` | Max concurrent synthesis requests |
| `--timeout=<ms>` | `60000` | Per-request timeout |
| `--retention-minutes=<n>` | `240` | Auto-cleanup age (0 to disable) |
## Packages
This is a pnpm monorepo with two publishable packages:
| Package | Description | npm |
|---------|-------------|-----|
| [`@mcptoolshop/voice-soundboard-core`](packages/core) | Backend-agnostic core library (validation, SSML, chunking, schemas) | [](https://www.npmjs.com/package/@mcptoolshop/voice-soundboard-core) |
| [`@mcptoolshop/voice-soundboard-mcp`](packages/mcp-server) | MCP server with CLI, guardrails, and transport | [](https://www.npmjs.com/package/@mcptoolshop/voice-soundboard-mcp) |
## Development
```bash
# Install
pnpm install
# Build
pnpm build
# Test (363 tests)
pnpm test
# Build + test in one step
pnpm verify
```
> Part of [MCP Tool Shop](https://mcp-tool-shop.github.io/)
### Project Structure
```
mcp-voice-soundboard/
packages/
core/ @mcptoolshop/voice-soundboard-core
src/
limits.ts SHIP_LIMITS, text/chunk limits
schemas.ts VoiceRequest, VoiceResponse, error codes
artifact.ts resolveOutputDir, path sandbox
voices.ts Approved voice registry + presets
emotion.ts Emotion span parser
ssml/ SSML-lite parser + limits
chunking/ Text chunker
sfx/ SFX tag parser + registry
sandbox.ts Safe filenames, symlink checks
ambient.ts AmbientEmitter for inner monologue
redact.ts PII/secret redaction
mcp-server/ @mcptoolshop/voice-soundboard-mcp
src/
server.ts MCP tool registration + guardrail wiring
cli.ts CLI entrypoint (stdio transport)
backend.ts Backend abstraction + mock/HTTP
concurrency.ts SynthesisSemaphore
rateLimit.ts ToolRateLimiter (sliding window)
timeout.ts withTimeout utility
retention.ts Output file cleanup timer
redact.ts Server-level redaction
validation.ts Synthesis result validation
tools/ Individual tool handlers
assets/ Logo, audio event manifests
docs/ Architecture docs
```
## Privacy
**No telemetry.** This tool collects no usage data, sends no analytics, and makes no network requests except to the TTS backend you configure. All processing is local.
## Security
See [SECURITY.md](SECURITY.md) for vulnerability reporting.
See [THREAT_MODEL.md](THREAT_MODEL.md) for the full threat surface analysis.
## Related
| Project | Description |
|---------|-------------|
| [soundboard-plugin](https://github.com/mcp-tool-shop-org/soundboard-plugin) | Claude Code plugin — slash commands, emotion-aware narration |
## Support
- **Questions / help:** [Discussions](https://github.com/mcp-tool-shop-org/mcp-voice-soundboard/discussions)
- **Bug reports:** [Issues](https://github.com/mcp-tool-shop-org/mcp-voice-soundboard/issues)
- **Security:** [SECURITY.md](SECURITY.md)
## Scorecard
| Category | Score | Notes |
|----------|-------|-------|
| A. Security | 10/10 | SECURITY.md, THREAT_MODEL.md, redaction, no telemetry |
| B. Error Handling | 8/10 | Structured error contract (code/hint/retryable), toToolError pattern |
| C. Operator Docs | 9/10 | README, CHANGELOG, HANDBOOK, tool docs |
| D. Shipping Hygiene | 9/10 | CI, verify script, dependabot, lockfile |
| E. Identity | 10/10 | Logo, translations, landing page, metadata |
| **Total** | **46/50** | |
## License
[MIT](LICENSE)
---
<p align="center">
Built by <a href="https://mcp-tool-shop.github.io/">MCP Tool Shop</a>
</p>
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessUnresponsive