view_level_image
Convert encoded VibeTide level data into a color-accurate PNG image for visual representation, generating temporary files for display in MCP clients.
Instructions
View a VibeTide level as a beautiful PNG image with proper colors.
This generates a much better visual representation than the ASCII version,
using the same colors as the web builder. The image is saved to a temporary
file and the file path is returned for MCP clients to display.
Args:
encoded_level: An encoded level string from a URL or sharing link
tile_size: Size of each tile in pixels (default 16, will auto-adjust for wide levels)
max_width: Maximum image width in pixels (default 1200)
Returns:
The file path to the generated PNG image
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| encoded_level | Yes | ||
| tile_size | No | ||
| max_width | No |
Implementation Reference
- vibe_tide_mcp_server.py:600-632 (handler)The main handler function for the 'view_level_image' MCP tool. It decodes the encoded level string and generates a PNG image file path using the helper function.@mcp.tool() async def view_level_image( encoded_level: str, tile_size: int = 16, max_width: int = 1200 ) -> str: """View a VibeTide level as a beautiful PNG image with proper colors. This generates a much better visual representation than the ASCII version, using the same colors as the web builder. The image is saved to a temporary file and the file path is returned for MCP clients to display. Args: encoded_level: An encoded level string from a URL or sharing link tile_size: Size of each tile in pixels (default 16, will auto-adjust for wide levels) max_width: Maximum image width in pixels (default 1200) Returns: The file path to the generated PNG image """ try: # Decode level from string level_data = level_encoder.decode(encoded_level) # Generate PNG image to temporary file image_path = generate_level_image_to_file(level_data, tile_size, max_width) return image_path except Exception as e: logger.error(f"Failed to generate level image: {e}") # Return error as string since we're returning a simple string now raise Exception(f"Failed to generate level image: {str(e)}")
- vibe_tide_mcp_server.py:483-567 (helper)The core helper function that creates the PNG image visualization of the level using Pillow library, drawing each tile with appropriate colors, borders, and labels if possible.def generate_level_image_to_file( level_data: Dict[str, Any], tile_size: int = 16, max_width: int = 1200 ) -> str: """Generate a PNG image of the level and save to a temporary file. Returns the file path.""" tiles = level_data.get("tiles", []) # Create a temporary file temp_file = tempfile.NamedTemporaryFile( delete=False, suffix=".png", prefix="vibe_tide_level_" ) temp_path = temp_file.name temp_file.close() if not tiles: # Create a small error image img = Image.new("RGB", (200, 100), (255, 255, 255)) draw = ImageDraw.Draw(img) draw.text((10, 40), "Empty Level", fill=(0, 0, 0)) img.save(temp_path, format="PNG") return temp_path height = len(tiles) width = len(tiles[0]) if tiles else 0 # Calculate image dimensions # For very wide levels, make tiles smaller to fit in max_width actual_tile_size = min(tile_size, max_width // width) if width > 0 else tile_size actual_tile_size = max(4, actual_tile_size) # Minimum 4px per tile img_width = width * actual_tile_size img_height = height * actual_tile_size # Create image with white background img = Image.new("RGB", (img_width, img_height), (255, 255, 255)) draw = ImageDraw.Draw(img) # Try to load a font for labels (fallback to default if not available) try: font = ImageFont.truetype("arial.ttf", max(8, actual_tile_size // 2)) except: try: font = ImageFont.load_default() except: font = None # Draw tiles for y in range(height): for x in range(width): tile_type = tiles[y][x] # Calculate tile position left = x * actual_tile_size top = y * actual_tile_size right = left + actual_tile_size bottom = top + actual_tile_size # Get colors fill_color = TILE_COLORS.get(tile_type, (128, 128, 128)) border_color = TILE_BORDER_COLORS.get(tile_type, (0, 0, 0)) # Draw tile background draw.rectangle( [left, top, right - 1, bottom - 1], fill=fill_color, outline=border_color, ) # Add label for non-empty tiles if tile is large enough if actual_tile_size >= 12 and tile_type != 0: label = TILE_LABELS.get(tile_type, str(tile_type)) if label and font: # Calculate text position (center of tile) bbox = draw.textbbox((0, 0), label, font=font) text_width = bbox[2] - bbox[0] text_height = bbox[3] - bbox[1] text_x = left + (actual_tile_size - text_width) // 2 text_y = top + (actual_tile_size - text_height) // 2 # Use white text for dark backgrounds, black for light text_color = (255, 255, 255) if sum(fill_color) < 400 else (0, 0, 0) draw.text((text_x, text_y), label, fill=text_color, font=font) # Save to temporary file img.save(temp_path, format="PNG", optimize=True) return temp_path
- vibe_tide_mcp_server.py:600-600 (registration)The @mcp.tool() decorator registers the view_level_image function as an MCP tool.@mcp.tool()