Skip to main content
Glama
duke0317

Image Processing MCP Server

by duke0317

create_gif

Create animated GIFs from multiple image sources by specifying frame duration and loop settings for visual storytelling or demonstration purposes.

Instructions

创建GIF动画

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
image_sourcesYes图片源列表,每个元素可以是文件路径或base64编码的图片数据
durationNo每帧持续时间(毫秒)
loopNo循环次数,0表示无限循环

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • main.py:772-792 (registration)
    MCP tool registration for 'create_gif' using @mcp.tool() decorator. This wrapper function collects arguments and calls the advanced handler.
    @mcp.tool()
    def create_gif(
        image_sources: Annotated[list, Field(description="图片源列表,每个元素可以是文件路径或base64编码的图片数据")],
        duration: Annotated[int, Field(description="每帧持续时间(毫秒)", ge=50, default=500)],
        loop: Annotated[int, Field(description="循环次数,0表示无限循环", ge=0, default=0)]
    ) -> str:
        """创建GIF动画"""
        try:
            arguments = {
                "image_sources": image_sources,
                "duration": duration,
                "loop": loop
            }
            result = safe_run_async(advanced_create_gif(arguments))
            return result[0].text
        except Exception as e:
            return json.dumps({
                "success": False,
                "error": f"创建GIF失败: {str(e)}"
            }, ensure_ascii=False, indent=2)
  • Core implementation of the create_gif tool. Loads multiple images, converts to RGB, resizes frames to match, saves as animated GIF to TEMP_DIR using PIL, returns file reference.
    async def create_gif(arguments: Dict[str, Any]) -> List[TextContent]:
        """
        从多张图片创建GIF动画
        
        Args:
            arguments: 包含图片源列表和GIF参数的字典
            
        Returns:
            List[TextContent]: 处理结果
        """
        try:
            # 参数验证
            image_sources = arguments.get("image_sources", [])
            if len(image_sources) < 2:
                raise ValidationError("至少需要2张图片")
            
            duration = arguments.get("duration", 500)
            loop = arguments.get("loop", 0)  # 默认0表示无限循环
            optimize = arguments.get("optimize", True)
            resize_to = arguments.get("resize_to")
            
            # 验证参数
            validate_numeric_range(duration, 100, 5000, "duration")
            
            processor = ImageProcessor()
            frames = []
            
            # 加载所有图片
            for source in image_sources:
                ensure_valid_image_source(source)
                image = processor.load_image(source)
                
                # 转换为RGB模式(GIF不支持RGBA)
                if image.mode != "RGB":
                    if image.mode == "RGBA":
                        # 创建白色背景
                        background = Image.new("RGB", image.size, (255, 255, 255))
                        background.paste(image, mask=image.split()[-1])
                        image = background
                    else:
                        image = image.convert("RGB")
                
                frames.append(image)
            
            # 调整所有帧到相同尺寸
            if resize_to:
                target_width = resize_to.get("width")
                target_height = resize_to.get("height")
                if target_width and target_height:
                    frames = [frame.resize((target_width, target_height), Image.Resampling.LANCZOS) 
                             for frame in frames]
            else:
                # 使用第一帧的尺寸
                target_size = frames[0].size
                frames = [frame.resize(target_size, Image.Resampling.LANCZOS) for frame in frames]
            
            # 生成唯一文件名并保存到temp目录
            import uuid
            import os
            from config import TEMP_DIR
            
            unique_id = str(uuid.uuid4())[:8]
            gif_filename = f"gif_{unique_id}.gif"
            gif_path = os.path.join(TEMP_DIR, gif_filename)
            
            # 确保temp目录存在
            os.makedirs(TEMP_DIR, exist_ok=True)
            
            # 创建并保存GIF
            frames[0].save(
                gif_path,
                format="GIF",
                save_all=True,
                append_images=frames[1:],
                duration=duration,
                loop=loop,  # 直接使用传入的整数值:0=无限循环,1=播放一次,n=循环n次
                optimize=optimize
            )
            
            # 获取文件大小
            file_size = os.path.getsize(gif_path)
            
            return [TextContent(
                type="text",
                text=json.dumps({
                    "success": True,
                    "message": f"成功创建包含{len(frames)}帧的GIF动画",
                    "data": {
                        "output_type": "file_reference",
                        "file_path": gif_path,
                        "format": "GIF",
                        "file_size": file_size,
                        "operation": "create_gif",
                        "frame_count": len(frames),
                        "size": [frames[0].width, frames[0].height],
                        "duration": duration,
                        "loop": loop,
                        "optimize": optimize
                    }
                }, ensure_ascii=False)
            )]
            
        except ValidationError as e:
            return [TextContent(
                type="text",
                text=json.dumps({
                    "success": False,
                    "error": f"参数验证失败: {str(e)}"
                }, ensure_ascii=False)
            )]
        except Exception as e:
            return [TextContent(
                type="text",
                text=json.dumps({
                    "success": False,
                    "error": f"创建GIF失败: {str(e)}"
                }, ensure_ascii=False)
            )]
  • JSON schema definition for create_gif tool inputs in get_advanced_tools() (note: actual registration uses pydantic in main.py)
    Tool(
        name="create_gif",
        description="从多张图片创建GIF动画",
        inputSchema={
            "type": "object",
            "properties": {
                "image_sources": {
                    "type": "array",
                    "description": "图片源列表(文件路径或base64编码)",
                    "items": {"type": "string"},
                    "minItems": 2,
                    "maxItems": 20
                },
                "duration": {
                    "type": "integer",
                    "description": "每帧持续时间(毫秒)",
                    "minimum": 100,
                    "maximum": 5000,
                    "default": 500
                },
                "loop": {
                    "type": "boolean",
                    "description": "是否循环播放",
                    "default": True
                },
                "optimize": {
                    "type": "boolean",
                    "description": "是否优化文件大小",
                    "default": True
                },
                "resize_to": {
                    "type": "object",
                    "description": "调整所有帧到指定尺寸",
                    "properties": {
                        "width": {"type": "integer", "minimum": 50, "maximum": 800},
                        "height": {"type": "integer", "minimum": 50, "maximum": 800}
                    }
                }
            },
            "required": ["image_sources"]
        }
    )
Behavior2/5

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

No annotations are provided, so the description carries full burden. It states the tool creates GIFs but doesn't disclose behavioral traits like whether it overwrites existing files, requires specific permissions, has rate limits, or what the output format/quality is. The description is minimal and lacks operational context needed for safe invocation.

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 extremely concise ('创建GIF动画') with no wasted words, but it's arguably under-specified rather than optimally concise. It's front-loaded with the core purpose, though more detail would improve utility without sacrificing brevity.

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 tool has an output schema (which handles return values) and full schema coverage for parameters, the description's minimalism is partially mitigated. However, for a mutation tool (creating GIFs) with no annotations, the description should provide more context about behavior, side effects, and usage scenarios to be complete.

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 description coverage is 100%, so the schema fully documents all three parameters (image_sources, duration, loop). The description adds no parameter semantics beyond what's in the schema, maintaining the baseline score of 3 since the schema does the heavy lifting.

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

Purpose3/5

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

The description '创建GIF动画' (Create GIF animation) states the basic purpose (verb+resource) but is vague about scope and mechanism. It doesn't specify whether this creates GIFs from image sequences, video, or other sources, nor does it distinguish this tool from sibling tools like 'create_collage' or 'create_thumbnail_grid' which also create composite outputs from images.

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 guidance is provided on when to use this tool versus alternatives. The description doesn't mention prerequisites (e.g., needing image files first), use cases (e.g., for animations vs static images), or comparisons to sibling tools like 'create_collage' for different output types.

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/duke0317/ps-mcp'

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