@bratcliffe909/mcp-server-segmind
Version:
Model Context Protocol server for Segmind API - Generate images and videos using AI models
104 lines • 4.74 kB
JavaScript
import { z } from 'zod';
import { modelRegistry, ModelCategory } from '../models/registry.js';
import { logger } from '../utils/logger.js';
import { BaseTool } from './base.js';
const GenerateMusicSchema = z.object({
prompt: z.string().describe('Text description of the music to generate'),
model: z.string().optional().describe('Music generation model to use'),
duration: z.number().min(1).max(300).optional().describe('Duration in seconds for the music'),
negative_prompt: z.string().optional().describe('What to avoid in the generation'),
seed: z.number().int().optional().describe('Seed for reproducible generation'),
num_outputs: z.number().int().min(1).max(4).default(1).describe('Number of variations to generate'),
save_location: z.string().optional().describe('Directory path to save the music. Overrides default save location.'),
});
export class GenerateMusicTool extends BaseTool {
name = 'generate_music';
description = 'Generate music from text descriptions';
async execute(params) {
try {
const validated = GenerateMusicSchema.parse(params);
const model = this.selectModel(validated);
if (!model) {
return {
content: [{
type: 'text',
text: 'No suitable music generation model found.',
}],
isError: true,
};
}
logger.info(`Selected music model ${model.id} for generation`);
const results = [];
for (let i = 0; i < validated.num_outputs; i++) {
if (validated.num_outputs > 1) {
logger.info(`Generating variation ${i + 1} of ${validated.num_outputs}`);
}
const modelParams = await this.prepareModelParameters(validated, model, i);
const paramValidation = modelRegistry.validateModelParameters(model.id, modelParams);
if (!paramValidation.success) {
return {
content: [{
type: 'text',
text: `Invalid parameters for model ${model.id}: ${paramValidation.error}`,
}],
isError: true,
};
}
const result = await this.callModel(model, paramValidation.data, validated.save_location);
results.push(...result.content);
}
results.push({
type: 'text',
text: `\nGenerated ${validated.num_outputs} ${validated.duration || 30}-second music track${validated.num_outputs > 1 ? 's' : ''} using ${model.name}`,
});
return { content: results };
}
catch (error) {
logger.error('Music generation failed', { error });
return this.createErrorResponse(error);
}
}
selectModel(params) {
if (params.model) {
const model = modelRegistry.getModel(params.model);
if (model && model.category === ModelCategory.TEXT_TO_MUSIC) {
return model;
}
logger.warn(`Model ${params.model} not found or not a music model`);
}
const musicModels = modelRegistry.getModelsByCategory(ModelCategory.TEXT_TO_MUSIC);
if (params.duration && params.duration > 30) {
return musicModels.find(m => m.id === 'minimax-music') || musicModels[0];
}
return musicModels.find(m => m.id === 'lyria-2') || musicModels[0];
}
async prepareModelParameters(params, model, variationIndex) {
const baseParams = {
prompt: params.prompt,
};
const seed = params.seed !== undefined
? params.seed + variationIndex
: undefined;
switch (model.id) {
case 'lyria-2':
if (params.duration)
baseParams.duration = params.duration;
if (params.negative_prompt)
baseParams.negative_prompt = params.negative_prompt;
break;
case 'minimax-music':
if (params.duration)
baseParams.duration = params.duration;
break;
}
if (seed !== undefined && model.parameters.shape.seed) {
baseParams.seed = seed;
}
if (model.parameters.shape.base64 !== undefined) {
baseParams.base64 = false;
}
return this.mergeWithDefaults(baseParams, model);
}
}
export const generateMusicTool = new GenerateMusicTool();
//# sourceMappingURL=generate-music.js.map