Skip to main content
Glama
dasheck0

Face Generator MCP Server

generate_face

Generate realistic human face images that don't represent real people. Save images to specified directories with customizable dimensions, shapes, and batch generation options.

Instructions

Generate and save a human face image

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
outputDirYesDirectory to save the image
fileNameNoOptional file name (defaults to timestamp)1767357705977.png
countNoNumber of images to generate (default: 1)
widthNoWidth of the image in pixels (default: 256)
heightNoHeight of the image in pixels (default: 256)
shapeNoImage shape (square|circle|rounded, default: square)square
borderRadiusNoBorder radius for rounded shape (default: 32)
returnImageContentNoReturn image as base64 encoded content instead of file path (default: false)

Implementation Reference

  • The CallToolRequestSchema handler implements the generate_face tool: validates name, parses arguments, fetches random face images from https://thispersondoesnotexist.com, processes with Sharp (resize, shape masking), saves to outputDir, optionally returns base64 ImageContent.
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      if (request.params.name !== 'generate_face') {
        throw new Error(`Unknown tool: ${request.params.name}`);
      }
    
      interface GenerateFaceArgs {
        outputDir: string;
        fileName?: string;
        count?: number;
        width?: number;
        height?: number;
        shape?: string;
        borderRadius?: number;
        returnImageContent?: boolean;
      }
      
      if (!request.params.arguments) {
        throw new Error('Arguments are required');
      }
      
      const args = request.params.arguments as unknown as GenerateFaceArgs;
      const { 
        outputDir, 
        fileName = `${Date.now()}.jpg`,
        count = 1,
        width = 256,
        height = 256,
        returnImageContent = false
      } = args;
    
      try {
        // Create directory if it doesn't exist
        if (!fs.existsSync(outputDir)) {
          fs.mkdirSync(outputDir, { recursive: true });
        }
    
        const sharp = (await import('sharp')).default;
        const results = [];
        const imageContents: ImageContent[] = [];
    
        for (let i = 0; i < count; i++) {
          // Fetch image
          const response = await axios.get('https://thispersondoesnotexist.com', {
            responseType: 'arraybuffer',
          });
    
          // Process image
          let image = sharp(response.data)
            .resize(width, height);
    
          // Apply shape transformations
          switch (args.shape || 'square') {
            case 'circle':
              const radius = Math.min(width, height) / 2;
              const circleShape = Buffer.from(
                `<svg><circle cx="${radius}" cy="${radius}" r="${radius}" fill="white" /></svg>`
              );
              image = image.composite([{
                input: circleShape,
                blend: 'dest-in'
              }]);
              break;
    
            case 'rounded':
              const borderRadius = args.borderRadius || 32;
              const roundedShape = Buffer.from(
                `<svg><rect width="${width}" height="${height}" rx="${borderRadius}" ry="${borderRadius}" fill="white" /></svg>`
              );
              image = image.composite([{
                input: roundedShape,
                blend: 'dest-in'
              }]);
              break;
          }
    
          const imageBuffer = await image.png().toBuffer();
          const base64Image = imageBuffer.toString('base64');
    
          // Generate unique filename if multiple images
          // Ensure .png extension
          const baseName = fileName.replace(/\.(jpg|jpeg|png)$/i, '');
          const finalFileName = count > 1
            ? `${baseName}_${i}.png`
            : `${baseName}.png`;
    
          // Save image
          const filePath = path.join(outputDir, finalFileName);
          await fs.promises.writeFile(filePath, imageBuffer);
    
          if (returnImageContent) {
            imageContents.push({
              type: 'image',
              mimeType: 'image/png',
              data: base64Image,
            });
          }
    
          results.push(filePath);
        }
    
        const content = returnImageContent
          ? imageContents
          : [
              {
                type: 'text',
                text: `Generated ${count} face image(s):\n${results.join('\n')}`,
              },
            ];
    
        return {
          content,
        };
      } catch (error) {
        console.error(error);
        let errorCode = ErrorCode.InternalError;
        let errorMessage = 'Unknown error occurred';
    
        if (error instanceof axios.AxiosError) {
          if (error.code === 'ENOTFOUND') {
            errorCode = ErrorCode.MethodNotFound;
            errorMessage = 'Failed to fetch image from thispersondoesnotexist.com: Network error.';
          } else {
            errorCode = ErrorCode.InternalError;
            errorMessage = `Failed to fetch image: ${error.message}`;
          }
        } else if (error instanceof Error) {
          errorMessage = error.message;
          if (error.message.includes('ENOSPC')) {
            errorCode = ErrorCode.InternalError;
            errorMessage = 'No space left on device.';
          } else if (error.message.includes('EEXIST')) {
            errorCode = ErrorCode.InternalError;
            errorMessage = 'File already exists.';
          } else if (error.message.includes('ENOENT')) {
            errorCode = ErrorCode.InternalError;
            errorMessage = 'No such file or directory.';
          } else if (error.message.includes('Invalid width')) {
            errorCode = ErrorCode.InvalidParams;
            errorMessage = 'Invalid width parameter.';
          } else if (error.message.includes('Invalid height')) {
            errorCode = ErrorCode.InvalidParams;
            errorMessage = 'Invalid height parameter.';
          } else if (error.message.includes('Input buffer contains unsupported image format')) {
            errorCode = ErrorCode.InvalidParams;
            errorMessage = 'Unsupported image format.';
          }
        } else {
          errorMessage = String(error);
        }
    
        const result: CallToolResult = {
          content: [
            {
              type: 'text',
              text: `Error generating face: ${errorMessage}`,
            },
          ],
          isError: true,
        };
        return result;
      }
    });
  • TypeScript interface defining the input arguments for generate_face tool, matching the inputSchema.
    interface GenerateFaceArgs {
      outputDir: string;
      fileName?: string;
      count?: number;
      width?: number;
      height?: number;
      shape?: string;
      borderRadius?: number;
      returnImageContent?: boolean;
    }
  • src/index.ts:37-94 (registration)
    Tool registration in ListToolsRequestSchema response, defining name, description, and detailed inputSchema for validation.
    {
      name: 'generate_face',
      description: 'Generate and save a human face image',
      inputSchema: {
        type: 'object',
        properties: {
          outputDir: {
            type: 'string',
            description: 'Directory to save the image',
          },
          fileName: {
            type: 'string',
            description: 'Optional file name (defaults to timestamp)',
            default: `${Date.now()}.png`,
          },
          count: {
            type: 'number',
            description: 'Number of images to generate (default: 1)',
            default: 1,
            minimum: 1,
            maximum: 10
          },
          width: {
            type: 'number',
            description: 'Width of the image in pixels (default: 256)',
            default: 256,
            minimum: 64,
            maximum: 1024
          },
          height: {
            type: 'number',
            description: 'Height of the image in pixels (default: 256)',
            default: 256,
            minimum: 64,
            maximum: 1024
          },
          shape: {
            type: 'string',
            description: 'Image shape (square|circle|rounded, default: square)',
            default: 'square',
            enum: ['square', 'circle', 'rounded']
          },
          borderRadius: {
            type: 'number',
            description: 'Border radius for rounded shape (default: 32)',
            default: 32,
            minimum: 0,
            maximum: 512
          },
          returnImageContent: {
            type: 'boolean',
            description: 'Return image as base64 encoded content instead of file path (default: false)',
            default: false
          }
        },
        required: ['outputDir'],
      },
    },
  • JSON schema for generate_face tool inputs, used for validation in tool listing.
    inputSchema: {
      type: 'object',
      properties: {
        outputDir: {
          type: 'string',
          description: 'Directory to save the image',
        },
        fileName: {
          type: 'string',
          description: 'Optional file name (defaults to timestamp)',
          default: `${Date.now()}.png`,
        },
        count: {
          type: 'number',
          description: 'Number of images to generate (default: 1)',
          default: 1,
          minimum: 1,
          maximum: 10
        },
        width: {
          type: 'number',
          description: 'Width of the image in pixels (default: 256)',
          default: 256,
          minimum: 64,
          maximum: 1024
        },
        height: {
          type: 'number',
          description: 'Height of the image in pixels (default: 256)',
          default: 256,
          minimum: 64,
          maximum: 1024
        },
        shape: {
          type: 'string',
          description: 'Image shape (square|circle|rounded, default: square)',
          default: 'square',
          enum: ['square', 'circle', 'rounded']
        },
        borderRadius: {
          type: 'number',
          description: 'Border radius for rounded shape (default: 32)',
          default: 32,
          minimum: 0,
          maximum: 512
        },
        returnImageContent: {
          type: 'boolean',
          description: 'Return image as base64 encoded content instead of file path (default: false)',
          default: false
        }
      },
      required: ['outputDir'],
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. While 'generate and save' implies a write operation, it doesn't disclose important behavioral traits like whether this requires specific permissions, what happens if the output directory doesn't exist, whether generation is deterministic or random, or what happens on failure. For a tool that creates files with no annotation coverage, this represents a significant gap in transparency.

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 perfectly concise at just 6 words: 'Generate and save a human face image.' It's front-loaded with the core functionality, contains zero wasted words, and communicates the essential purpose efficiently. Every word earns its place in this minimal but complete statement of function.

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

Completeness2/5

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

For a tool with 8 parameters, no annotations, and no output schema, the description is insufficiently complete. It doesn't explain what the tool returns (file paths? success indicators? error formats?), doesn't mention any constraints or requirements beyond what's in the parameter schema, and provides no context about the generation quality, source, or limitations. The agent would need to guess about important behavioral aspects.

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?

The description provides no parameter information beyond what's already in the schema, which has 100% coverage with detailed descriptions for all 8 parameters. The baseline score of 3 reflects that the schema does the heavy lifting, and the description adds no additional parameter context, semantics, or examples beyond what's already documented in the structured schema fields.

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

Purpose4/5

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

The description 'Generate and save a human face image' clearly states the verb ('generate and save') and resource ('human face image'), making the purpose immediately understandable. It's specific about generating a face image rather than generic image generation. However, without sibling tools to differentiate from, it can't achieve the full 5 points for sibling distinction.

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?

The description provides no guidance on when to use this tool versus alternatives, prerequisites, or constraints. It simply states what the tool does without any context about appropriate use cases, limitations, or when other tools might be more suitable. This leaves the agent with insufficient context for optimal tool selection.

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/dasheck0/face-generator'

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