Skip to main content
Glama
falahgs

3D Cartoon Generator & File System MCP Server

by falahgs

generate_3d_cartoon

Generate a 3D-style cartoon image for kids using a text prompt and specify the output file name.

Instructions

Generates a 3D style cartoon image for kids based on the given prompt

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
promptYesThe prompt describing the 3D cartoon image to generate
fileNameYesThe name of the output file (without extension)

Implementation Reference

  • The core handler logic for the generate_3d_cartoon tool. It takes prompt and fileName arguments, wraps the prompt with 3D cartoon context, calls Google GenAI (Gemini 2.0 Flash) to generate the image, saves the image file, creates an HTML preview, and returns the result paths.
    case "generate_3d_cartoon": {
      const { prompt, fileName } = args;
      
      // Add 3D cartoon-specific context to the prompt
      const cartoonPrompt = `Generate a 3D style cartoon image for kids: ${prompt}. The image should be colorful, playful, and child-friendly. Use bright colors, soft shapes, and a fun, engaging style that appeals to children. Make it look like a high-quality 3D animated character or scene.`;
      
      const contents = [
        {
          role: 'user',
          parts: [
            {
              text: cartoonPrompt,
            },
          ],
        },
      ];
    
      try {
        const response = await genAI.models.generateContentStream({
          model,
          config,
          contents,
        });
    
        for await (const chunk of response) {
          if (!chunk.candidates || !chunk.candidates[0].content || !chunk.candidates[0].content.parts) {
            continue;
          }
          if (chunk.candidates[0].content.parts[0].inlineData) {
            const inlineData = chunk.candidates[0].content.parts[0].inlineData;
            const buffer = Buffer.from(inlineData.data || '', 'base64');
            
            // Create an output filename with timestamp for uniqueness
            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
            const outputFileName = fileName.endsWith('.png') 
              ? fileName 
              : `${fileName}_${timestamp}.png`;
            
            // Find appropriate save location
            const { savedPath } = await saveImageWithProperPath(buffer, outputFileName);
            
            // Create simple HTML preview
            const htmlContent = `
            <!DOCTYPE html>
            <html>
            <head>
              <title>3D Cartoon Preview</title>
              <style>
                body { font-family: Arial, sans-serif; margin: 20px; }
                .image-container { max-width: 800px; margin: 0 auto; }
                img { max-width: 100%; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
                .prompt { margin: 10px 0; color: #666; }
                .path { font-family: monospace; margin: 10px 0; }
              </style>
            </head>
            <body>
              <h1>3D Cartoon Image</h1>
              <div class="prompt">Prompt: ${prompt}</div>
              <div class="path">Saved to: ${savedPath}</div>
              <div class="image-container">
                <img src="file://${savedPath}" alt="Generated cartoon image">
              </div>
            </body>
            </html>
            `;
    
            // Create and save HTML file
            const htmlFileName = `${outputFileName.replace('.png', '')}_preview.html`;
            const htmlPath = path.join(path.dirname(savedPath), htmlFileName);
            
            // Ensure directory exists before writing
            ensureDirectoryExists(path.dirname(htmlPath));
            fs.writeFileSync(htmlPath, htmlContent, 'utf8');
    
            // Try to open in browser
            try {
              await openInBrowser(htmlPath);
            } catch (error) {
              console.warn('Could not open browser automatically:', error);
            }
    
            return {
              toolResult: {
                success: true,
                imagePath: savedPath,
                htmlPath: htmlPath,
                content: [
                  {
                    type: "text",
                    text: `Image saved to: ${savedPath}\nPreview HTML: ${htmlPath}`
                  }
                ],
                message: "Image generated and saved"
              }
            };
          }
        }
        
        throw new McpError(ErrorCode.InternalError, "No image data received from the API");
      } catch (error) {
        console.error('Error generating image:', error);
        if (error instanceof Error) {
          throw new McpError(ErrorCode.InternalError, `Failed to generate image: ${error.message}`);
        }
        throw new McpError(ErrorCode.InternalError, 'An unknown error occurred');
      }
    }
  • Tool registration with input schema. Defines the 'generate_3d_cartoon' tool with required string properties 'prompt' and 'fileName', used for children's 3D cartoon image generation.
    name: "generate_3d_cartoon",
    description: "Generates a 3D style cartoon image for kids based on the given prompt",
    inputSchema: {
      type: "object",
      properties: {
        prompt: {
          type: "string",
          description: "The prompt describing the 3D cartoon image to generate"
        },
        fileName: {
          type: "string",
          description: "The name of the output file (without extension)"
        }
      },
      required: ["prompt", "fileName"]
    }
  • src/index.ts:282-297 (registration)
    The tool is registered within the ListToolsRequestSchema handler as part of the tools array returned to the MCP client.
    name: "generate_3d_cartoon",
    description: "Generates a 3D style cartoon image for kids based on the given prompt",
    inputSchema: {
      type: "object",
      properties: {
        prompt: {
          type: "string",
          description: "The prompt describing the 3D cartoon image to generate"
        },
        fileName: {
          type: "string",
          description: "The name of the output file (without extension)"
        }
      },
      required: ["prompt", "fileName"]
    }
  • saveImageWithProperPath helper function used by the handler to save the generated image buffer either to the desktop (if SAVE_TO_DESKTOP=true) or a local server directory.
    async function saveImageWithProperPath(buffer: Buffer, fileName: string): Promise<{savedPath: string}> {
      try {
        // Check if SAVE_TO_DESKTOP is true
        if (process.env.SAVE_TO_DESKTOP === "true") {
          // Original desktop saving logic
          const saveDir = path.join(getDesktopPath(), 'generated-images');
          
          // Replace console.log with debugLog
          debugLog(`Saving to desktop directory: ${saveDir}`);
          debugLog(`Platform: ${os.platform()}`);
          debugLog(`Home directory: ${os.homedir()}`);
          debugLog(`Username: ${os.userInfo().username}`);
          
          // Ensure save directory exists
          ensureDirectoryExists(saveDir);
          
          // Create full path and normalize for OS
          const outputPath = path.normalize(path.join(saveDir, fileName));
          
          // Save the file
          fs.writeFileSync(outputPath, buffer);
          debugLog(`Image saved successfully to: ${outputPath}`);
          
          return { savedPath: outputPath };
        } else {
          // Save locally in the server directory
          const serverDir = process.cwd();
          const outputDir = path.join(serverDir, 'generated-images');
          
          debugLog(`Saving to server directory: ${outputDir}`);
          
          // Ensure output directory exists
          ensureDirectoryExists(outputDir);
          
          // Create full path and normalize for OS
          const outputPath = path.normalize(path.join(outputDir, fileName));
          
          // Save the file
          fs.writeFileSync(outputPath, buffer);
          debugLog(`Image saved successfully to server path: ${outputPath}`);
          
          return { savedPath: outputPath };
        }
      } catch (error) {
        console.error('Error saving image:', error);
        // Fallback to output directory
        const fallbackDir = path.join(process.cwd(), 'output');
        ensureDirectoryExists(fallbackDir);
        const fallbackPath = path.join(fallbackDir, fileName);
        fs.writeFileSync(fallbackPath, buffer);
        debugLog(`Fallback save to: ${fallbackPath}`);
        return { savedPath: fallbackPath };
      }
    }
  • openInBrowser helper function used by the handler to open the generated HTML preview in the system's default browser.
    async function openInBrowser(filePath: string): Promise<void> {
      try {
        // Check for headless environment
        if (process.env.DISPLAY === undefined && os.platform() !== 'win32' && os.platform() !== 'darwin') {
          console.log('Headless environment detected, skipping browser open');
          return;
        }
        
        // Ensure path is properly formatted for the OS
        const normalizedPath = path.normalize(filePath);
        
        // Different commands for different OSes
        const command = os.platform() === 'win32' 
          ? 'explorer'
          : os.platform() === 'darwin'
            ? 'open'
            : 'xdg-open';
    
        const args = [normalizedPath];
        
        await execFileAsync(command, args);
        console.log(`Opened in browser: ${normalizedPath}`);
      } catch (error) {
        console.error('Error opening file in browser:', error);
        console.log('Unable to open browser automatically. File saved at:', filePath);
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden for behavioral disclosure. It only states the action without revealing side effects (e.g., file saving behavior, error handling, image format), leaving significant gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, direct sentence with no unnecessary words. It is front-loaded with the verb and efficiently conveys the tool's purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the low complexity (2 simple params) and no output schema or annotations, the description is adequate but lacks details on output format, file location, or failure modes, leaving room for improvement.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameter descriptions are already present. The description adds minor context (e.g., 'for kids') but does not enhance parameter meaning beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it 'Generates a 3D style cartoon image for kids based on the given prompt', specifying the verb, resource, and audience. This distinct purpose differentiates it from sibling file-management tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No usage guidelines are provided. The description does not indicate when to use this tool over alternatives, nor does it mention prerequisites or exclusions like content restrictions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/falahgs/mcp-3d-style-cartoon-gen-server'

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