Skip to main content
Glama
duke0317

Image Processing MCP Server

by duke0317

rotate_image

Rotate images by specified angles with options to expand canvas or crop, and set background fill colors for image processing workflows.

Instructions

旋转图片

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
image_sourceYes图片源,可以是文件路径或base64编码的图片数据
angleYes旋转角度(度),正值为顺时针,负值为逆时针
expandNo是否扩展画布以容纳旋转后的图片,False会裁剪
fill_colorNo填充颜色,十六进制格式如 #FFFFFF(白色)#FFFFFF

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • Core handler function that loads the image, validates parameters, rotates it using PIL.Image.rotate, processes output, and returns JSON result.
    async def rotate_image(image_data: str, angle: float, expand: bool = True, fill_color: str = "#FFFFFF") -> list[TextContent]:
        """
        旋转图片
        
        Args:
            image_data: 图片数据(base64编码)
            angle: 旋转角度(度,正值为顺时针)
            expand: 是否扩展画布
            fill_color: 填充颜色
            
        Returns:
            旋转后的图片数据
        """
        try:
            # 验证参数
            if not image_data:
                raise ValidationError("图片数据不能为空")
            
            if not validate_color_hex(fill_color):
                raise ValidationError(f"无效的颜色格式: {fill_color}")
            
            # 加载图片
            image = processor.load_image(image_data)
            original_size = image.size
            
            # 转换颜色格式
            fill_rgb = tuple(int(fill_color[i:i+2], 16) for i in (1, 3, 5))
            
            # 旋转图片
            rotated_image = image.rotate(
                -angle,  # PIL中负值为顺时针
                expand=expand,
                fillcolor=fill_rgb
            )
            
            # 输出旋转后的图片
            output_info = processor.output_image(rotated_image, f"rotate_{int(angle)}deg")
            
            result = {
                "success": True,
                "message": f"图片旋转成功: {angle}度",
                "data": {
                    **output_info,
                    "original_size": original_size,
                    "rotated_size": rotated_image.size,
                    "angle": angle,
                    "expand": expand,
                    "fill_color": fill_color
                }
            }
            
            return [TextContent(type="text", text=json.dumps(result, ensure_ascii=False))]
            
        except ValidationError as e:
            error_result = {
                "success": False,
                "error": f"参数验证失败: {str(e)}"
            }
            return [TextContent(type="text", text=json.dumps(error_result, ensure_ascii=False))]
            
        except Exception as e:
            error_result = {
                "success": False,
                "error": f"图片旋转失败: {str(e)}"
            }
            return [TextContent(type="text", text=json.dumps(error_result, ensure_ascii=False))]
  • main.py:206-222 (registration)
    MCP tool registration for 'rotate_image' using @mcp.tool() decorator. This wrapper function calls the core handler from tools.transform and handles errors.
    @mcp.tool()
    def rotate_image(
        image_source: Annotated[str, Field(description="图片源,可以是文件路径或base64编码的图片数据")],
        angle: Annotated[float, Field(description="旋转角度(度),正值为顺时针,负值为逆时针")],
        expand: Annotated[bool, Field(description="是否扩展画布以容纳旋转后的图片,False会裁剪", default=True)],
        fill_color: Annotated[str, Field(description="填充颜色,十六进制格式如 #FFFFFF(白色)", default="#FFFFFF")]
    ) -> str:
        """旋转图片"""
        try:
            result = safe_run_async(transform_rotate_image(image_source, angle, expand, fill_color))
            return result[0].text
        except Exception as e:
            return json.dumps({
                "success": False,
                "error": f"旋转图片失败: {str(e)}"
            }, ensure_ascii=False, indent=2)
  • Explicit input schema definition for the rotate_image tool, returned by get_transform_tools() function.
    Tool(
        name="rotate_image",
        description="旋转图片",
        inputSchema={
            "type": "object",
            "properties": {
                "image_data": {
                    "type": "string",
                    "description": "图片数据(base64编码)"
                },
                "angle": {
                    "type": "number",
                    "description": "旋转角度(度,正值为顺时针)"
                },
                "expand": {
                    "type": "boolean",
                    "description": "是否扩展画布以容纳旋转后的图片",
                    "default": True
                },
                "fill_color": {
                    "type": "string",
                    "description": "填充颜色(十六进制格式,如#FFFFFF)",
                    "default": "#FFFFFF"
                }
            },
            "required": ["image_data", "angle"]
        }
    ),
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It states the action 'rotate' but doesn't disclose behavioral traits like whether it modifies the original image, requires specific permissions, handles errors, or has performance implications. This is a significant gap for a mutation tool with zero annotation coverage.

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 a single phrase '旋转图片', which is concise and front-loaded. However, it's under-specified rather than efficiently informative, as it lacks necessary context for a tool with multiple parameters and sibling alternatives.

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 (not provided in details but indicated as true), the description needn't explain return values. However, with 4 parameters, no annotations, and many sibling tools, the description is incomplete—it doesn't cover usage context or behavioral aspects, making it minimally adequate but with clear gaps.

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 already documents all parameters (image_source, angle, expand, fill_color) with details like formats and defaults. The description adds no meaning beyond what the schema provides, but the baseline is 3 when schema coverage is high.

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 '旋转图片' (rotate image) states the basic action but is vague. It specifies the verb 'rotate' and resource 'image' but lacks details about what gets rotated (e.g., by angle) or how it distinguishes from siblings like 'flip_image'. It's not tautological but minimal.

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 on when to use this tool versus alternatives is provided. The description doesn't mention context, prerequisites, or exclusions, such as when to choose 'rotate_image' over 'flip_image' or other image manipulation tools in the sibling list.

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