Skip to main content
Glama

Minimax MCP Tools

by PsychArch
index.ts6.45 kB
#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; // Import refactored components import { ConfigManager } from './config/config-manager.js'; import { imageGenerationSchema, textToSpeechSchema, taskBarrierSchema, validateImageParams, validateTTSParams, validateTaskBarrierParams } from './config/schemas.js'; import { ImageGenerationService } from './services/image-service.js'; import { TextToSpeechService } from './services/tts-service.js'; import { RateLimitedTaskManager } from './core/task-manager.js'; import { ErrorHandler } from './utils/error-handler.js'; // MCP Tool Response interface interface ToolResponse { [x: string]: unknown; content: Array<{ type: "text"; text: string; }>; } // Initialize configuration and services let config: ConfigManager; let imageService: ImageGenerationService; let ttsService: TextToSpeechService; let taskManager: RateLimitedTaskManager; try { config = ConfigManager.getInstance(); config.validate(); imageService = new ImageGenerationService(); ttsService = new TextToSpeechService(); taskManager = new RateLimitedTaskManager(); } catch (error: any) { console.error("❌ Failed to initialize:", ErrorHandler.formatErrorForUser(error)); process.exit(1); } // Create MCP server const server = new McpServer({ name: "minimax-mcp-tools", version: "2.2.0", description: "Async Minimax AI integration for image generation and text-to-speech" }); // Image generation tool server.registerTool( "submit_image_generation", { title: "Submit Image Generation Task", description: "Generate images asynchronously. RECOMMENDED: Submit multiple tasks in batch to saturate rate limits, then call task_barrier once to wait for all completions. Returns task ID only - actual files available after task_barrier.", inputSchema: imageGenerationSchema.shape }, async (params: unknown): Promise<ToolResponse> => { try { const validatedParams = validateImageParams(params); const { taskId } = await taskManager.submitImageTask(async () => { return await imageService.generateImage(validatedParams); }); return { content: [{ type: "text", text: `Task ${taskId} submitted` }] }; } catch (error: any) { ErrorHandler.logError(error, { tool: 'submit_image_generation', params }); return { content: [{ type: "text", text: `❌ Failed to submit image generation task: ${ErrorHandler.formatErrorForUser(error)}` }] }; } } ); // Text-to-speech tool server.registerTool( "submit_speech_generation", { title: "Submit Speech Generation Task", description: "Convert text to speech asynchronously. RECOMMENDED: Submit multiple tasks in batch to saturate rate limits, then call task_barrier once to wait for all completions. Returns task ID only - actual files available after task_barrier.", inputSchema: textToSpeechSchema.shape }, async (params: unknown): Promise<ToolResponse> => { try { const validatedParams = validateTTSParams(params); const { taskId } = await taskManager.submitTTSTask(async () => { return await ttsService.generateSpeech(validatedParams); }); return { content: [{ type: "text", text: `Task ${taskId} submitted` }] }; } catch (error: any) { ErrorHandler.logError(error, { tool: 'submit_speech_generation', params }); return { content: [{ type: "text", text: `❌ Failed to submit TTS task: ${ErrorHandler.formatErrorForUser(error)}` }] }; } } ); // Task barrier tool server.registerTool( "task_barrier", { title: "Wait for Task Completion", description: "Wait for ALL submitted tasks to complete and retrieve results. Essential for batch processing - submit multiple tasks first, then call task_barrier once to collect all results efficiently. Clears completed tasks.", inputSchema: taskBarrierSchema.shape }, async (params: unknown): Promise<ToolResponse> => { try { validateTaskBarrierParams(params); const { completed, results } = await taskManager.barrier(); if (completed === 0) { return { content: [{ type: "text", text: "ℹ️ No tasks were submitted before this barrier." }] }; } // Format results const resultSummaries = results.map(({ taskId, success, result, error }) => { if (!success) { return `❌ Task ${taskId}: FAILED - ${error?.message || 'Unknown error'}`; } // Format success results based on task type if (result?.files) { // Image generation result const warnings = result.warnings ? ` (${result.warnings.length} warnings)` : ''; return `✅ Task ${taskId}: Generated ${result.count} image(s)${warnings}`; } else if (result?.audioFile) { // TTS generation result const subtitles = result.subtitleFile ? ` + subtitles` : ''; const warnings = result.warnings ? ` (${result.warnings.length} warnings)` : ''; return `✅ Task ${taskId}: Generated speech${subtitles}${warnings}`; } else { // Generic success return `✅ Task ${taskId}: Completed successfully`; } }); const summary = resultSummaries.join('\n'); // Clear completed tasks to prevent memory leaks taskManager.clearCompletedTasks(); return { content: [{ type: "text", text: summary }] }; } catch (error: any) { ErrorHandler.logError(error, { tool: 'task_barrier' }); return { content: [{ type: "text", text: `❌ Task barrier failed: ${ErrorHandler.formatErrorForUser(error)}` }] }; } } ); // Graceful shutdown process.on('SIGINT', () => { console.error("🛑 Shutting down gracefully..."); taskManager.clearCompletedTasks(); process.exit(0); }); process.on('SIGTERM', () => { console.error("🛑 Received SIGTERM, shutting down..."); taskManager.clearCompletedTasks(); process.exit(0); }); // Start server const transport = new StdioServerTransport(); await server.connect(transport);

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/PsychArch/minimax-mcp-tools'

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