MCP 서버

Spritesheet Forge

io.github.LAXY9887/spritesheet-forge
디자인 및 크리에이티브 게임 공개 · 연결 가능 MCP 2026-07-28

이 MCP로 할 수 있는 일

Converts, trims, splits, assembles, and animates PNG, GIF, and spritesheet assets for game development.

frames_to_animation
Assemble multiple PNG files into an animated GIF or animated WebP.
외부 접근 가능
입력 스키마
{'type': 'object', 'required': ['files'], 'properties': {'loop': {'type': 'integer', 'description': 'Loop count. 0 = infinite. Default: 0'}, 'files': {'type': 'array', 'items': {'type': 'string'}, 'description': 'PNG frames — HTTPS URLs, data URIs, or output URLs from previous tool calls (pass directly, no re-encoding needed). For local files < 4 MB each: base64-encode the bytes and prepend "data:image/png;base64," — you MUST strip ALL whitespace and newlines from the base64 string before prepending. For files ≥ 4 MB each: call server_info to get the upload_url, POST the file there (multipart/form-data, field "file", Bearer token), and pass the returned URL.'}, 'resize': {'enum': ['error', 'fill', 'transparent'], 'type': 'string', 'description': 'Dimension mismatch handling. Default: transparent'}, 'quality': {'type': 'integer', 'description': 'WebP lossy quality 0-100. Default: 80'}, 'duration': {'type': 'integer', 'description': 'Frame duration in ms (10-10000). Default: 100'}, 'lossless': {'type': 'boolean', 'description': 'WebP lossless mode. Default: false'}, 'bg_fill_color': {'type': 'string', 'description': 'Fill color for resize=fill. Hex #RRGGBB. Default: #000000'}, 'output_format': {'enum': ['gif', 'webp'], 'type': 'string', 'description': 'Output format. Default: gif'}, 'file_name_order': {'type': 'boolean', 'description': "Order frames by the numeric _N suffix in each filename (e.g. frame_00.png, frame_01.png) instead of by array order. REQUIRES every input filename to end with _N.<ext> — the name is taken from the URL's last path segment. IMPORTANT: this server's upload endpoint renames every file to output-<hex>.png (no _N suffix), and data URIs carry no filename, so file_name_order=true is REJECTED (422) for both — it only works for external URLs that already end in _N.<ext>. TO ORDER FRAMES, PREFER doing it manually: leave this false and pass `files` in the exact order you want (the server preserves array order). If order matters but your inputs are upload URLs / data URIs / local files, fetch the files locally, CONFIRM the intended order with the user, then pass `files` in that order with file_name_order=false. Default: false"}}}
출력 스키마
{'type': 'object', 'required': ['url', 'expires_at', 'content_type', 'size_bytes', 'quota'], 'properties': {'url': {'type': 'string', 'description': 'Download URL for the output file (expires in 1 hour)'}, 'quota': {'type': 'object', 'required': ['used', 'limit', 'reset_at'], 'properties': {'used': {'type': 'number', 'description': 'Operations used this month'}, 'limit': {'type': 'number', 'description': 'Monthly operation limit'}, 'reset_at': {'type': 'string', 'description': 'Date quota resets (YYYY-MM-01)'}}}, 'expires_at': {'type': 'string', 'format': 'date-time', 'description': 'ISO 8601 expiry timestamp'}, 'size_bytes': {'type': 'number', 'description': 'Output file size in bytes'}, 'content_type': {'type': 'string', 'description': 'MIME type of the output file (image/png, image/gif, application/zip, etc.)'}}}
gif_to_frames
Extract all frames from a GIF and return them as individual PNGs in a ZIP archive.
외부 접근 가능
입력 스키마
{'type': 'object', 'required': ['file'], 'properties': {'file': {'type': 'string', 'description': 'GIF file — HTTPS URL, data URI, or output URL from a previous tool call (pass directly, no re-encoding needed). For local files < ~185 KB: base64-encode the bytes and prepend "data:image/gif;base64," — you MUST strip ALL whitespace and newlines from the base64 string before prepending (shell encoders like openssl insert newlines that cause INVALID_BASE64). For larger files or any file encoded via a shell command: call server_info to get the upload_url and token instructions, POST the file there (multipart/form-data, field "file", Bearer token required), and pass the returned URL.'}, 'bg_color': {'type': 'string', 'description': '"auto" or hex "#RRGGBB"'}, 'remove_bg': {'type': 'boolean', 'description': 'Remove background from each frame. Default: false'}, 'tolerance': {'type': 'integer', 'description': 'Background removal threshold 0-255. Default: 30'}}}
출력 스키마
{'type': 'object', 'required': ['url', 'expires_at', 'content_type', 'size_bytes', 'quota'], 'properties': {'url': {'type': 'string', 'description': 'Download URL for the output file (expires in 1 hour)'}, 'quota': {'type': 'object', 'required': ['used', 'limit', 'reset_at'], 'properties': {'used': {'type': 'number', 'description': 'Operations used this month'}, 'limit': {'type': 'number', 'description': 'Monthly operation limit'}, 'reset_at': {'type': 'string', 'description': 'Date quota resets (YYYY-MM-01)'}}}, 'expires_at': {'type': 'string', 'format': 'date-time', 'description': 'ISO 8601 expiry timestamp'}, 'size_bytes': {'type': 'number', 'description': 'Output file size in bytes'}, 'content_type': {'type': 'string', 'description': 'MIME type of the output file (image/png, image/gif, application/zip, etc.)'}}}
gif_to_spritesheet
Convert a GIF animation into a spritesheet PNG with all frames arranged in a grid. Optionally remove the background.
외부 접근 가능
입력 스키마
{'type': 'object', 'required': ['file'], 'properties': {'file': {'type': 'string', 'description': 'GIF file — HTTPS URL, data URI, or output URL from a previous tool call (pass directly, no re-encoding needed). For local files < ~185 KB: base64-encode the bytes and prepend "data:image/gif;base64," — you MUST strip ALL whitespace and newlines from the base64 string before prepending (shell encoders like openssl insert newlines that cause INVALID_BASE64). For larger files or any file encoded via a shell command: call server_info to get the upload_url and token instructions, POST the file there (multipart/form-data, field "file", Bearer token required), and pass the returned URL.'}, 'columns': {'type': 'integer', 'description': 'Grid columns. Auto-calculated if omitted.'}, 'padding': {'type': 'integer', 'description': 'Pixel gap between frames. Default: 0'}, 'bg_color': {'type': 'string', 'description': '"auto" or hex "#RRGGBB". Default: "auto"'}, 'remove_bg': {'type': 'boolean', 'description': 'Remove background from each frame. Default: false'}, 'tolerance': {'type': 'integer', 'description': 'Background removal threshold 0-255. Default: 30'}}}
출력 스키마
{'type': 'object', 'required': ['url', 'expires_at', 'content_type', 'size_bytes', 'quota'], 'properties': {'url': {'type': 'string', 'description': 'Download URL for the output file (expires in 1 hour)'}, 'quota': {'type': 'object', 'required': ['used', 'limit', 'reset_at'], 'properties': {'used': {'type': 'number', 'description': 'Operations used this month'}, 'limit': {'type': 'number', 'description': 'Monthly operation limit'}, 'reset_at': {'type': 'string', 'description': 'Date quota resets (YYYY-MM-01)'}}}, 'expires_at': {'type': 'string', 'format': 'date-time', 'description': 'ISO 8601 expiry timestamp'}, 'size_bytes': {'type': 'number', 'description': 'Output file size in bytes'}, 'content_type': {'type': 'string', 'description': 'MIME type of the output file (image/png, image/gif, application/zip, etc.)'}}}
png_to_spritesheet
Merge multiple PNG files into a single spritesheet. Supports grid, horizontal, vertical, and packed (bin-packed) layouts with optional TexturePacker-compatible JSON metadata. Returns a download URL.
외부 접근 가능
입력 스키마
{'type': 'object', 'required': ['files'], 'properties': {'align': {'enum': ['center', 'top_left'], 'type': 'string'}, 'files': {'type': 'array', 'items': {'type': 'string'}, 'description': 'PNG files — HTTPS URLs, data URIs, or output URLs from previous tool calls (pass directly, no re-encoding needed). For local files < ~185 KB each: base64-encode the bytes and prepend "data:image/png;base64," — you MUST strip ALL whitespace and newlines from the base64 string before prepending (shell encoders like openssl insert newlines that cause INVALID_BASE64). For larger files or any file encoded via a shell command: call server_info to get the upload_url and token instructions, POST the file there (multipart/form-data, field "file", Bearer token required), and pass the returned URL.'}, 'layout': {'enum': ['grid', 'horizontal', 'vertical', 'packed'], 'type': 'string', 'description': 'Frame arrangement. Default: grid'}, 'columns': {'type': 'integer', 'description': 'Grid columns. Auto-calculated if omitted.'}, 'extrude': {'type': 'integer', 'description': 'Extrude outermost pixels by N px per frame'}, 'padding': {'type': 'integer', 'description': 'Pixel gap between frames'}, 'bg_color': {'type': 'string', 'description': '"transparent" or hex "#RRGGBB"'}, 'fit_mode': {'enum': ['scale_fit', 'scale_fill', 'error'], 'type': 'string'}, 'cell_mode': {'enum': ['auto_max', 'auto_uniform', 'fixed'], 'type': 'string', 'description': 'Cell sizing mode. Default: auto_max'}, 'cell_width': {'type': 'integer', 'description': 'Required when cell_mode=fixed'}, 'power_of_2': {'type': 'boolean', 'description': 'Pad output to next power of 2'}, 'trim_input': {'type': 'boolean', 'description': 'Auto-trim transparent edges before compositing'}, 'cell_height': {'type': 'integer', 'description': 'Required when cell_mode=fixed'}, 'file_name_order': {'type': 'boolean', 'description': "Order frames by the numeric _N suffix in each filename (e.g. frame_00.png, frame_01.png) instead of by array order. REQUIRES every input filename to end with _N.<ext> — the name is taken from the URL's last path segment. IMPORTANT: this server's upload endpoint renames every file to output-<hex>.png (no _N suffix), and data URIs carry no filename, so file_name_order=true is REJECTED (422) for both — it only works for external URLs that already end in _N.<ext>. TO ORDER FRAMES, PREFER doing it manually: leave this false and pass `files` in the exact order you want (the server preserves array order). If order matters but your inputs are upload URLs / data URIs / local files, fetch the files locally, CONFIRM the intended order with the user, then pass `files` in that order with file_name_order=false. Default: false"}, 'metadata_format': {'enum': ['none', 'json_array', 'json_hash', 'css'], 'type': 'string', 'description': 'Atlas metadata format. Required (non-none) when layout=packed'}}}
출력 스키마
{'type': 'object', 'required': ['url', 'expires_at', 'content_type', 'size_bytes', 'quota'], 'properties': {'url': {'type': 'string', 'description': 'Download URL for the output file (expires in 1 hour)'}, 'quota': {'type': 'object', 'required': ['used', 'limit', 'reset_at'], 'properties': {'used': {'type': 'number', 'description': 'Operations used this month'}, 'limit': {'type': 'number', 'description': 'Monthly operation limit'}, 'reset_at': {'type': 'string', 'description': 'Date quota resets (YYYY-MM-01)'}}}, 'expires_at': {'type': 'string', 'format': 'date-time', 'description': 'ISO 8601 expiry timestamp'}, 'size_bytes': {'type': 'number', 'description': 'Output file size in bytes'}, 'content_type': {'type': 'string', 'description': 'MIME type of the output file (image/png, image/gif, application/zip, etc.)'}}}
server_info
Returns this server's runtime configuration: upload endpoint URL, output file TTL, file size limits, and base64 encoding rules. Call this before working with large files (≥ 4 MB) or when building multi-step workflows that chain tool outputs.
읽기 전용 멱등성
입력 스키마
{'type': 'object', 'required': [], 'properties': {}}
출력 스키마
{'type': 'object', 'required': ['upload_url', 'output_ttl_seconds', 'max_file_bytes', 'base64_threshold_bytes', 'file_input_rules'], 'properties': {'upload_url': {'type': 'string', 'description': 'URL for uploading files via multipart/form-data (Bearer token required)'}, 'max_file_bytes': {'type': 'number', 'description': 'Maximum accepted file size in bytes'}, 'file_input_rules': {'type': 'object', 'properties': {'large_file': {'type': 'string'}, 'small_file': {'type': 'string'}, 'ttl_warning': {'type': 'string'}, 'previous_output': {'type': 'string'}, 'token_for_upload': {'type': 'string'}}, 'description': 'Guidance for agents on how to pass file inputs'}, 'output_ttl_seconds': {'type': 'number', 'description': 'Seconds until output files expire'}, 'base64_threshold_bytes': {'type': 'number', 'description': 'Files smaller than this can be sent as base64 data URIs'}}}
split_spritesheet
Slice a spritesheet PNG into individual frames, generate TexturePacker-compatible atlas JSON, or both. Provide columns+rows (grid mode) or cell_width+cell_height (cell mode).
외부 접근 가능
입력 스키마
{'type': 'object', 'required': ['file'], 'properties': {'file': {'type': 'string', 'description': 'Spritesheet PNG — HTTPS URL, data URI, or output URL from a previous tool call (pass directly, no re-encoding needed). For local files < 4 MB: base64-encode the bytes and prepend "data:image/png;base64," — you MUST strip ALL whitespace and newlines from the base64 string before prepending. For files ≥ 4 MB: call server_info to get the upload_url, POST the file there (multipart/form-data, field "file", Bearer token), and pass the returned URL.'}, 'rows': {'type': 'integer', 'description': 'Grid rows (grid mode)'}, 'output': {'enum': ['frames', 'metadata', 'both'], 'type': 'string', 'description': 'Default: frames'}, 'columns': {'type': 'integer', 'description': 'Grid columns (grid mode)'}, 'padding': {'type': 'integer'}, 'trim_top': {'type': 'integer'}, 'row_range': {'type': 'string'}, 'trim_left': {'type': 'integer'}, 'cell_width': {'type': 'integer', 'description': 'Cell width in px (cell mode)'}, 'skip_empty': {'type': 'boolean', 'description': 'Remove fully transparent frames. Default: true'}, 'trim_right': {'type': 'integer'}, 'cell_height': {'type': 'integer', 'description': 'Cell height in px (cell mode)'}, 'frame_count': {'type': 'integer'}, 'trim_bottom': {'type': 'integer'}, 'column_range': {'type': 'string', 'description': 'e.g. "0-5" or "2"'}, 'metadata_format': {'enum': ['json_array', 'json_hash', 'css'], 'type': 'string'}}}
출력 스키마
{'type': 'object', 'required': ['url', 'expires_at', 'content_type', 'size_bytes', 'quota'], 'properties': {'url': {'type': 'string', 'description': 'Download URL for the output file (expires in 1 hour)'}, 'quota': {'type': 'object', 'required': ['used', 'limit', 'reset_at'], 'properties': {'used': {'type': 'number', 'description': 'Operations used this month'}, 'limit': {'type': 'number', 'description': 'Monthly operation limit'}, 'reset_at': {'type': 'string', 'description': 'Date quota resets (YYYY-MM-01)'}}}, 'expires_at': {'type': 'string', 'format': 'date-time', 'description': 'ISO 8601 expiry timestamp'}, 'size_bytes': {'type': 'number', 'description': 'Output file size in bytes'}, 'content_type': {'type': 'string', 'description': 'MIME type of the output file (image/png, image/gif, application/zip, etc.)'}}}
spritesheet_to_animation
Slice a spritesheet PNG into frames and produce an animated GIF or WebP. Provide columns+rows (grid mode) or cell_width+cell_height (cell mode).
외부 접근 가능
입력 스키마
{'type': 'object', 'required': ['file'], 'properties': {'file': {'type': 'string', 'description': 'Spritesheet PNG — HTTPS URL, data URI, or output URL from a previous tool call (pass directly, no re-encoding needed). For local files < ~185 KB: base64-encode the bytes and prepend "data:image/png;base64," — you MUST strip ALL whitespace and newlines from the base64 string before prepending (shell encoders like openssl insert newlines that cause INVALID_BASE64). For larger files or any file encoded via a shell command: call server_info to get the upload_url and token instructions, POST the file there (multipart/form-data, field "file", Bearer token required), and pass the returned URL.'}, 'loop': {'type': 'integer', 'description': 'Loop count. 0 = infinite. Default: 0'}, 'rows': {'type': 'integer', 'description': 'Grid rows (grid mode)'}, 'columns': {'type': 'integer', 'description': 'Grid columns (grid mode)'}, 'padding': {'type': 'integer', 'description': 'Pixel gap between cells. Default: 0'}, 'quality': {'type': 'integer', 'description': 'WebP quality 0-100. Default: 80'}, 'duration': {'type': 'integer', 'description': 'Frame duration in ms. Default: 100'}, 'lossless': {'type': 'boolean', 'description': 'WebP lossless. Default: false'}, 'trim_top': {'type': 'integer'}, 'row_range': {'type': 'string'}, 'trim_left': {'type': 'integer'}, 'cell_width': {'type': 'integer', 'description': 'Cell width in px (cell mode)'}, 'skip_empty': {'type': 'boolean', 'description': 'Auto-remove fully transparent frames. Default: true'}, 'trim_right': {'type': 'integer'}, 'cell_height': {'type': 'integer', 'description': 'Cell height in px (cell mode)'}, 'frame_count': {'type': 'integer', 'description': 'Actual frame count for incomplete last row'}, 'trim_bottom': {'type': 'integer'}, 'column_range': {'type': 'string', 'description': 'e.g. "0-5" or "2"'}, 'output_format': {'enum': ['gif', 'webp'], 'type': 'string', 'description': 'Default: gif'}}}
출력 스키마
{'type': 'object', 'required': ['url', 'expires_at', 'content_type', 'size_bytes', 'quota'], 'properties': {'url': {'type': 'string', 'description': 'Download URL for the output file (expires in 1 hour)'}, 'quota': {'type': 'object', 'required': ['used', 'limit', 'reset_at'], 'properties': {'used': {'type': 'number', 'description': 'Operations used this month'}, 'limit': {'type': 'number', 'description': 'Monthly operation limit'}, 'reset_at': {'type': 'string', 'description': 'Date quota resets (YYYY-MM-01)'}}}, 'expires_at': {'type': 'string', 'format': 'date-time', 'description': 'ISO 8601 expiry timestamp'}, 'size_bytes': {'type': 'number', 'description': 'Output file size in bytes'}, 'content_type': {'type': 'string', 'description': 'MIME type of the output file (image/png, image/gif, application/zip, etc.)'}}}
trim_png
Crop transparent edges from one or more PNG files. Single file returns PNG; multiple files return a ZIP.
외부 접근 가능
입력 스키마
{'type': 'object', 'required': ['files'], 'properties': {'files': {'type': 'array', 'items': {'type': 'string'}, 'description': 'PNG files — HTTPS URLs, data URIs, or output URLs from previous tool calls (pass directly, no re-encoding needed). For local files < ~185 KB each: base64-encode the bytes and prepend "data:image/png;base64," — you MUST strip ALL whitespace and newlines from the base64 string before prepending (shell encoders like openssl insert newlines that cause INVALID_BASE64). For larger files or any file encoded via a shell command: call server_info to get the upload_url and token instructions, POST the file there (multipart/form-data, field "file", Bearer token required), and pass the returned URL.'}, 'padding': {'type': 'integer', 'description': 'Transparent margin to preserve around trimmed content. Default: 0'}, 'threshold': {'type': 'integer', 'description': 'Alpha threshold 0-255. Pixels with alpha ≤ threshold are trimmed. Default: 0'}}}
출력 스키마
{'type': 'object', 'required': ['url', 'expires_at', 'content_type', 'size_bytes', 'quota'], 'properties': {'url': {'type': 'string', 'description': 'Download URL for the output file (expires in 1 hour)'}, 'quota': {'type': 'object', 'required': ['used', 'limit', 'reset_at'], 'properties': {'used': {'type': 'number', 'description': 'Operations used this month'}, 'limit': {'type': 'number', 'description': 'Monthly operation limit'}, 'reset_at': {'type': 'string', 'description': 'Date quota resets (YYYY-MM-01)'}}}, 'expires_at': {'type': 'string', 'format': 'date-time', 'description': 'ISO 8601 expiry timestamp'}, 'size_bytes': {'type': 'number', 'description': 'Output file size in bytes'}, 'content_type': {'type': 'string', 'description': 'MIME type of the output file (image/png, image/gif, application/zip, etc.)'}}}
추가됨
spritesheet_to_animation
2026년 9월 17일 12:43 PM
추가됨
frames_to_animation
2026년 9월 17일 12:42 PM
추가됨
gif_to_frames
2026년 9월 17일 12:42 PM
추가됨
gif_to_spritesheet
2026년 9월 17일 12:42 PM
추가됨
trim_png
2026년 9월 17일 12:42 PM
추가됨
split_spritesheet
2026년 9월 17일 12:42 PM
추가됨
png_to_spritesheet
2026년 9월 17일 12:42 PM
추가됨
server_info
2026년 9월 17일 12:42 PM