ai-voice-bridge 0.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/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # ai-voice-bridge
2
+
3
+ npm shim for the [Voice Bridge](https://github.com/Tomorrow-You/voice-bridge) MCP server — multi-engine TTS for AI coding assistants.
4
+
5
+ ## What this package does
6
+
7
+ This is a thin Node.js wrapper that bootstraps the Python-based Voice Bridge MCP server. When you run `npx ai-voice-bridge`, it:
8
+
9
+ 1. Finds Python 3.10+ on your system
10
+ 2. Installs the `ai-voice-bridge[mcp]` pip package if not already present
11
+ 3. Launches the MCP server connected to stdio
12
+
13
+ ## Requirements
14
+
15
+ - **Node.js 16+** (for npx)
16
+ - **Python 3.10+** with **pip**
17
+ - **Audio player**: macOS has `afplay` built-in. Linux needs `mpv` or `ffmpeg`. Windows needs `ffmpeg` or `mpv`.
18
+ - **Audio output hardware**: speakers or headphones on the local machine
19
+
20
+ **Not supported**: headless servers, Docker containers, SSH sessions, and CI runners lack audio output. The MCP server will start, but `speak` commands will fail silently.
21
+
22
+ ## Usage
23
+
24
+ ### Claude Desktop / Cursor
25
+
26
+ Add to your MCP config:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "voice-bridge": {
32
+ "command": "npx",
33
+ "args": ["ai-voice-bridge"]
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### Claude Code
40
+
41
+ ```bash
42
+ claude mcp add voice-bridge -- npx ai-voice-bridge
43
+ ```
44
+
45
+ ## Troubleshooting
46
+
47
+ The shim prints diagnostic warnings to stderr on startup:
48
+
49
+ - **`ERROR: Python 3.10+ is required`** — Install Python with platform-specific instructions shown in the error
50
+ - **`ERROR: Found Python 3.x, but Python 3.10+ is required`** — Upgrade your Python installation
51
+ - **`ERROR: pip is not available`** — Install pip (e.g., `sudo apt install python3-pip` on Ubuntu)
52
+ - **`WARNING: No audio player detected`** — Install `mpv` or `ffmpeg` for audio playback
53
+ - **`WARNING: No display server or PulseAudio detected`** — You're likely in a headless environment where audio cannot play
54
+
55
+ ## License
56
+
57
+ MIT. See the [main repository](https://github.com/Tomorrow-You/voice-bridge) for details.
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * npm shim for Voice Bridge MCP server.
5
+ *
6
+ * Checks for Python 3.10+, installs the pip package if needed,
7
+ * then launches the MCP server connected to stdio.
8
+ *
9
+ * Usage in Claude Desktop / Cursor config:
10
+ * { "command": "npx", "args": ["ai-voice-bridge"] }
11
+ */
12
+
13
+ const { execFileSync, spawn } = require("child_process");
14
+ const os = require("os");
15
+
16
+ const MIN_PYTHON = [3, 10];
17
+
18
+ function warn(msg) {
19
+ process.stderr.write(`[voice-bridge] ${msg}\n`);
20
+ }
21
+
22
+ function findPython() {
23
+ let bestFound = null; // track any Python we find (even if too old)
24
+
25
+ for (const cmd of ["python3", "python"]) {
26
+ try {
27
+ const version = execFileSync(cmd, ["--version"], {
28
+ encoding: "utf-8",
29
+ stdio: ["ignore", "pipe", "pipe"],
30
+ }).trim();
31
+ const match = version.match(/Python (\d+)\.(\d+)/);
32
+ if (match) {
33
+ const major = parseInt(match[1], 10);
34
+ const minor = parseInt(match[2], 10);
35
+ if (
36
+ major > MIN_PYTHON[0] ||
37
+ (major === MIN_PYTHON[0] && minor >= MIN_PYTHON[1])
38
+ ) {
39
+ return { cmd, version };
40
+ }
41
+ // Python found but too old
42
+ bestFound = { cmd, version };
43
+ }
44
+ } catch {
45
+ // Command not found, try next
46
+ }
47
+ }
48
+ return bestFound ? { cmd: null, version: bestFound.version } : null;
49
+ }
50
+
51
+ function isPackageInstalled(python) {
52
+ try {
53
+ execFileSync(python, ["-c", "import voice_bridge"], { stdio: "ignore" });
54
+ return true;
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ function hasPip(python) {
61
+ try {
62
+ execFileSync(python, ["-m", "pip", "--version"], {
63
+ stdio: ["ignore", "pipe", "pipe"],
64
+ });
65
+ return true;
66
+ } catch {
67
+ return false;
68
+ }
69
+ }
70
+
71
+ function checkAudioEnvironment() {
72
+ const platform = os.platform();
73
+
74
+ if (platform === "darwin") {
75
+ // macOS always has afplay
76
+ return;
77
+ }
78
+
79
+ const players =
80
+ platform === "win32"
81
+ ? ["ffplay", "mpv"]
82
+ : ["mpv", "ffplay", "aplay", "paplay"];
83
+
84
+ for (const player of players) {
85
+ try {
86
+ execFileSync(platform === "win32" ? "where" : "which", [player], {
87
+ stdio: ["ignore", "pipe", "pipe"],
88
+ });
89
+ return; // found one
90
+ } catch {
91
+ // not found, try next
92
+ }
93
+ }
94
+
95
+ const installHint =
96
+ platform === "win32"
97
+ ? "Install ffmpeg (includes ffplay): https://ffmpeg.org/download.html\n" +
98
+ " Or install mpv: https://mpv.io/installation/"
99
+ : "Install an audio player:\n" +
100
+ " Ubuntu/Debian: sudo apt install mpv (or: sudo apt install ffmpeg)\n" +
101
+ " Fedora/RHEL: sudo dnf install mpv\n" +
102
+ " Arch: sudo pacman -S mpv";
103
+
104
+ warn(
105
+ "WARNING: No audio player detected.\n" +
106
+ " Voice Bridge requires mpv, ffplay, or another audio player to produce sound.\n" +
107
+ " The MCP server will start, but speak commands will fail silently.\n\n" +
108
+ ` ${installHint}\n`
109
+ );
110
+
111
+ // Check if we're likely headless (no DISPLAY on Linux, no audio device)
112
+ if (platform === "linux" && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY && !process.env.PULSE_SERVER) {
113
+ warn(
114
+ "WARNING: No display server or PulseAudio detected — this may be a headless environment.\n" +
115
+ " TTS audio playback requires a machine with speakers or audio output.\n" +
116
+ " Remote sessions (SSH, containers, CI) typically cannot play audio.\n"
117
+ );
118
+ }
119
+ }
120
+
121
+ function pythonInstallHint() {
122
+ const platform = os.platform();
123
+ if (platform === "darwin") {
124
+ return (
125
+ "Install Python on macOS:\n" +
126
+ " brew install python@3.12 (recommended)\n" +
127
+ " Or download from https://python.org/downloads/"
128
+ );
129
+ } else if (platform === "win32") {
130
+ return (
131
+ "Install Python on Windows:\n" +
132
+ " winget install Python.Python.3.12\n" +
133
+ " Or download from https://python.org/downloads/"
134
+ );
135
+ } else {
136
+ return (
137
+ "Install Python on Linux:\n" +
138
+ " Ubuntu/Debian: sudo apt install python3 python3-pip\n" +
139
+ " Fedora/RHEL: sudo dnf install python3 python3-pip\n" +
140
+ " Arch: sudo pacman -S python python-pip\n" +
141
+ " Or download from https://python.org/downloads/"
142
+ );
143
+ }
144
+ }
145
+
146
+ function main() {
147
+ const result = findPython();
148
+
149
+ if (!result || !result.cmd) {
150
+ if (result && result.version) {
151
+ // Python found but too old
152
+ warn(
153
+ `ERROR: Found ${result.version}, but Python ${MIN_PYTHON.join(".")}+ is required.\n\n` +
154
+ ` ${pythonInstallHint()}\n`
155
+ );
156
+ } else {
157
+ // No Python at all
158
+ warn(
159
+ `ERROR: Python ${MIN_PYTHON.join(".")}+ is required but not found on this system.\n\n` +
160
+ ` ${pythonInstallHint()}\n`
161
+ );
162
+ }
163
+ process.exit(1);
164
+ }
165
+
166
+ const python = result.cmd;
167
+
168
+ // Check audio environment before proceeding
169
+ checkAudioEnvironment();
170
+
171
+ if (!isPackageInstalled(python)) {
172
+ if (!hasPip(python)) {
173
+ const platform = os.platform();
174
+ const pipHint =
175
+ platform === "linux"
176
+ ? " Ubuntu/Debian: sudo apt install python3-pip\n" +
177
+ " Fedora/RHEL: sudo dnf install python3-pip"
178
+ : ` ${python} -m ensurepip --upgrade`;
179
+ warn(
180
+ "ERROR: pip is not available. Install pip first:\n" +
181
+ ` ${pipHint}\n\n` +
182
+ "Then retry, or install manually:\n" +
183
+ ` ${python} -m pip install "ai-voice-bridge[mcp]"\n`
184
+ );
185
+ process.exit(1);
186
+ }
187
+
188
+ warn("Installing ai-voice-bridge[mcp]...");
189
+ try {
190
+ execFileSync(python, ["-m", "pip", "install", "ai-voice-bridge[mcp]"], {
191
+ stdio: "inherit",
192
+ });
193
+ } catch {
194
+ warn(
195
+ "Failed to install ai-voice-bridge. Try manually:\n" +
196
+ ` ${python} -m pip install "ai-voice-bridge[mcp]"\n`
197
+ );
198
+ process.exit(1);
199
+ }
200
+ }
201
+
202
+ // Launch the MCP server, connecting stdio directly
203
+ const child = spawn(python, ["-m", "voice_bridge.mcp.server"], {
204
+ stdio: "inherit",
205
+ });
206
+
207
+ child.on("error", (err) => {
208
+ warn(`Failed to start MCP server: ${err.message}`);
209
+ process.exit(1);
210
+ });
211
+
212
+ child.on("exit", (code) => {
213
+ process.exit(code ?? 0);
214
+ });
215
+ }
216
+
217
+ main();
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "ai-voice-bridge",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Voice Bridge — multi-engine TTS for AI coding assistants",
5
+ "author": "Tomorrow You LLC",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/Tomorrow-You/voice-bridge"
10
+ },
11
+ "keywords": ["mcp", "tts", "text-to-speech", "claude", "voice", "ai-assistant"],
12
+ "bin": {
13
+ "ai-voice-bridge": "bin/ai-voice-bridge-mcp.js"
14
+ },
15
+ "files": ["bin/", "README.md"],
16
+ "engines": {
17
+ "node": ">=16"
18
+ }
19
+ }