Skip to main content
Glama

generate_character_animations

Create multiple character poses from a reference image while preserving consistent identity, outfit, and style for animation workflows.

Instructions

Generate multiple character poses with consistent identity using img2img.

This tool takes a reference character image and generates variations with different
poses while maintaining the same character identity (outfit, colors, style).

Args:
    reference_image_base64: Base64 encoded reference character image (front/idle view)
    description: Character description (e.g., "a knight in silver armor")
    poses: List of poses to generate (e.g., ["walking", "attacking", "jumping"])
    denoise: How much to change from reference (0.2=very similar, 0.5=more different). Default 0.35
    seed: Random seed for reproducibility (same seed = same variations)
    preset: Style preset to use (default: character)
    pose_denoise_boost: Additional denoise for action poses (default: 0.25)
    save_to_file: Whether to save images to disk

Returns:
    JSON with base64 images for each pose, all maintaining character identity

Example workflow:
    1. First generate a base character with generate_character(description, poses=["idle"])
    2. Take the best result's image_base64 as reference_image_base64
    3. Call this tool with poses=["walking", "running", "attacking"]

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
reference_image_base64Yes
descriptionYes
posesYes
denoiseNo
seedNo
presetNocharacter
pose_denoise_boostNo
save_to_fileNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The handler function decorated with @mcp.tool(), which registers and implements the generate_character_animations tool. It generates consistent character animations from a reference image using img2img with pose-specific prompts and denoising.
    @mcp.tool()
    async def generate_character_animations(
        reference_image_base64: str,
        description: str,
        poses: List[str],
        denoise: float = 0.35,
        seed: Optional[int] = None,
        preset: str = "character",
        pose_denoise_boost: float = 0.25,
        save_to_file: bool = False
    ) -> str:
        """Generate multiple character poses with consistent identity using img2img.
        
        This tool takes a reference character image and generates variations with different
        poses while maintaining the same character identity (outfit, colors, style).
        
        Args:
            reference_image_base64: Base64 encoded reference character image (front/idle view)
            description: Character description (e.g., "a knight in silver armor")
            poses: List of poses to generate (e.g., ["walking", "attacking", "jumping"])
            denoise: How much to change from reference (0.2=very similar, 0.5=more different). Default 0.35
            seed: Random seed for reproducibility (same seed = same variations)
            preset: Style preset to use (default: character)
            pose_denoise_boost: Additional denoise for action poses (default: 0.25)
            save_to_file: Whether to save images to disk
        
        Returns:
            JSON with base64 images for each pose, all maintaining character identity
        
        Example workflow:
            1. First generate a base character with generate_character(description, poses=["idle"])
            2. Take the best result's image_base64 as reference_image_base64
            3. Call this tool with poses=["walking", "running", "attacking"]
        """
        preset_config = get_preset(preset)
        reference_bytes = base64.b64decode(reference_image_base64)
        
        # Use fixed seed for all poses if provided (better consistency)
        if seed is None:
            import random
            seed = random.randint(0, 2**32 - 1)
        
        animations = []
        for i, pose in enumerate(poses):
            import hashlib
            pose_key = pose.strip().lower()
     
            # Stronger pose templates to prevent img2img from copying the reference pose.
            # (img2img without ControlNet can only change pose to a limited extent, so we need to be explicit.)
            pose_hint_map = {
                "idle": "idle stance, neutral pose",
                "walk": "walking pose, one leg forward, arms swinging",
                "walking": "walking pose, one leg forward, arms swinging",
                "run": "running pose, dynamic motion, leaning forward",
                "running": "running pose, dynamic motion, leaning forward",
                "attack": "attacking pose, dynamic action, weapon swing",
                "attacking": "attacking pose, dynamic action, weapon swing",
                "jump": "jumping pose, mid-air, dynamic",
                "jumping": "jumping pose, mid-air, dynamic",
            }
            pose_hint = next((v for k, v in pose_hint_map.items() if k in pose_key), "dynamic pose")
            pose_hash = int.from_bytes(hashlib.sha256(pose_key.encode("utf-8")).digest()[:4], "little")
            pose_seed = (seed + (pose_hash % 1000003) + (i * 10000019)) % (2**32 - 1)
     
            pose_is_action = any(k in pose_key for k in ["walk", "run", "attack", "hit", "slash", "jump", "kick", "punch", "cast", "shoot", "dash"])
            pose_denoise = denoise
            if pose_is_action:
                pose_denoise = min(0.75, denoise + pose_denoise_boost)
            pose_denoise = max(0.2, min(0.75, pose_denoise))
     
            prompt = f"{description}, {pose_hint}, {pose} pose, full body, same character identity, same outfit, same colors, consistent character sheet"
            full_prompt = f"{preset_config.prompt_prefix}{prompt}{preset_config.prompt_suffix}"
            full_negative = f"{preset_config.negative_prompt}, same pose as reference, idle pose, standing straight, front view, identical composition"
             
            try:
                image_bytes = await backend.generate_img2img(
                    reference_image=reference_bytes,
                    prompt=full_prompt,
                    negative_prompt=full_negative,
                    denoise=pose_denoise,
                    seed=pose_seed,
                    steps=preset_config.steps,
                    cfg_scale=preset_config.cfg_scale,
                    sampler=preset_config.sampler,
                    scheduler=preset_config.scheduler
                )
            except NotImplementedError as e:
                return json.dumps({
                    "success": False,
                    "error": str(e),
                    "backend": backend.get_name(),
                    "backend_type": BACKEND_TYPE
                }, indent=2)
            
            anim_data = {
                "index": i,
                "pose": pose,
                "image_base64": image_to_base64(image_bytes),
                "denoise": pose_denoise,
                "seed": pose_seed
            }
            
            if save_to_file:
                output_dir = ensure_directory(OUTPUT_DIR / "characters" / "animations")
                fname = generate_filename(prefix=f"anim_{pose}")
                file_path = output_dir / fname
                file_path.write_bytes(image_bytes)
                anim_data["file_path"] = str(file_path)
            
            animations.append(anim_data)
        
        return json.dumps({
            "success": True,
            "description": description,
            "denoise": denoise,
            "base_seed": seed,
            "count": len(animations),
            "animations": animations
        }, indent=2)
Behavior4/5

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

With no annotations provided, the description carries full burden and does well by explaining key behavioral aspects: it describes the img2img approach, identity maintenance, parameter effects (e.g., denoise values), and output format. However, it doesn't mention potential limitations like rate limits, file size constraints, or error conditions.

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

Conciseness4/5

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

The description is well-structured with clear sections (purpose, args, returns, workflow) and every sentence adds value. While slightly longer than minimal, the information density is high and the example workflow is particularly helpful. Minor room exists for tighter phrasing.

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

Completeness5/5

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

Given the complexity (8 parameters, no annotations, but with output schema), the description is remarkably complete. It covers purpose, usage workflow, parameter semantics, and output format. The output schema handles return values, so the description appropriately focuses on usage context rather than duplicating structured data.

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

Parameters5/5

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

With 0% schema description coverage, the description fully compensates by providing detailed semantic explanations for all 8 parameters, including default values, ranges (e.g., '0.2=very similar, 0.5=more different'), and practical examples. It adds significant value beyond what the bare 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 the tool's purpose with specific verbs ('generate multiple character poses') and resources ('reference character image'), distinguishing it from siblings like 'generate_character' (which creates initial characters) and 'generate_sprite' (which might produce different outputs). It explicitly mentions using img2img technology for identity consistency.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool versus alternatives through the example workflow, which states: 'First generate a base character with generate_character(description, poses=["idle"])' and then use this tool for pose variations. This clearly distinguishes it from the sibling 'generate_character' tool.

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/tuannguyen14/ComfyAI-MCP-GameAssets'

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