Skip to main content
Glama

MCP FishAudio Server

by da-okazaki
config.ts4.56 kB
import { config as dotenvConfig } from 'dotenv'; import { Config, AudioFormat, Mp3Bitrate, ReferenceConfig } from '../types/index.js'; import { existsSync, mkdirSync } from 'fs'; import { join, resolve } from 'path'; import { homedir } from 'os'; import { logger } from './logger.js'; dotenvConfig(); function parseBoolean(value: string | undefined, defaultValue: boolean): boolean { if (!value) return defaultValue; return value.toLowerCase() === 'true'; } function parseAudioFormat(value: string | undefined, defaultValue: AudioFormat): AudioFormat { if (!value) return defaultValue; const validFormats: AudioFormat[] = ['mp3', 'wav', 'pcm', 'opus']; const format = value.toLowerCase() as AudioFormat; return validFormats.includes(format) ? format : defaultValue; } function parseMp3Bitrate(value: string | undefined, defaultValue: Mp3Bitrate): Mp3Bitrate { if (!value) return defaultValue; const bitrate = parseInt(value); const validBitrates: Mp3Bitrate[] = [64, 128, 192]; return validBitrates.includes(bitrate as Mp3Bitrate) ? (bitrate as Mp3Bitrate) : defaultValue; } let configCache: Config | null = null; function parseReferences(): ReferenceConfig[] { const references: ReferenceConfig[] = []; // Parse FISH_REFERENCES as JSON array const referencesStr = process.env.FISH_REFERENCES; if (referencesStr) { try { const parsedRefs = JSON.parse(referencesStr); if (Array.isArray(parsedRefs)) { for (const ref of parsedRefs) { if (ref.reference_id || ref.id) { references.push({ id: ref.reference_id || ref.id, name: ref.name, tags: ref.tags }); } } } } catch (error) { logger.error('Failed to parse FISH_REFERENCES as JSON:', error); logger.error('Please use JSON array format: [{"reference_id":"id1","name":"Alice","tags":["female","english"]}]'); } } // Fallback: support individual reference configs for backward compatibility if (references.length === 0) { for (let i = 1; i <= 10; i++) { const id = process.env[`FISH_REFERENCE_${i}_ID`]; if (id) { references.push({ id, name: process.env[`FISH_REFERENCE_${i}_NAME`], tags: process.env[`FISH_REFERENCE_${i}_TAGS`]?.split(',').map(t => t.trim()) }); } } } return references; } export function loadConfig(): Config { if (configCache) { return configCache; } const apiKey = process.env.FISH_API_KEY; if (!apiKey) { throw new Error('FISH_API_KEY environment variable is required'); } // Default to user's home directory for audio output const defaultOutputDir = join(homedir(), '.fish-audio-mcp', 'audio_output'); let audioOutputDir = process.env.AUDIO_OUTPUT_DIR || defaultOutputDir; // Expand ~ to home directory if present if (audioOutputDir.startsWith('~/')) { audioOutputDir = join(homedir(), audioOutputDir.slice(2)); } const resolvedOutputDir = resolve(audioOutputDir); // Create output directory if it doesn't exist try { if (!existsSync(resolvedOutputDir)) { mkdirSync(resolvedOutputDir, { recursive: true }); } } catch (error) { logger.error(`Warning: Could not create audio output directory at ${resolvedOutputDir}. Audio files will be saved to memory only.`); } const streaming = parseBoolean(process.env.FISH_STREAMING, false); const autoPlay = parseBoolean(process.env.FISH_AUTO_PLAY, false); // Parse references const references = parseReferences(); const defaultReference = process.env.FISH_DEFAULT_REFERENCE || process.env.FISH_REFERENCE_ID; const config: Config = { apiKey, modelId: process.env.FISH_MODEL_ID || 's1', referenceId: process.env.FISH_REFERENCE_ID, // Keep for backward compatibility references, defaultReference, outputFormat: parseAudioFormat(process.env.FISH_OUTPUT_FORMAT, 'mp3'), streaming: streaming, mp3Bitrate: parseMp3Bitrate(process.env.FISH_MP3_BITRATE, 128), audioOutputDir: resolvedOutputDir, autoPlay: autoPlay, websocketStreaming: false, // Default to false for HTTP streaming realtimePlay: false // Default to false for standard playback }; configCache = config; return config; } export function getOutputPath(format: string): string { const config = loadConfig(); const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const filename = `tts_${timestamp}.${format}`; return join(config.audioOutputDir, filename); }

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/da-okazaki/mcp-fish-audio-server'

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