Skip to main content
Glama

VOICEPEAK MCP Server

by k2wanko
temp-file-manager.ts3 kB
import { randomUUID } from "node:crypto"; import { promises as fs } from "node:fs"; import { tmpdir } from "node:os"; import * as path from "node:path"; import { ErrorCode, VoicepeakError } from "./errors.js"; import { CONFIG } from "./types.js"; export class TempFileManager { private tempFiles = new Set<string>(); private cleanupTimer: NodeJS.Timeout | null = null; constructor() { // Register cleanup handlers process.on("SIGINT", () => this.cleanupAll()); process.on("SIGTERM", () => this.cleanupAll()); process.on("exit", () => this.cleanupAll()); // Periodic cleanup every 5 minutes this.cleanupTimer = setInterval( () => { this.cleanupStale(); }, 5 * 60 * 1000, ); } async create(prefix: string = CONFIG.TEMP_FILE.PREFIX): Promise<string> { const tempDir = tmpdir(); const fileName = `${prefix}-${Date.now()}-${randomUUID()}${CONFIG.TEMP_FILE.EXTENSION}`; const tempPath = path.join(tempDir, fileName); this.tempFiles.add(tempPath); return tempPath; } async cleanup(filePath: string): Promise<void> { if (!this.tempFiles.has(filePath)) { return; // Not our file, don't touch it } try { await fs.unlink(filePath); this.tempFiles.delete(filePath); } catch (error) { // Only log if file exists but couldn't be deleted if ((error as NodeJS.ErrnoException).code !== "ENOENT") { console.error(`Failed to delete temp file ${filePath}:`, error); } // Remove from tracking regardless this.tempFiles.delete(filePath); } } async cleanupAll(): Promise<void> { if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = null; } const cleanupPromises = Array.from(this.tempFiles).map( (file) => this.cleanup(file).catch(() => {}), // Ignore individual failures ); await Promise.allSettled(cleanupPromises); this.tempFiles.clear(); } /** * Clean up files older than 1 hour */ private async cleanupStale(): Promise<void> { const staleAge = 60 * 60 * 1000; // 1 hour const now = Date.now(); for (const filePath of this.tempFiles) { try { const stats = await fs.stat(filePath); if (now - stats.mtimeMs > staleAge) { await this.cleanup(filePath); } } catch { // File doesn't exist or can't be accessed, remove from tracking this.tempFiles.delete(filePath); } } } /** * Ensures temp file was created and exists */ async ensureExists(filePath: string): Promise<void> { try { const stats = await fs.stat(filePath); if (!stats.isFile()) { throw new VoicepeakError( "Temporary file creation failed", ErrorCode.TEMP_FILE_ERROR, ); } } catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") { throw new VoicepeakError( "Temporary file was not created", ErrorCode.TEMP_FILE_ERROR, ); } throw error; } } get fileCount(): number { return this.tempFiles.size; } } // Singleton instance export const tempFileManager = new TempFileManager();

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/k2wanko/voicepeak-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server