@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.
Files changed (69) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/LICENSE +21 -0
  3. package/README.md +3 -3
  4. package/backend-python/soundboard_bridge/__init__.py +0 -0
  5. package/backend-python/soundboard_bridge/__main__.py +200 -0
  6. package/backend-python/soundboard_bridge/__pycache__/__init__.cpython-314.pyc +0 -0
  7. package/backend-python/soundboard_bridge/__pycache__/__main__.cpython-314.pyc +0 -0
  8. package/dist/backend.d.ts +1 -0
  9. package/dist/backend.d.ts.map +1 -1
  10. package/dist/backend.js +16 -3
  11. package/dist/backend.js.map +1 -1
  12. package/dist/backends/httpBackend.d.ts +3 -0
  13. package/dist/backends/httpBackend.d.ts.map +1 -1
  14. package/dist/backends/httpBackend.js +111 -4
  15. package/dist/backends/httpBackend.js.map +1 -1
  16. package/dist/backends/pythonBackend.d.ts +3 -1
  17. package/dist/backends/pythonBackend.d.ts.map +1 -1
  18. package/dist/backends/pythonBackend.js +72 -6
  19. package/dist/backends/pythonBackend.js.map +1 -1
  20. package/dist/cli.js +204 -3
  21. package/dist/cli.js.map +1 -1
  22. package/dist/rateLimit.d.ts +2 -0
  23. package/dist/rateLimit.d.ts.map +1 -1
  24. package/dist/rateLimit.js +14 -0
  25. package/dist/rateLimit.js.map +1 -1
  26. package/dist/server.d.ts +1 -1
  27. package/dist/server.d.ts.map +1 -1
  28. package/dist/server.js +123 -17
  29. package/dist/server.js.map +1 -1
  30. package/dist/sessionConfig.d.ts +14 -0
  31. package/dist/sessionConfig.d.ts.map +1 -0
  32. package/dist/sessionConfig.js +23 -0
  33. package/dist/sessionConfig.js.map +1 -0
  34. package/dist/synthesisRegistry.d.ts +25 -0
  35. package/dist/synthesisRegistry.d.ts.map +1 -0
  36. package/dist/synthesisRegistry.js +49 -0
  37. package/dist/synthesisRegistry.js.map +1 -0
  38. package/dist/tools/voiceCleanup.d.ts +16 -0
  39. package/dist/tools/voiceCleanup.d.ts.map +1 -0
  40. package/dist/tools/voiceCleanup.js +52 -0
  41. package/dist/tools/voiceCleanup.js.map +1 -0
  42. package/dist/tools/voiceConfig.d.ts +14 -0
  43. package/dist/tools/voiceConfig.d.ts.map +1 -0
  44. package/dist/tools/voiceConfig.js +14 -0
  45. package/dist/tools/voiceConfig.js.map +1 -0
  46. package/dist/tools/voiceDialogue.d.ts.map +1 -1
  47. package/dist/tools/voiceDialogue.js +4 -0
  48. package/dist/tools/voiceDialogue.js.map +1 -1
  49. package/dist/tools/voiceInterrupt.d.ts +2 -1
  50. package/dist/tools/voiceInterrupt.d.ts.map +1 -1
  51. package/dist/tools/voiceInterrupt.js +30 -5
  52. package/dist/tools/voiceInterrupt.js.map +1 -1
  53. package/dist/tools/voicePlay.d.ts +16 -0
  54. package/dist/tools/voicePlay.d.ts.map +1 -0
  55. package/dist/tools/voicePlay.js +99 -0
  56. package/dist/tools/voicePlay.js.map +1 -0
  57. package/dist/tools/voiceQueue.d.ts +31 -0
  58. package/dist/tools/voiceQueue.d.ts.map +1 -0
  59. package/dist/tools/voiceQueue.js +136 -0
  60. package/dist/tools/voiceQueue.js.map +1 -0
  61. package/dist/tools/voiceSpeak.d.ts +2 -0
  62. package/dist/tools/voiceSpeak.d.ts.map +1 -1
  63. package/dist/tools/voiceSpeak.js +47 -10
  64. package/dist/tools/voiceSpeak.js.map +1 -1
  65. package/dist/tools/voiceStatus.d.ts +25 -1
  66. package/dist/tools/voiceStatus.d.ts.map +1 -1
  67. package/dist/tools/voiceStatus.js +19 -3
  68. package/dist/tools/voiceStatus.js.map +1 -1
  69. 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` &mdash; configurable max concurrent synthesis (default 1)
118
+ - `ToolRateLimiter` &mdash; per-tool sliding window rate limit (30 calls/60s)
119
+ - `withTimeout` &mdash; 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
- 48 voices &bull; 9 languages &bull; 5 presets &bull; 8 emotions &bull; SSML-lite &bull; SFX tags &bull; multi-speaker dialogue<br>
20
+ 46 voices &bull; 9 languages &bull; 5 presets &bull; 8 emotions &bull; SSML-lite &bull; SFX tags &bull; 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** &mdash; stdio transport, works with Claude Desktop, Cursor, and any MCP client
29
29
  - **5 tools** &mdash; `voice_speak`, `voice_dialogue`, `voice_status`, `voice_interrupt`, `voice_inner_monologue`
30
- - **48 approved voices, 9 languages** &mdash; English (American + British), Japanese, Mandarin, Spanish, French, Hindi, Italian, Brazilian Portuguese. Curated presets: `narrator`, `announcer`, `whisper`, `storyteller`, `assistant`
30
+ - **46 approved voices, 9 languages** &mdash; English (American + British), Japanese, Mandarin, Spanish, French, Hindi, Italian, Brazilian Portuguese. Curated presets: `narrator`, `announcer`, `whisper`, `storyteller`, `assistant`
31
31
  - **Emotion spans** &mdash; 8 emotions via `[happy]...[/happy]` inline markup
32
32
  - **SSML-lite** &mdash; `<break>`, `<emphasis>`, `<prosody>` without full SSML complexity
33
33
  - **SFX tags** &mdash; `[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
- 48 voices across 9 languages. Language is auto-inferred from the voice ID prefix — no configuration required.
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
@@ -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,CAqB/D;AAWD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAoD3E;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,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;CAwBtE"}
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
- config.ttsUrl = process.env.VOICE_SOUNDBOARD_TTS_URL;
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
- config.httpTimeout = parseInt(process.env.VOICE_SOUNDBOARD_HTTP_TIMEOUT, 10);
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") {
@@ -1 +1 @@
1
- {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
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;AAKD,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;gBAE7B,MAAM,EAAE,iBAAiB;IAQ/B,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IA0BhC,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAiErE,OAAO,CAAC,YAAY;YAQN,gBAAgB;YAyChB,aAAa;CAoF5B"}
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"}