whisper-windows-mcp 1.4.2 → 1.5.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/dist/index.js +88 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextpro
|
|
|
10
10
|
import { execFile } from "child_process";
|
|
11
11
|
import { existsSync, unlinkSync, readdirSync, writeFileSync, readFileSync } from "fs";
|
|
12
12
|
import { cpus, tmpdir } from "os";
|
|
13
|
-
import { join, extname, basename } from "path";
|
|
13
|
+
import { join, extname, basename, dirname } from "path";
|
|
14
14
|
import { promisify } from "util";
|
|
15
15
|
const execFileAsync = promisify(execFile);
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
@@ -53,6 +53,48 @@ async function isWhisperRunning() {
|
|
|
53
53
|
return false;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
async function detectGpus() {
|
|
57
|
+
try {
|
|
58
|
+
const { stdout } = await execFileAsync("wmic", ["path", "win32_VideoController", "get", "name,AdapterRAM", "/format:csv"], { windowsHide: true });
|
|
59
|
+
const gpus = [];
|
|
60
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
61
|
+
const trimmed = line.trim();
|
|
62
|
+
if (!trimmed || trimmed.startsWith("Node") || trimmed.startsWith(",AdapterRAM"))
|
|
63
|
+
continue;
|
|
64
|
+
const parts = trimmed.split(",");
|
|
65
|
+
if (parts.length < 3)
|
|
66
|
+
continue;
|
|
67
|
+
const vramBytes = parseInt(parts[1] ?? "0", 10) || 0;
|
|
68
|
+
const name = (parts[2] ?? "").trim();
|
|
69
|
+
if (name && name !== "Name")
|
|
70
|
+
gpus.push({ name, vramBytes });
|
|
71
|
+
}
|
|
72
|
+
return gpus;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function formatVram(bytes) {
|
|
79
|
+
if (!bytes || bytes < 1024 * 1024)
|
|
80
|
+
return "Unknown";
|
|
81
|
+
const gb = bytes / (1024 * 1024 * 1024);
|
|
82
|
+
return gb >= 1 ? `${gb.toFixed(1)} GB` : `${Math.round(bytes / (1024 * 1024))} MB`;
|
|
83
|
+
}
|
|
84
|
+
function recommendedModel(vramBytes) {
|
|
85
|
+
const gb = vramBytes / (1024 * 1024 * 1024);
|
|
86
|
+
if (gb >= 6)
|
|
87
|
+
return "large-v3 (ggml-large-v3.bin) — fits comfortably in your VRAM";
|
|
88
|
+
if (gb >= 4)
|
|
89
|
+
return "medium.en (ggml-medium.en.bin) — good fit for your VRAM";
|
|
90
|
+
if (gb >= 2)
|
|
91
|
+
return "small.en (ggml-small.en.bin) — safe choice for your VRAM";
|
|
92
|
+
return "base.en (ggml-base.en.bin) — recommended for limited VRAM";
|
|
93
|
+
}
|
|
94
|
+
function hasVulkanDll() {
|
|
95
|
+
const whisperDir = dirname(WHISPER_CLI_PATH);
|
|
96
|
+
return existsSync(join(whisperDir, "ggml-vulkan.dll"));
|
|
97
|
+
}
|
|
56
98
|
function needsConversion(filePath) {
|
|
57
99
|
return !NATIVE_EXTENSIONS.includes(extname(filePath).toLowerCase());
|
|
58
100
|
}
|
|
@@ -144,7 +186,7 @@ function getFiles(dir, recursive) {
|
|
|
144
186
|
// ---------------------------------------------------------------------------
|
|
145
187
|
// MCP Server
|
|
146
188
|
// ---------------------------------------------------------------------------
|
|
147
|
-
const server = new Server({ name: "whisper-windows-mcp", version: "1.
|
|
189
|
+
const server = new Server({ name: "whisper-windows-mcp", version: "1.5.0" }, { capabilities: { tools: {} } });
|
|
148
190
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
149
191
|
tools: [
|
|
150
192
|
{
|
|
@@ -216,6 +258,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
216
258
|
description: "Verify whisper-cli.exe, model, and FFmpeg are all available. Run this first if anything fails.",
|
|
217
259
|
inputSchema: { type: "object", properties: {} },
|
|
218
260
|
},
|
|
261
|
+
{
|
|
262
|
+
name: "check_system",
|
|
263
|
+
description: "Detect GPU hardware and verify Vulkan acceleration is available. " +
|
|
264
|
+
"Reports GPU name, VRAM, whether the Vulkan binary is installed, " +
|
|
265
|
+
"and recommends the best Whisper model for your hardware. " +
|
|
266
|
+
"Run this if you want to confirm GPU acceleration is working or diagnose why it isn't.",
|
|
267
|
+
inputSchema: { type: "object", properties: {} },
|
|
268
|
+
},
|
|
219
269
|
],
|
|
220
270
|
}));
|
|
221
271
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -247,6 +297,41 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
247
297
|
};
|
|
248
298
|
}
|
|
249
299
|
// -------------------------------------------------------------------------
|
|
300
|
+
// check_system
|
|
301
|
+
// -------------------------------------------------------------------------
|
|
302
|
+
if (name === "check_system") {
|
|
303
|
+
const vulkan = hasVulkanDll();
|
|
304
|
+
const gpus = await detectGpus();
|
|
305
|
+
let gpuLines = "";
|
|
306
|
+
if (gpus.length === 0) {
|
|
307
|
+
gpuLines = "⚠️ No GPU detected via wmic — this may indicate a driver issue.\n";
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
for (const gpu of gpus) {
|
|
311
|
+
const vramStr = formatVram(gpu.vramBytes);
|
|
312
|
+
gpuLines += `🖥️ GPU: ${gpu.name}\n`;
|
|
313
|
+
gpuLines += `💾 VRAM: ${vramStr} (reported by Windows — may be half of actual on AMD cards)\n`;
|
|
314
|
+
if (gpu.vramBytes > 0) {
|
|
315
|
+
gpuLines += `📦 Recommended model: ${recommendedModel(gpu.vramBytes)}\n`;
|
|
316
|
+
}
|
|
317
|
+
gpuLines += "\n";
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const vulkanLine = vulkan
|
|
321
|
+
? `✅ Vulkan binary: ggml-vulkan.dll found — GPU acceleration is active`
|
|
322
|
+
: `❌ Vulkan binary: ggml-vulkan.dll NOT found — whisper is running CPU-only\n\n` +
|
|
323
|
+
` To enable GPU acceleration:\n` +
|
|
324
|
+
` Download whisper-vulkan-win-x64.zip from:\n` +
|
|
325
|
+
` https://github.com/eviscerations/whisper-windows-mcp/releases\n` +
|
|
326
|
+
` Extract to: ${dirname(WHISPER_CLI_PATH)}`;
|
|
327
|
+
return {
|
|
328
|
+
content: [{
|
|
329
|
+
type: "text",
|
|
330
|
+
text: `System check\n${"─".repeat(40)}\n\n${gpuLines}${vulkanLine}`,
|
|
331
|
+
}],
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
// -------------------------------------------------------------------------
|
|
250
335
|
// transcribe_audio
|
|
251
336
|
// -------------------------------------------------------------------------
|
|
252
337
|
if (name === "transcribe_audio") {
|
|
@@ -391,7 +476,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
391
476
|
async function main() {
|
|
392
477
|
const transport = new StdioServerTransport();
|
|
393
478
|
await server.connect(transport);
|
|
394
|
-
console.error(`whisper-windows-mcp v1.
|
|
479
|
+
console.error(`whisper-windows-mcp v1.5.0 running | threads: ${WHISPER_THREADS}/${SYSTEM_THREADS}`);
|
|
395
480
|
}
|
|
396
481
|
main().catch((err) => {
|
|
397
482
|
console.error("Fatal error:", err);
|
package/package.json
CHANGED