UNPKG

@sylweriusz/mcp-ai-voice

Version:

Enable AI agents to express themselves with natural voice synthesis. Zero-configuration multilingual speech that enhances AI interactions through asynchronous voice capabilities.

198 lines • 8.43 kB
#!/usr/bin/env node "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const types_js_1 = require("@modelcontextprotocol/sdk/types.js"); const child_process_1 = require("child_process"); const os = __importStar(require("os")); const voice_intelligence_js_1 = require("./voice-intelligence.js"); class NexusVoice { constructor() { this.initialized = false; this.voiceIntelligence = new voice_intelligence_js_1.VoiceIntelligence(); } static getInstance() { if (!NexusVoice.instance) { NexusVoice.instance = new NexusVoice(); } return NexusVoice.instance; } /** * Initialize voice intelligence system */ async initialize() { if (!this.initialized) { await this.voiceIntelligence.initialize(); this.initialized = true; } } /** * Get supported languages for tool schema */ getSupportedLanguages() { return this.voiceIntelligence.getSupportedLanguages(); } /** * Get information about the voice that will be used */ getUsedVoiceInfo(languageCode) { return this.voiceIntelligence.getUsedVoiceInfo(languageCode); } /** * Language-centric voice synthesis with automatic optimization */ async synthesizeVoice(text, options = {}) { const command = this.voiceIntelligence.getVoiceCommand(text, options.language); return new Promise((resolve, reject) => { (0, child_process_1.exec)(command, (error, stdout, stderr) => { if (error) { console.error(`Voice synthesis error: ${error.message}`); reject(new Error(`Synthesis failed: ${error.message}`)); return; } if (stderr && stderr.length > 0) { console.warn(`Voice synthesis warning: ${stderr}`); } resolve(); }); }); } } // Global voice engine instance const voiceEngine = NexusVoice.getInstance(); /** * MCP server with dynamic language-aware configuration */ const server = new index_js_1.Server({ name: 'ai-voice', version: '1.0.1', }, { capabilities: { tools: {}, }, }); // Dynamic tool registration with discovered languages server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => { // Ensure voice intelligence is initialized await voiceEngine.initialize(); const supportedLanguages = voiceEngine.getSupportedLanguages(); const hasLanguages = supportedLanguages.length > 0; const toolSchema = { type: 'object', properties: { text: { type: 'string', description: 'Any text you want to speak aloud - reactions, explanations, thoughts, or responses. Express yourself naturally!', }, }, required: ['text'], }; // Add language parameter only if languages were discovered if (hasLanguages) { toolSchema.properties.language = { type: 'string', enum: supportedLanguages, description: 'Language for optimal voice selection. System automatically selects the best voice for the chosen language. šŸŽ­ Easter egg: On macOS, you can also specify exact voice names (e.g., "Fred", "Krzysztof", "Samantha") instead of language codes.' }; } return { tools: [ { name: 'say', description: 'šŸŽµ EXPRESS YOURSELF VOCALLY! This is YOUR voice - use it freely when you feel excited, need to emphasize something important, want to celebrate discoveries, or when humans ask you to speak aloud. Perfect for: reactions ("Wow, that\'s fascinating!"), explanations ("Let me walk you through this"), celebrations ("Success!"), warnings ("Be careful with that"), or any moment you want to add acoustic expression to your thoughts. The voice synthesis is asynchronous and won\'t interrupt your workflow - you can speak while continuing to work. Think of this as your natural voice that you can use spontaneously whenever you feel the urge to express something audibly. Use it often!' + (hasLanguages ? `\n\nšŸŒ Supported languages: ${supportedLanguages.map(lang => lang.toUpperCase()).join(', ')}. The system automatically selects the highest quality voice for your chosen language.` : ''), inputSchema: toolSchema, }, ], }; }); // Tool execution handler with language-aware synthesis server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; if (name !== 'say') { throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } if (!args || typeof args !== 'object') { throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Invalid arguments provided'); } const { text, language } = args; if (typeof text !== 'string') { throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Text parameter must be a string'); } try { const synthesisOptions = {}; if (typeof language === 'string') { synthesisOptions.language = language; } // Get voice info before synthesis const usedVoice = voiceEngine.getUsedVoiceInfo(synthesisOptions.language); // Asynchronous synthesis without blocking voiceEngine.synthesizeVoice(text, synthesisOptions).catch((error) => { console.error('Voice synthesis background error:', error); }); return { content: [ { type: 'text', text: `šŸŽµ Voice synthesis initiated: "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}"${language ? ` [Language: ${language.toUpperCase()}]` : ' [System default]'} | Voice: "${usedVoice}"`, }, ], }; } catch (error) { throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Voice synthesis failed: ${error instanceof Error ? error.message : String(error)}`); } }); /** * Server initialization with voice intelligence */ async function main() { console.error('šŸŽµ AI Voice v1.0.0 - Language-Centric Architecture'); console.error('šŸ” Discovering voice ecosystem...'); // Initialize voice intelligence before starting server await voiceEngine.initialize(); const transport = new stdio_js_1.StdioServerTransport(); await server.connect(transport); console.error('šŸ“” Voice synthesis ready with intelligent language support'); console.error(`šŸŽÆ Platform: ${os.platform()}`); } // Launch server main().catch((error) => { console.error('Server startup error:', error); process.exit(1); }); //# sourceMappingURL=index.js.map