@mcptoolshop/voice-soundboard-mcp 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +172 -0
- package/LICENSE +21 -0
- package/README.md +3 -3
- package/backend-python/soundboard_bridge/__init__.py +0 -0
- package/backend-python/soundboard_bridge/__main__.py +200 -0
- package/backend-python/soundboard_bridge/__pycache__/__init__.cpython-314.pyc +0 -0
- package/backend-python/soundboard_bridge/__pycache__/__main__.cpython-314.pyc +0 -0
- package/dist/backend.d.ts +1 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +16 -3
- package/dist/backend.js.map +1 -1
- package/dist/backends/httpBackend.d.ts +3 -0
- package/dist/backends/httpBackend.d.ts.map +1 -1
- package/dist/backends/httpBackend.js +111 -4
- package/dist/backends/httpBackend.js.map +1 -1
- package/dist/backends/pythonBackend.d.ts +3 -1
- package/dist/backends/pythonBackend.d.ts.map +1 -1
- package/dist/backends/pythonBackend.js +72 -6
- package/dist/backends/pythonBackend.js.map +1 -1
- package/dist/cli.js +204 -3
- package/dist/cli.js.map +1 -1
- package/dist/rateLimit.d.ts +2 -0
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +14 -0
- package/dist/rateLimit.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +123 -17
- package/dist/server.js.map +1 -1
- package/dist/sessionConfig.d.ts +14 -0
- package/dist/sessionConfig.d.ts.map +1 -0
- package/dist/sessionConfig.js +23 -0
- package/dist/sessionConfig.js.map +1 -0
- package/dist/synthesisRegistry.d.ts +25 -0
- package/dist/synthesisRegistry.d.ts.map +1 -0
- package/dist/synthesisRegistry.js +49 -0
- package/dist/synthesisRegistry.js.map +1 -0
- package/dist/tools/voiceCleanup.d.ts +16 -0
- package/dist/tools/voiceCleanup.d.ts.map +1 -0
- package/dist/tools/voiceCleanup.js +52 -0
- package/dist/tools/voiceCleanup.js.map +1 -0
- package/dist/tools/voiceConfig.d.ts +14 -0
- package/dist/tools/voiceConfig.d.ts.map +1 -0
- package/dist/tools/voiceConfig.js +14 -0
- package/dist/tools/voiceConfig.js.map +1 -0
- package/dist/tools/voiceDialogue.d.ts.map +1 -1
- package/dist/tools/voiceDialogue.js +4 -0
- package/dist/tools/voiceDialogue.js.map +1 -1
- package/dist/tools/voiceInterrupt.d.ts +2 -1
- package/dist/tools/voiceInterrupt.d.ts.map +1 -1
- package/dist/tools/voiceInterrupt.js +30 -5
- package/dist/tools/voiceInterrupt.js.map +1 -1
- package/dist/tools/voicePlay.d.ts +16 -0
- package/dist/tools/voicePlay.d.ts.map +1 -0
- package/dist/tools/voicePlay.js +99 -0
- package/dist/tools/voicePlay.js.map +1 -0
- package/dist/tools/voiceQueue.d.ts +31 -0
- package/dist/tools/voiceQueue.d.ts.map +1 -0
- package/dist/tools/voiceQueue.js +136 -0
- package/dist/tools/voiceQueue.js.map +1 -0
- package/dist/tools/voiceSpeak.d.ts +2 -0
- package/dist/tools/voiceSpeak.d.ts.map +1 -1
- package/dist/tools/voiceSpeak.js +47 -10
- package/dist/tools/voiceSpeak.js.map +1 -1
- package/dist/tools/voiceStatus.d.ts +25 -1
- package/dist/tools/voiceStatus.d.ts.map +1 -1
- package/dist/tools/voiceStatus.js +19 -3
- package/dist/tools/voiceStatus.js.map +1 -1
- package/package.json +5 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.2] - 2026-03-25
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `--version` / `-V` flag to print version and exit
|
|
12
|
+
- `--help` / `-h` flag with full CLI usage documentation
|
|
13
|
+
- CHANGELOG.md and LICENSE included in npm tarballs
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Health endpoint version was hardcoded at 0.1.2 — now reads from package.json
|
|
17
|
+
- SECURITY.md version table updated from 0.x to 1.0.x
|
|
18
|
+
|
|
19
|
+
## [1.0.0] - 2026-02-27
|
|
20
|
+
|
|
21
|
+
### Overview
|
|
22
|
+
|
|
23
|
+
**First stable release.** Structured error contract, Ship Gate audit (46/50), version alignment, and v1 README.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- **Structured error contract** — all errors now carry `hint` (actionable guidance) and `retryable` (safe to retry?) fields
|
|
28
|
+
- `SoundboardError` base class in core — extends `Error` with `code`, `hint`, `retryable`, `cause`
|
|
29
|
+
- `fromError()` helper — converts any caught error into a `VoiceErrorResponse`, extracting hint + retryable from `SoundboardError` subclasses
|
|
30
|
+
- `toToolError()` pattern in MCP server — converts errors into MCP tool error responses with structured fields, never exposes stack traces
|
|
31
|
+
- `wrapError()` utility — wraps unknown thrown values into `SoundboardError`
|
|
32
|
+
- `pnpm verify` script (build + test in one command)
|
|
33
|
+
- Explicit "No telemetry" privacy statement in README
|
|
34
|
+
- SHIP_GATE.md and SCORECARD.md for product quality tracking
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- All 11 error classes across core and server now extend `SoundboardError`
|
|
39
|
+
- `VoiceErrorResponse` schema now includes `hint: string` and `retryable: boolean`
|
|
40
|
+
- `voiceSpeak` and `voiceDialogue` handlers migrated from manual `instanceof` chains to `fromError()`
|
|
41
|
+
- Golden-contract tests now verify `hint` and `retryable` fields in error responses
|
|
42
|
+
- MCP server version string aligned with package version
|
|
43
|
+
- Repo description and topics updated (48 voices, 9 languages)
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- MCP handshake version was stuck at `0.2.1` — now aligned at `1.0.0`
|
|
48
|
+
- Error responses from `BusyError`, `RateLimitError`, `TimeoutError` now correctly report `retryable: true`
|
|
49
|
+
- Stale v2.x git tags deleted
|
|
50
|
+
- Dependabot cleaned (removed stale pip ecosystem entry)
|
|
51
|
+
|
|
52
|
+
## [0.2.1] - 2026-02-18
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- README in `@mcptoolshop/voice-soundboard-core` npm tarball still showed 12 voices — corrected to 48 voices, 9 languages
|
|
57
|
+
- Broken Development section in root README (stray `> Part of MCP Tool Shop` line inside code block)
|
|
58
|
+
|
|
59
|
+
## [0.2.0] - 2026-02-18
|
|
60
|
+
|
|
61
|
+
### Overview
|
|
62
|
+
|
|
63
|
+
**Multilingual expansion** — 48 voices across 9 languages.
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
|
|
67
|
+
- **48 voices** — expanded from 12 English-only to 48 across 9 languages
|
|
68
|
+
- **9 languages** — English US, English UK, Japanese, Mandarin Chinese, Spanish, French, Hindi, Italian, Brazilian Portuguese
|
|
69
|
+
- **`getVoicesByLanguage(language)`** — new helper in `@mcptoolshop/voice-soundboard-core` to filter voices by language code
|
|
70
|
+
- Language is auto-inferred by the synthesis backend from the voice ID prefix — no caller changes required
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
|
|
74
|
+
- `VoiceInfo.accent` field widened from `"american" | "british"` to `string` to accommodate new languages
|
|
75
|
+
- `VoiceInfo.language` values now use BCP-47 style codes (`"en-us"`, `"en-gb"`, `"ja"`, `"zh"`, etc.) instead of `"en"`
|
|
76
|
+
- Server version string updated to `0.2.0`
|
|
77
|
+
- Package descriptions updated to reflect 48 voices and 9 languages
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## [0.1.0] - 2026-02-13
|
|
82
|
+
|
|
83
|
+
### Overview
|
|
84
|
+
|
|
85
|
+
**Initial release** — Node.js/TypeScript MCP server for text-to-speech.
|
|
86
|
+
|
|
87
|
+
Complete rewrite from the original Python prototype into a pnpm monorepo with two
|
|
88
|
+
publishable npm packages: `@mcp-tool-shop/voice-soundboard-core` and
|
|
89
|
+
`@mcp-tool-shop/voice-soundboard-mcp`.
|
|
90
|
+
|
|
91
|
+
### Packages
|
|
92
|
+
|
|
93
|
+
- **@mcp-tool-shop/voice-soundboard-core** (v0.1.0) — Backend-agnostic core library
|
|
94
|
+
- **@mcp-tool-shop/voice-soundboard-mcp** (v0.1.0) — MCP server with CLI
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
#### MCP Tools
|
|
99
|
+
- `voice_speak` — Synthesize speech from text with voice, speed, format options
|
|
100
|
+
- `voice_dialogue` — Multi-speaker dialogue synthesis with cast mapping
|
|
101
|
+
- `voice_status` — Engine health, available voices, presets, backend info
|
|
102
|
+
- `voice_interrupt` — Stop/rollback active synthesis
|
|
103
|
+
- `voice_inner_monologue` — Ephemeral micro-utterances (ambient system, opt-in)
|
|
104
|
+
|
|
105
|
+
#### Core Features
|
|
106
|
+
- 12 approved voices (4 American female, 4 American male, 3 British female, 2 British male)
|
|
107
|
+
- 5 voice presets (narrator, announcer, whisper, storyteller, assistant)
|
|
108
|
+
- 8 emotion spans via `[happy]...[/happy]` inline markup
|
|
109
|
+
- SSML-lite parser (`<break>`, `<emphasis>`, `<prosody>`)
|
|
110
|
+
- SFX tags (`[ding]`, `[chime]`, `[whoosh]`, `[tada]`, `[error]`, `[click]`)
|
|
111
|
+
- Text chunking with sentence/paragraph boundaries
|
|
112
|
+
- WAV concatenation for multi-segment output
|
|
113
|
+
- Base64 and file-path artifact delivery modes
|
|
114
|
+
- Output directory sandboxing with path traversal protection
|
|
115
|
+
|
|
116
|
+
#### Security & Guardrails
|
|
117
|
+
- `SynthesisSemaphore` — configurable max concurrent synthesis (default 1)
|
|
118
|
+
- `ToolRateLimiter` — per-tool sliding window rate limit (30 calls/60s)
|
|
119
|
+
- `withTimeout` — per-request timeout (default 20s)
|
|
120
|
+
- Path traversal protection (resolveOutputDir with symlink checks)
|
|
121
|
+
- Secret/PII redaction in logs and error messages
|
|
122
|
+
- Synthesis result validation (WAV header, duration, file size)
|
|
123
|
+
- Output file retention cleanup (default 4 hours)
|
|
124
|
+
|
|
125
|
+
#### Backend System
|
|
126
|
+
- `Backend` interface with `synthesize()`, `voices()`, `health()`
|
|
127
|
+
- MockBackend (built-in, deterministic WAV generation)
|
|
128
|
+
- HTTP proxy backend (delegate to external TTS service)
|
|
129
|
+
- Python bridge backend (connect to Python Kokoro/Piper engines)
|
|
130
|
+
|
|
131
|
+
#### Developer Experience
|
|
132
|
+
- 342 tests (252 core + 90 server)
|
|
133
|
+
- Abuse battery (adversarial input testing)
|
|
134
|
+
- CI pipeline: Node.js 20+22 matrix, type-check, npm pack dry-run
|
|
135
|
+
- Dependabot for npm dependency updates
|
|
136
|
+
- Architecture invariant enforcement (engine never imports compiler)
|
|
137
|
+
|
|
138
|
+
### Architecture
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
@mcp-tool-shop/voice-soundboard-core
|
|
142
|
+
limits.ts SHIP_LIMITS consolidation
|
|
143
|
+
schemas.ts VoiceRequest, VoiceResponse, error codes
|
|
144
|
+
voices.ts Approved voice registry + presets
|
|
145
|
+
emotion.ts Emotion span parser
|
|
146
|
+
ssml/ SSML-lite parser
|
|
147
|
+
chunking/ Text chunker
|
|
148
|
+
sfx/ SFX tag parser
|
|
149
|
+
artifact.ts Output directory sandboxing
|
|
150
|
+
sandbox.ts Safe filenames, symlink checks
|
|
151
|
+
ambient.ts AmbientEmitter
|
|
152
|
+
redact.ts PII/secret redaction
|
|
153
|
+
|
|
154
|
+
@mcp-tool-shop/voice-soundboard-mcp
|
|
155
|
+
server.ts MCP tool registration + guardrails
|
|
156
|
+
cli.ts CLI entrypoint (stdio transport)
|
|
157
|
+
backend.ts Backend abstraction
|
|
158
|
+
concurrency.ts SynthesisSemaphore
|
|
159
|
+
rateLimit.ts ToolRateLimiter
|
|
160
|
+
timeout.ts withTimeout
|
|
161
|
+
retention.ts Output cleanup timer
|
|
162
|
+
validation.ts Result validation
|
|
163
|
+
redact.ts Server-level redaction
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Pre-0.1.0 (Python)
|
|
169
|
+
|
|
170
|
+
The original Python implementation (`voice_soundboard/`) with Compiler-Graph-Engine
|
|
171
|
+
architecture is preserved in the repository but is not part of the npm packages.
|
|
172
|
+
See git history for the full Python changelog.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mcp-tool-shop
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
19
|
<p align="center">
|
|
20
|
-
|
|
20
|
+
46 voices • 9 languages • 5 presets • 8 emotions • SSML-lite • SFX tags • multi-speaker dialogue<br>
|
|
21
21
|
Swappable TTS backends. Guardrails built in. Ships as a single <code>npx</code> command.
|
|
22
22
|
</p>
|
|
23
23
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
- **MCP native** — stdio transport, works with Claude Desktop, Cursor, and any MCP client
|
|
29
29
|
- **5 tools** — `voice_speak`, `voice_dialogue`, `voice_status`, `voice_interrupt`, `voice_inner_monologue`
|
|
30
|
-
- **
|
|
30
|
+
- **46 approved voices, 9 languages** — English (American + British), Japanese, Mandarin, Spanish, French, Hindi, Italian, Brazilian Portuguese. Curated presets: `narrator`, `announcer`, `whisper`, `storyteller`, `assistant`
|
|
31
31
|
- **Emotion spans** — 8 emotions via `[happy]...[/happy]` inline markup
|
|
32
32
|
- **SSML-lite** — `<break>`, `<emphasis>`, `<prosody>` without full SSML complexity
|
|
33
33
|
- **SFX tags** — `[ding]`, `[chime]`, `[whoosh]`, `[tada]`, `[error]`, `[click]` inline sound effects
|
|
@@ -133,7 +133,7 @@ category?: "thinking" # general | thinking | observation | debug
|
|
|
133
133
|
|
|
134
134
|
## Voices
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
46 voices across 9 languages. Language is auto-inferred from the voice ID prefix — no configuration required.
|
|
137
137
|
|
|
138
138
|
| Prefix | Language |
|
|
139
139
|
|--------|----------|
|
|
File without changes
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Voice Soundboard Python Bridge — NDJSON stdio protocol.
|
|
3
|
+
|
|
4
|
+
Auto-downloads Kokoro ONNX model + voices on first run.
|
|
5
|
+
Communicates with the Node.js MCP server via newline-delimited JSON on stdin/stdout.
|
|
6
|
+
|
|
7
|
+
Protocol:
|
|
8
|
+
IN: {"id": "...", "op": "health"}
|
|
9
|
+
OUT: {"id": "...", "ok": true, "model": "kokoro-v0.19"}
|
|
10
|
+
|
|
11
|
+
IN: {"id": "...", "op": "synthesize", "text": "Hello", "voice": "af_bella", "speed": 1.0,
|
|
12
|
+
"format": "wav", "artifact_mode": "base64"}
|
|
13
|
+
OUT: {"id": "...", "ok": true, "audio_bytes_base64": "...", "duration_ms": 1234,
|
|
14
|
+
"sample_rate": 24000, "format": "wav"}
|
|
15
|
+
|
|
16
|
+
IN: {"id": "...", "op": "interrupt"}
|
|
17
|
+
OUT: {"id": "...", "ok": true}
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import sys
|
|
22
|
+
import io
|
|
23
|
+
import base64
|
|
24
|
+
import struct
|
|
25
|
+
import os
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
GITHUB_RELEASE = "https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0"
|
|
29
|
+
MODEL_FILE = "kokoro-v1.0.onnx"
|
|
30
|
+
VOICES_FILE = "voices-v1.0.bin"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def ensure_deps():
|
|
34
|
+
"""Install kokoro-onnx if missing."""
|
|
35
|
+
try:
|
|
36
|
+
import kokoro_onnx # noqa: F401
|
|
37
|
+
except ImportError:
|
|
38
|
+
import subprocess
|
|
39
|
+
print("[bridge] Installing kokoro-onnx...", file=sys.stderr)
|
|
40
|
+
subprocess.check_call(
|
|
41
|
+
[sys.executable, "-m", "pip", "install", "--user", "-q", "kokoro-onnx"],
|
|
42
|
+
stdout=sys.stderr,
|
|
43
|
+
stderr=sys.stderr,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def download_file(url: str, dest: str):
|
|
48
|
+
"""Download a file with progress."""
|
|
49
|
+
import urllib.request
|
|
50
|
+
filename = os.path.basename(dest)
|
|
51
|
+
print(f"[bridge] Downloading {filename}...", file=sys.stderr)
|
|
52
|
+
urllib.request.urlretrieve(url, dest)
|
|
53
|
+
size_mb = os.path.getsize(dest) / (1024 * 1024)
|
|
54
|
+
print(f"[bridge] Downloaded {filename} ({size_mb:.0f} MB)", file=sys.stderr)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def download_model():
|
|
58
|
+
"""Download Kokoro ONNX model + voices from GitHub releases. Returns (model_path, voices_path)."""
|
|
59
|
+
cache_dir = os.path.join(os.path.expanduser("~"), ".cache", "voice-soundboard")
|
|
60
|
+
os.makedirs(cache_dir, exist_ok=True)
|
|
61
|
+
|
|
62
|
+
model_path = os.path.join(cache_dir, MODEL_FILE)
|
|
63
|
+
voices_path = os.path.join(cache_dir, VOICES_FILE)
|
|
64
|
+
|
|
65
|
+
if not os.path.exists(model_path):
|
|
66
|
+
download_file(f"{GITHUB_RELEASE}/{MODEL_FILE}", model_path)
|
|
67
|
+
|
|
68
|
+
if not os.path.exists(voices_path):
|
|
69
|
+
download_file(f"{GITHUB_RELEASE}/{VOICES_FILE}", voices_path)
|
|
70
|
+
|
|
71
|
+
print(f"[bridge] Model ready: {model_path}", file=sys.stderr)
|
|
72
|
+
return model_path, voices_path
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def pcm_to_wav(samples, sample_rate: int) -> bytes:
|
|
76
|
+
"""Convert float32 numpy array to WAV bytes."""
|
|
77
|
+
import numpy as np
|
|
78
|
+
|
|
79
|
+
# Clamp and convert to 16-bit PCM
|
|
80
|
+
pcm = np.clip(samples, -1.0, 1.0)
|
|
81
|
+
pcm = (pcm * 32767).astype(np.int16)
|
|
82
|
+
raw = pcm.tobytes()
|
|
83
|
+
|
|
84
|
+
# Build WAV header
|
|
85
|
+
buf = io.BytesIO()
|
|
86
|
+
num_channels = 1
|
|
87
|
+
bits_per_sample = 16
|
|
88
|
+
byte_rate = sample_rate * num_channels * bits_per_sample // 8
|
|
89
|
+
block_align = num_channels * bits_per_sample // 8
|
|
90
|
+
data_size = len(raw)
|
|
91
|
+
|
|
92
|
+
buf.write(b"RIFF")
|
|
93
|
+
buf.write(struct.pack("<I", 36 + data_size))
|
|
94
|
+
buf.write(b"WAVE")
|
|
95
|
+
buf.write(b"fmt ")
|
|
96
|
+
buf.write(struct.pack("<I", 16))
|
|
97
|
+
buf.write(struct.pack("<H", 1)) # PCM
|
|
98
|
+
buf.write(struct.pack("<H", num_channels))
|
|
99
|
+
buf.write(struct.pack("<I", sample_rate))
|
|
100
|
+
buf.write(struct.pack("<I", byte_rate))
|
|
101
|
+
buf.write(struct.pack("<H", block_align))
|
|
102
|
+
buf.write(struct.pack("<H", bits_per_sample))
|
|
103
|
+
buf.write(b"data")
|
|
104
|
+
buf.write(struct.pack("<I", data_size))
|
|
105
|
+
buf.write(raw)
|
|
106
|
+
|
|
107
|
+
return buf.getvalue()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def main():
|
|
111
|
+
ensure_deps()
|
|
112
|
+
|
|
113
|
+
from kokoro_onnx import Kokoro
|
|
114
|
+
|
|
115
|
+
model_path, voices_path = download_model()
|
|
116
|
+
kokoro = Kokoro(model_path, voices_path)
|
|
117
|
+
available_voices = kokoro.get_voices()
|
|
118
|
+
|
|
119
|
+
print(f"[bridge] Ready — {len(available_voices)} voices available", file=sys.stderr)
|
|
120
|
+
|
|
121
|
+
for line in sys.stdin:
|
|
122
|
+
line = line.strip()
|
|
123
|
+
if not line:
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
msg = json.loads(line)
|
|
128
|
+
except json.JSONDecodeError:
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
req_id = msg.get("id")
|
|
132
|
+
op = msg.get("op")
|
|
133
|
+
|
|
134
|
+
if op == "health":
|
|
135
|
+
resp = {"id": req_id, "ok": True, "model": "kokoro-v1.1-onnx", "voices": len(available_voices)}
|
|
136
|
+
sys.stdout.write(json.dumps(resp) + "\n")
|
|
137
|
+
sys.stdout.flush()
|
|
138
|
+
|
|
139
|
+
elif op == "synthesize":
|
|
140
|
+
try:
|
|
141
|
+
text = msg.get("text", "")
|
|
142
|
+
voice = msg.get("voice", "af_bella")
|
|
143
|
+
speed = float(msg.get("speed", 1.0))
|
|
144
|
+
artifact_mode = msg.get("artifact_mode", "base64")
|
|
145
|
+
|
|
146
|
+
# Validate voice
|
|
147
|
+
if voice not in available_voices:
|
|
148
|
+
# Try partial match
|
|
149
|
+
matches = [v for v in available_voices if v.startswith(voice)]
|
|
150
|
+
voice = matches[0] if matches else available_voices[0]
|
|
151
|
+
|
|
152
|
+
samples, sample_rate = kokoro.create(text, voice=voice, speed=speed)
|
|
153
|
+
wav_bytes = pcm_to_wav(samples, sample_rate)
|
|
154
|
+
duration_ms = int(len(samples) / sample_rate * 1000)
|
|
155
|
+
|
|
156
|
+
if artifact_mode == "base64":
|
|
157
|
+
resp = {
|
|
158
|
+
"id": req_id,
|
|
159
|
+
"ok": True,
|
|
160
|
+
"audio_bytes_base64": base64.b64encode(wav_bytes).decode(),
|
|
161
|
+
"duration_ms": duration_ms,
|
|
162
|
+
"sample_rate": sample_rate,
|
|
163
|
+
"format": "wav",
|
|
164
|
+
}
|
|
165
|
+
else:
|
|
166
|
+
output_dir = msg.get("output_dir", os.path.join(os.path.expanduser("~"), ".voice-soundboard"))
|
|
167
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
168
|
+
import uuid
|
|
169
|
+
audio_path = os.path.join(output_dir, f"vsmcp_{uuid.uuid4().hex[:8]}.wav")
|
|
170
|
+
with open(audio_path, "wb") as f:
|
|
171
|
+
f.write(wav_bytes)
|
|
172
|
+
resp = {
|
|
173
|
+
"id": req_id,
|
|
174
|
+
"ok": True,
|
|
175
|
+
"audio_path": audio_path,
|
|
176
|
+
"duration_ms": duration_ms,
|
|
177
|
+
"sample_rate": sample_rate,
|
|
178
|
+
"format": "wav",
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
sys.stdout.write(json.dumps(resp) + "\n")
|
|
182
|
+
sys.stdout.flush()
|
|
183
|
+
|
|
184
|
+
except Exception as e:
|
|
185
|
+
resp = {
|
|
186
|
+
"id": req_id,
|
|
187
|
+
"ok": False,
|
|
188
|
+
"error": {"code": "SYNTHESIS_FAILED", "message": str(e)},
|
|
189
|
+
}
|
|
190
|
+
sys.stdout.write(json.dumps(resp) + "\n")
|
|
191
|
+
sys.stdout.flush()
|
|
192
|
+
|
|
193
|
+
elif op == "interrupt":
|
|
194
|
+
resp = {"id": req_id, "ok": True}
|
|
195
|
+
sys.stdout.write(json.dumps(resp) + "\n")
|
|
196
|
+
sys.stdout.flush()
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
if __name__ == "__main__":
|
|
200
|
+
main()
|
package/dist/backend.d.ts
CHANGED
|
@@ -62,6 +62,7 @@ export declare class MockBackend implements Backend {
|
|
|
62
62
|
readonly model = "mock-silence";
|
|
63
63
|
readonly sampleRate = 24000;
|
|
64
64
|
health(): Promise<BackendHealth>;
|
|
65
|
+
interrupt(): Promise<void>;
|
|
65
66
|
synthesize(request: SynthesisRequest): Promise<SynthesisResult>;
|
|
66
67
|
}
|
|
67
68
|
//# sourceMappingURL=backend.d.ts.map
|
package/dist/backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAOzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAI3E,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IACjC,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAChE,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAID,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAOzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAI3E,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IACjC,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAChE,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAID,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CA2B/D;AAWD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAwD3E;AAID,qBAAa,WAAY,YAAW,OAAO;IACzC,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,QAAQ,CAAC,KAAK,SAAS;IAEjB,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IAIhC,UAAU,IAAI,OAAO,CAAC,eAAe,CAAC;CAG7C;AAyCD,qBAAa,WAAY,YAAW,OAAO;IACzC,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,QAAQ,CAAC,KAAK,QAAQ;IACtB,QAAQ,CAAC,KAAK,kBAAkB;IAChC,QAAQ,CAAC,UAAU,SAAS;IAEtB,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IAIhC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAI1B,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;CAwBtE"}
|
package/dist/backend.js
CHANGED
|
@@ -17,12 +17,18 @@ export function readBackendConfig(argv) {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
// Env vars (lower precedence than explicit flags)
|
|
20
|
-
|
|
20
|
+
// VOICE_SOUNDBOARD_TTS_URL is canonical; VOICE_SOUNDBOARD_HTTP_URL is an alias (DX-015)
|
|
21
|
+
config.ttsUrl = process.env.VOICE_SOUNDBOARD_TTS_URL
|
|
22
|
+
?? process.env.VOICE_SOUNDBOARD_HTTP_URL;
|
|
21
23
|
config.ttsToken = process.env.VOICE_SOUNDBOARD_TTS_TOKEN;
|
|
22
24
|
config.pythonCommand = process.env.VOICE_SOUNDBOARD_PYTHON;
|
|
23
25
|
config.pythonModule = process.env.VOICE_SOUNDBOARD_PYTHON_MODULE;
|
|
24
26
|
if (process.env.VOICE_SOUNDBOARD_HTTP_TIMEOUT) {
|
|
25
|
-
|
|
27
|
+
const parsed = parseInt(process.env.VOICE_SOUNDBOARD_HTTP_TIMEOUT, 10);
|
|
28
|
+
// MCP-010: Guard against NaN from invalid env var
|
|
29
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
30
|
+
config.httpTimeout = parsed;
|
|
31
|
+
}
|
|
26
32
|
}
|
|
27
33
|
return config;
|
|
28
34
|
}
|
|
@@ -49,7 +55,7 @@ export async function selectBackend(config) {
|
|
|
49
55
|
switch (config.backend) {
|
|
50
56
|
case "mock":
|
|
51
57
|
return new MockBackend();
|
|
52
|
-
case "http":
|
|
58
|
+
case "http": {
|
|
53
59
|
// Lazy import to avoid loading HTTP backend when not needed
|
|
54
60
|
const { HttpBackend } = await import("./backends/httpBackend.js");
|
|
55
61
|
return new HttpBackend({
|
|
@@ -57,6 +63,7 @@ export async function selectBackend(config) {
|
|
|
57
63
|
token: config.ttsToken,
|
|
58
64
|
timeout: config.httpTimeout,
|
|
59
65
|
});
|
|
66
|
+
}
|
|
60
67
|
case "python": {
|
|
61
68
|
const { PythonBackend } = await import("./backends/pythonBackend.js");
|
|
62
69
|
const pyBackend = new PythonBackend({
|
|
@@ -69,6 +76,9 @@ export async function selectBackend(config) {
|
|
|
69
76
|
}
|
|
70
77
|
case "none":
|
|
71
78
|
return new NoneBackend();
|
|
79
|
+
default:
|
|
80
|
+
// MCP-009: Reject unrecognized backend types
|
|
81
|
+
throw new Error(`Unknown backend type: ${JSON.stringify(config.backend)}. Valid types: mock, http, python, none`);
|
|
72
82
|
}
|
|
73
83
|
}
|
|
74
84
|
// Auto-detect: HTTP URL set?
|
|
@@ -158,6 +168,9 @@ export class MockBackend {
|
|
|
158
168
|
async health() {
|
|
159
169
|
return { ready: true, details: "Mock backend — returns silence" };
|
|
160
170
|
}
|
|
171
|
+
async interrupt() {
|
|
172
|
+
// Mock backend has no real synthesis to cancel — no-op.
|
|
173
|
+
}
|
|
161
174
|
async synthesize(request) {
|
|
162
175
|
const wav = generateMockWav();
|
|
163
176
|
if (request.artifact.mode === "base64") {
|
package/dist/backend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AA+C9C;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAc;IAC9C,MAAM,MAAM,GAAkB,EAAE,CAAC;IAEjC,yBAAyB;IACzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAgB,CAAC;QACjE,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,9 +21,12 @@ export declare class HttpBackend implements Backend {
|
|
|
21
21
|
private readonly token?;
|
|
22
22
|
private readonly timeout;
|
|
23
23
|
private readonly maxResponseSize;
|
|
24
|
+
/** Active fetch controller — aborted by interrupt(). */
|
|
25
|
+
private activeController;
|
|
24
26
|
constructor(config: HttpBackendConfig);
|
|
25
27
|
health(): Promise<BackendHealth>;
|
|
26
28
|
synthesize(request: SynthesisRequest): Promise<SynthesisResult>;
|
|
29
|
+
interrupt(): Promise<void>;
|
|
27
30
|
private buildHeaders;
|
|
28
31
|
private readResponseBody;
|
|
29
32
|
private parseResponse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpBackend.d.ts","sourceRoot":"","sources":["../../src/backends/httpBackend.ts"],"names":[],"mappings":"AAAA,iFAAiF;AAMjF,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAE5F,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAQD,2DAA2D;AAC3D,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,iBAAiB,GAAG,sBAAsB,GAAG,qBAAqB,EACxE,UAAU,CAAC,EAAE,MAAM;CAMtB;
|
|
1
|
+
{"version":3,"file":"httpBackend.d.ts","sourceRoot":"","sources":["../../src/backends/httpBackend.ts"],"names":[],"mappings":"AAAA,iFAAiF;AAMjF,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAE5F,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAQD,2DAA2D;AAC3D,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,iBAAiB,GAAG,sBAAsB,GAAG,qBAAqB,EACxE,UAAU,CAAC,EAAE,MAAM;CAMtB;AA2DD,qBAAa,WAAY,YAAW,OAAO;IACzC,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,wDAAwD;IACxD,OAAO,CAAC,gBAAgB,CAAgC;gBAE5C,MAAM,EAAE,iBAAiB;IAQ/B,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IA0BhC,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAoE/D,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAOhC,OAAO,CAAC,YAAY;YAQN,gBAAgB;YAyChB,aAAa;CA6I5B"}
|