We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mbailey/voicemode'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""Uninstall tool for Whisper STT service."""
import os
import shutil
import subprocess
import platform
import logging
from pathlib import Path
from typing import Dict, Any, Union
from voice_mode.server import mcp
from voice_mode.config import BASE_DIR
from voice_mode.utils.services.common import find_process_by_port
logger = logging.getLogger("voicemode")
@mcp.tool()
async def whisper_uninstall(
remove_models: Union[bool, str] = False,
remove_all_data: Union[bool, str] = False
) -> Dict[str, Any]:
"""Uninstall whisper.cpp and optionally remove models and data.
This tool will:
1. Stop any running Whisper service
2. Remove service configurations (launchd/systemd)
3. Remove the whisper.cpp installation
4. Optionally remove downloaded models
5. Optionally remove all Whisper-related data
Args:
remove_models: Also remove downloaded Whisper models (default: False)
remove_all_data: Remove all Whisper data including logs and transcriptions (default: False)
Returns:
Dictionary with uninstall status and details
"""
system = platform.system()
removed_items = []
errors = []
try:
# 1. Stop any running Whisper service
logger.info("Checking for running Whisper service...")
proc = find_process_by_port(2022)
if proc:
try:
logger.info(f"Stopping Whisper service (PID: {proc.pid})...")
proc.terminate()
proc.wait(timeout=5)
removed_items.append("Stopped running Whisper service")
except Exception as e:
logger.warning(f"Failed to stop Whisper service: {e}")
# 2. Remove service configurations
if system == "Darwin":
# Remove launchd plist files (check both old and new names)
plist_names = [
"com.voicemode.whisper.plist",
"com.voicemode.whisper-server.plist" # Old name for compatibility
]
for plist_name in plist_names:
plist_path = Path.home() / "Library" / "LaunchAgents" / plist_name
if plist_path.exists():
try:
# Unload if loaded
subprocess.run(
["launchctl", "unload", str(plist_path)],
capture_output=True
)
# Remove file
plist_path.unlink()
removed_items.append(f"Removed launchd configuration: {plist_name}")
logger.info(f"Removed {plist_path}")
except Exception as e:
errors.append(f"Failed to remove {plist_path}: {e}")
elif system == "Linux":
# Remove systemd service files
service_names = [
"voicemode-whisper.service",
"whisper-server.service" # Old name for compatibility
]
systemd_user_dir = Path.home() / ".config" / "systemd" / "user"
for service_name in service_names:
service_path = systemd_user_dir / service_name
if service_path.exists():
try:
# Stop and disable service
subprocess.run(
["systemctl", "--user", "stop", service_name],
capture_output=True,
stderr=subprocess.DEVNULL
)
subprocess.run(
["systemctl", "--user", "disable", service_name],
capture_output=True,
stderr=subprocess.DEVNULL
)
# Remove file
service_path.unlink()
# Reload systemd
subprocess.run(["systemctl", "--user", "daemon-reload"], check=True)
removed_items.append(f"Removed systemd service: {service_name}")
logger.info(f"Removed {service_path}")
except Exception as e:
errors.append(f"Failed to remove {service_path}: {e}")
# 3. Remove whisper.cpp installation
# Check new location first, then legacy location
whisper_dirs = [
BASE_DIR / "services" / "whisper", # New location
BASE_DIR / "whisper.cpp" # Legacy location
]
for whisper_dir in whisper_dirs:
if whisper_dir.exists():
try:
shutil.rmtree(whisper_dir)
removed_items.append(f"Removed whisper.cpp installation: {whisper_dir}")
logger.info(f"Removed {whisper_dir}")
except Exception as e:
errors.append(f"Failed to remove {whisper_dir}: {e}")
# 4. Optionally remove models
if remove_models:
models_dir = BASE_DIR / "models" / "whisper"
if models_dir.exists():
try:
shutil.rmtree(models_dir)
removed_items.append(f"Removed Whisper models: {models_dir}")
logger.info(f"Removed {models_dir}")
except Exception as e:
errors.append(f"Failed to remove {models_dir}: {e}")
# 5. Optionally remove all data
if remove_all_data:
# Remove logs
log_files = [
BASE_DIR / "logs" / "whisper" / "whisper.out.log", # New location
BASE_DIR / "logs" / "whisper" / "whisper.err.log", # New location
BASE_DIR / "logs" / "whisper.out.log", # Legacy location
BASE_DIR / "logs" / "whisper.err.log", # Legacy location
BASE_DIR / "whisper-server.log",
BASE_DIR / "whisper-server.stdout.log",
BASE_DIR / "whisper-server.stderr.log",
BASE_DIR / "whisper-server.error.log"
]
# Also remove the whisper logs directory if empty
whisper_log_dir = BASE_DIR / "logs" / "whisper"
for log_file in log_files:
if log_file.exists():
try:
log_file.unlink()
removed_items.append(f"Removed log file: {log_file.name}")
except Exception as e:
errors.append(f"Failed to remove {log_file}: {e}")
# Remove any whisper-specific transcriptions
transcriptions_dir = BASE_DIR / "transcriptions"
if transcriptions_dir.exists():
for file in transcriptions_dir.glob("whisper_*.txt"):
try:
file.unlink()
removed_items.append(f"Removed transcription: {file.name}")
except Exception as e:
errors.append(f"Failed to remove {file}: {e}")
# Prepare response
success = len(errors) == 0
if success:
message = "Whisper has been successfully uninstalled"
if remove_models:
message += " (including models)"
if remove_all_data:
message += " (including all data)"
else:
message = "Whisper uninstall completed with some errors"
return {
"success": success,
"message": message,
"removed_items": removed_items,
"errors": errors,
"summary": {
"items_removed": len(removed_items),
"errors_encountered": len(errors)
}
}
except Exception as e:
logger.error(f"Unexpected error during Whisper uninstall: {e}")
return {
"success": False,
"message": f"Failed to uninstall Whisper: {str(e)}",
"removed_items": removed_items,
"errors": errors + [str(e)],
"summary": {
"items_removed": len(removed_items),
"errors_encountered": len(errors) + 1
}
}