minimax-mcp-tools
Version:
Async MCP server with Minimax API integration for image generation and text-to-speech
118 lines • 4.3 kB
JavaScript
import { MinimaxBaseClient } from '../core/base-client.js';
import { API_CONFIG, DEFAULTS, MODELS, CONSTRAINTS } from '../config/constants.js';
import { FileHandler } from '../utils/file-handler.js';
import { ErrorHandler } from '../utils/error-handler.js';
export class ImageGenerationService extends MinimaxBaseClient {
constructor(options = {}) {
super(options);
}
async generateImage(params) {
try {
const payload = this.buildPayload(params);
const response = await this.post(API_CONFIG.ENDPOINTS.IMAGE_GENERATION, payload);
return await this.processImageResponse(response, params);
}
catch (error) {
const processedError = ErrorHandler.handleAPIError(error);
ErrorHandler.logError(processedError, { service: 'image', params });
throw processedError;
}
}
buildPayload(params) {
const imageDefaults = DEFAULTS.IMAGE;
const model = params.style ? 'image-01-live' : 'image-01';
const payload = {
model: model,
prompt: params.prompt,
n: 1,
prompt_optimizer: true,
response_format: 'url'
};
if (params.customSize) {
payload.width = params.customSize.width;
payload.height = params.customSize.height;
}
else {
payload.aspect_ratio = params.aspectRatio || imageDefaults.aspectRatio;
}
if (params.seed !== undefined) {
payload.seed = params.seed;
}
if (model === 'image-01') {
if (params.subjectReference) {
payload.subject_reference = [{
type: 'character',
image_file: params.subjectReference
}];
}
}
else if (model === 'image-01-live') {
if (params.style) {
payload.style = {
style_type: params.style.style_type,
style_weight: params.style.style_weight || 0.8
};
}
}
return payload;
}
async processImageResponse(response, params) {
const imageUrls = response.data?.image_urls || [];
const imageBase64 = response.data?.image_base64 || [];
if (!imageUrls.length && !imageBase64.length) {
throw new Error('No images generated in API response');
}
const savedFiles = [];
const errors = [];
const imageSources = imageUrls.length ? imageUrls : imageBase64;
for (let i = 0; i < imageSources.length; i++) {
try {
const filename = FileHandler.generateUniqueFilename(params.outputFile, i, imageSources.length);
if (imageBase64.length && !imageUrls.length) {
await FileHandler.saveBase64Image(imageBase64[i], filename);
}
else {
await FileHandler.downloadFile(imageSources[i], filename);
}
savedFiles.push(filename);
}
catch (error) {
errors.push(`Image ${i + 1}: ${error.message}`);
}
}
if (savedFiles.length === 0) {
throw new Error(`Failed to save any images: ${errors.join('; ')}`);
}
const modelUsed = params.style ? 'image-01-live' : 'image-01';
const result = {
files: savedFiles,
count: savedFiles.length,
model: modelUsed,
prompt: params.prompt
};
if (errors.length > 0) {
result.warnings = errors;
}
return result;
}
async validateSubjectReference(reference) {
if (!reference)
return null;
try {
return await FileHandler.convertToBase64(reference);
}
catch (error) {
throw new Error(`Invalid subject reference: ${error.message}`);
}
}
getSupportedModels() {
return Object.keys(MODELS.IMAGE);
}
getSupportedAspectRatios() {
return CONSTRAINTS.IMAGE.ASPECT_RATIOS;
}
getModelInfo(modelName) {
return MODELS.IMAGE[modelName] || null;
}
}
//# sourceMappingURL=image-service.js.map