@genwave/svgmaker-mcp
Version:
MCP server for generating, editing, and converting SVG images using SVGMaker API
114 lines • 5.05 kB
JavaScript
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';
import * as svgmakerService from '../services/svgmakerService.js';
import * as fileUtils from '../utils/fileUtils.js';
import { logToFile } from '../utils/logUtils.js';
import { ProgressManager } from '../utils/progressUtils.js';
const GenerateToolInputSchema = z.object({
prompt: z.string().min(1, 'Prompt cannot be empty.'),
output_path: z.string().min(1, 'Output path cannot be empty.'),
quality: z
.enum(['low', 'medium', 'high'])
.optional()
.describe("Quality level - affects aspect ratio: low/medium use 'auto', high uses 'square'"),
aspectRatio: z
.enum(['square', 'portrait', 'landscape'])
.optional()
.describe('Aspect ratio for the generated SVG'),
background: z.enum(['auto', 'transparent', 'opaque']).optional().describe('Background type'),
});
export const generateToolDefinition = {
name: 'svgmaker_generate',
description: 'Generates an SVG image from a detailed text prompt using SVGMaker API and saves it to a specified local path. For best results, provide a clear, detailed description of the desired image including style, colors, composition, and key elements. If quality is not specified, medium quality will be used by default.',
inputSchema: zodToJsonSchema(GenerateToolInputSchema),
};
export async function handleGenerateTool(server, request) {
const { arguments: args } = request.params;
// Log that the tool is being called
logToFile('========== SVG GENERATE TOOL CALLED ==========');
logToFile(`Arguments: ${JSON.stringify(args, null, 2)}`);
logToFile(`Request meta: ${JSON.stringify(request.params._meta, null, 2)}`);
try {
const validatedArgs = GenerateToolInputSchema.parse(args);
// Note: In a real implementation, we'd need to get roots from the client
// For now, we'll use a simple path validation
const clientRoots = []; // server.getRoots() is not available in this SDK version
const validatedOutputPath = await fileUtils.resolveAndValidatePath(validatedArgs.output_path, clientRoots, 'write');
// Determine aspect ratio based on quality and explicit aspectRatio
let finalAspectRatio = validatedArgs.aspectRatio;
if (!finalAspectRatio) {
if (validatedArgs.quality === 'high') {
finalAspectRatio = 'square';
}
else {
finalAspectRatio = 'auto'; // low and medium use auto
}
}
const progressManager = new ProgressManager({
server,
progressToken: request.params._meta?.progressToken,
totalSteps: 4,
messages: {
initial: 'Initializing SVG generation...',
preparing: 'Preparing API request...',
processing: 'AI is creating your SVG...',
saving: 'Saving SVG file...',
complete: 'SVG generation complete!',
},
});
// Send initial progress
await progressManager.sendInitialProgress();
try {
const sdkParams = {
prompt: validatedArgs.prompt,
quality: validatedArgs.quality,
aspectRatio: finalAspectRatio,
background: validatedArgs.background,
svgText: true,
};
// Update progress: preparing request
await progressManager.sendPreparingProgress();
// Update progress: making API call with periodic updates
await progressManager.startProcessingProgress();
let result;
try {
// The actual API call
result = await svgmakerService.generateSVG(sdkParams);
}
finally {
// Clean up the progress interval
progressManager.stopProcessingProgress();
}
// Update progress: processing complete
await progressManager.sendSavingProgress();
if (result.svgText) {
await fileUtils.writeFile(validatedOutputPath, result.svgText);
// Send final progress
await progressManager.sendFinalProgress();
return {
content: [
{
type: 'text',
text: `SVG generated successfully: ${validatedOutputPath}`,
},
],
};
}
else {
throw new Error('SVGMaker API did not return SVG content.');
}
}
catch (error) {
// Ensure cleanup on error
progressManager.cleanup();
throw error;
}
}
catch (error) {
return {
isError: true,
content: [{ type: 'text', text: `Error generating SVG: ${error.message}` }],
};
}
}
//# sourceMappingURL=generateTool.js.map