voice-mcp-server 0.1.0 → 0.1.2

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 CHANGED
@@ -121,15 +121,14 @@ pip install -r requirements.txt
121
121
 
122
122
  ### 3. Install the NPM Bridge
123
123
 
124
- Install the package globally, or simply rely on `npx` when configuring your client:
124
+ You can run the server directly via `npx` without installing it globally, or install it globally via `npm`:
125
125
 
126
126
  ```bash
127
- # Build the TypeScript entry point
128
- npm install
129
- npm run build
130
-
131
127
  # Install globally
132
- npm install -g .
128
+ npm install -g voice-mcp-server
129
+
130
+ # Or run directly via npx
131
+ npx -y voice-mcp-server
133
132
  ```
134
133
 
135
134
  -----
@@ -142,7 +141,7 @@ You can seamlessly plug Voice MCP Server into any standard MCP-compatible client
142
141
 
143
142
  Add the server to your global configuration:
144
143
  ```bash
145
- gemini mcp add voice-mcp-server node /absolute/path/to/voice_mcp_server/build/index.js
144
+ gemini mcp add voice-mcp-server npx -y voice-mcp-server
146
145
  ```
147
146
 
148
147
  ### For Cursor
@@ -151,7 +150,7 @@ gemini mcp add voice-mcp-server node /absolute/path/to/voice_mcp_server/build/in
151
150
  2. Click **+ Add New MCP Server**
152
151
  3. **Name:** `Voice`
153
152
  4. **Type:** `command`
154
- 5. **Command:** `node /absolute/path/to/voice_mcp_server/build/index.js`
153
+ 5. **Command:** `npx -y voice-mcp-server`
155
154
 
156
155
  ### For Claude Desktop
157
156
 
@@ -161,8 +160,8 @@ Add the following to your `claude_desktop_config.json` (usually located at `~/Li
161
160
  {
162
161
  "mcpServers": {
163
162
  "voice-mcp": {
164
- "command": "node",
165
- "args": ["/absolute/path/to/voice_mcp_server/build/index.js"]
163
+ "command": "npx",
164
+ "args": ["-y", "voice-mcp-server"]
166
165
  }
167
166
  }
168
167
  }
package/build/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { spawn } from "node:child_process";
2
+ import { spawn, spawnSync } from "node:child_process";
3
3
  import { join, dirname } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { existsSync } from "node:fs";
@@ -10,31 +10,59 @@ const __dirname = dirname(__filename);
10
10
  const projectRoot = join(__dirname, "..");
11
11
  // Path to the Python script
12
12
  const pythonScriptPath = join(projectRoot, "src", "mcp_server.py");
13
+ const venvPath = join(projectRoot, "venv");
14
+ const venvPythonPath = join(venvPath, "bin", "python3");
15
+ const requirementsPath = join(projectRoot, "requirements.txt");
13
16
  /**
14
- * Locate the best Python executable to use.
15
- * Priority:
16
- * 1. Local venv inside the project
17
- * 2. System python3
17
+ * Strips npm/npx specific environment variables that can break Python virtual environments.
18
18
  */
19
- function getPythonExecutable() {
20
- const venvPath = join(projectRoot, "venv", "bin", "python3");
21
- if (existsSync(venvPath)) {
22
- return venvPath;
19
+ function cleanEnv() {
20
+ const env = { ...process.env, PYTHONUNBUFFERED: "1" };
21
+ for (const key in env) {
22
+ if (key.toLowerCase().startsWith("npm_")) {
23
+ delete env[key];
24
+ }
25
+ }
26
+ return env;
27
+ }
28
+ /**
29
+ * Ensures the Python virtual environment exists and dependencies are installed.
30
+ */
31
+ function ensurePythonEnvironment() {
32
+ if (!existsSync(venvPath)) {
33
+ console.error("Voice MCP: Initializing Python virtual environment. This may take a minute...");
34
+ // Create the virtual environment
35
+ const venvResult = spawnSync("python3", ["-m", "venv", "venv"], {
36
+ cwd: projectRoot,
37
+ stdio: "inherit",
38
+ env: cleanEnv()
39
+ });
40
+ if (venvResult.status !== 0) {
41
+ console.error("Voice MCP: Failed to create Python virtual environment.");
42
+ process.exit(1);
43
+ }
44
+ console.error("Voice MCP: Installing ML dependencies (silero-vad, mlx-whisper, kokoro, etc.)...");
45
+ // Install requirements
46
+ const pipResult = spawnSync(venvPythonPath, ["-m", "pip", "install", "-r", requirementsPath], {
47
+ cwd: projectRoot,
48
+ stdio: "inherit",
49
+ env: cleanEnv()
50
+ });
51
+ if (pipResult.status !== 0) {
52
+ console.error("Voice MCP: Failed to install Python dependencies.");
53
+ process.exit(1);
54
+ }
55
+ console.error("Voice MCP: Environment setup complete!");
23
56
  }
24
- return "python3";
25
57
  }
26
- const pythonExecutable = getPythonExecutable();
27
58
  /**
28
59
  * Start the Python MCP Server and bridge standard I/O.
29
60
  */
30
61
  function startBridge() {
31
- const pythonProcess = spawn(pythonExecutable, [pythonScriptPath], {
62
+ ensurePythonEnvironment();
63
+ const pythonProcess = spawn(venvPythonPath, [pythonScriptPath], {
32
64
  stdio: ["pipe", "pipe", "inherit"],
33
- env: {
34
- ...process.env,
35
- // Ensure Python output isn't buffered
36
- PYTHONUNBUFFERED: "1",
37
- },
65
+ env: cleanEnv()
38
66
  });
39
67
  // Pipe our stdin into Python's stdin
40
68
  process.stdin.pipe(pythonProcess.stdin);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "voice-mcp-server",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "An MCP server to allow LLMs to speak and listen via bidirectional voice loops",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { spawn } from "node:child_process";
3
+ import { spawn, spawnSync } from "node:child_process";
4
4
  import { join, dirname } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { existsSync } from "node:fs";
@@ -14,34 +14,69 @@ const projectRoot = join(__dirname, "..");
14
14
 
15
15
  // Path to the Python script
16
16
  const pythonScriptPath = join(projectRoot, "src", "mcp_server.py");
17
+ const venvPath = join(projectRoot, "venv");
18
+ const venvPythonPath = join(venvPath, "bin", "python3");
19
+ const requirementsPath = join(projectRoot, "requirements.txt");
17
20
 
18
21
  /**
19
- * Locate the best Python executable to use.
20
- * Priority:
21
- * 1. Local venv inside the project
22
- * 2. System python3
22
+ * Strips npm/npx specific environment variables that can break Python virtual environments.
23
23
  */
24
- function getPythonExecutable(): string {
25
- const venvPath = join(projectRoot, "venv", "bin", "python3");
26
- if (existsSync(venvPath)) {
27
- return venvPath;
24
+ function cleanEnv(): NodeJS.ProcessEnv {
25
+ const env: Record<string, string | undefined> = { ...process.env, PYTHONUNBUFFERED: "1" };
26
+ for (const key in env) {
27
+ if (key.toLowerCase().startsWith("npm_")) {
28
+ delete env[key];
29
+ }
28
30
  }
29
- return "python3";
31
+ return env as NodeJS.ProcessEnv;
30
32
  }
31
33
 
32
- const pythonExecutable = getPythonExecutable();
34
+ /**
35
+ * Ensures the Python virtual environment exists and dependencies are installed.
36
+ */
37
+ function ensurePythonEnvironment() {
38
+ if (!existsSync(venvPath)) {
39
+ console.error("Voice MCP: Initializing Python virtual environment. This may take a minute...");
40
+
41
+ // Create the virtual environment
42
+ const venvResult = spawnSync("python3", ["-m", "venv", "venv"], {
43
+ cwd: projectRoot,
44
+ stdio: "inherit",
45
+ env: cleanEnv()
46
+ });
47
+
48
+ if (venvResult.status !== 0) {
49
+ console.error("Voice MCP: Failed to create Python virtual environment.");
50
+ process.exit(1);
51
+ }
52
+
53
+ console.error("Voice MCP: Installing ML dependencies (silero-vad, mlx-whisper, kokoro, etc.)...");
54
+
55
+ // Install requirements
56
+ const pipResult = spawnSync(venvPythonPath, ["-m", "pip", "install", "-r", requirementsPath], {
57
+ cwd: projectRoot,
58
+ stdio: "inherit",
59
+ env: cleanEnv()
60
+ });
61
+
62
+ if (pipResult.status !== 0) {
63
+ console.error("Voice MCP: Failed to install Python dependencies.");
64
+ process.exit(1);
65
+ }
66
+
67
+ console.error("Voice MCP: Environment setup complete!");
68
+ }
69
+ }
33
70
 
34
71
  /**
35
72
  * Start the Python MCP Server and bridge standard I/O.
36
73
  */
37
74
  function startBridge() {
38
- const pythonProcess = spawn(pythonExecutable, [pythonScriptPath], {
75
+ ensurePythonEnvironment();
76
+
77
+ const pythonProcess = spawn(venvPythonPath, [pythonScriptPath], {
39
78
  stdio: ["pipe", "pipe", "inherit"],
40
- env: {
41
- ...process.env,
42
- // Ensure Python output isn't buffered
43
- PYTHONUNBUFFERED: "1",
44
- },
79
+ env: cleanEnv()
45
80
  });
46
81
 
47
82
  // Pipe our stdin into Python's stdin
@@ -61,3 +96,4 @@ function startBridge() {
61
96
  }
62
97
 
63
98
  startBridge();
99
+