Skip to main content
Glama

edit_entire_level

Replace all tiles and modify metadata for VibeTide 2D platformer levels to create custom gameplay environments with controlled enemy and coin parameters.

Instructions

Edit an entire VibeTide level, replacing all tiles and optionally metadata.

Args:
    level_data: The original level data (for reference)
    new_tiles: 2D array of tile types (each 0-7)
    new_name: New name for the level (optional)
    new_description: New description for the level (optional)
    max_enemies: Maximum enemies parameter (1-10, optional)
    enemy_spawn_chance: Enemy spawn chance percentage (0-100, optional)
    coin_spawn_chance: Coin spawn chance percentage (0-100, optional)

Returns the completely modified level data.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
level_dataYes
new_tilesYes
new_nameNo
new_descriptionNo
max_enemiesNo
enemy_spawn_chanceNo
coin_spawn_chanceNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The @mcp.tool()-decorated handler function that implements the core logic for the 'edit_entire_level' tool. It validates the input new_tiles 2D array and optional metadata parameters, constructs the new level data, encodes it using LevelEncoder, generates visualization and play URL, and returns the result.
    @mcp.tool()
    async def edit_entire_level(
        level_data: Dict[str, Any],
        new_tiles: List[List[int]],
        new_name: Optional[str] = None,
        new_description: Optional[str] = None,
        max_enemies: Optional[int] = None,
        enemy_spawn_chance: Optional[float] = None,
        coin_spawn_chance: Optional[float] = None,
    ) -> Dict[str, Any]:
        """Edit an entire VibeTide level, replacing all tiles and optionally metadata.
    
        Args:
            level_data: The original level data (for reference)
            new_tiles: 2D array of tile types (each 0-7)
            new_name: New name for the level (optional)
            new_description: New description for the level (optional)
            max_enemies: Maximum enemies parameter (1-10, optional)
            enemy_spawn_chance: Enemy spawn chance percentage (0-100, optional)
            coin_spawn_chance: Coin spawn chance percentage (0-100, optional)
    
        Returns the completely modified level data.
        """
        try:
            # Validate new tiles array
            if not isinstance(new_tiles, list) or not new_tiles:
                return {"success": False, "error": "new_tiles must be a non-empty 2D array"}
    
            # Validate dimensions
            height = len(new_tiles)
            width = len(new_tiles[0]) if new_tiles else 0
    
            if width == 0:
                return {"success": False, "error": "new_tiles rows cannot be empty"}
    
            # Validate all rows have same width and contain valid tile types
            for row_idx, row in enumerate(new_tiles):
                if not isinstance(row, list):
                    return {"success": False, "error": f"Row {row_idx} is not a list"}
    
                if len(row) != width:
                    return {
                        "success": False,
                        "error": f"Row {row_idx} has length {len(row)}, expected {width}",
                    }
    
                for col_idx, tile_type in enumerate(row):
                    if not isinstance(tile_type, int) or tile_type < 0 or tile_type > 7:
                        return {
                            "success": False,
                            "error": f"Invalid tile type {tile_type} at ({row_idx}, {col_idx}) - must be integer 0-7",
                        }
    
            # Create new level data
            edited_level = {
                "tiles": [row.copy() for row in new_tiles],
                "width": width,
                "height": height,
                "name": new_name or level_data.get("name", "Edited Level"),
                "description": new_description
                or level_data.get("description", "A custom edited level"),
            }
    
            # Add game parameters if provided
            if max_enemies is not None:
                if not isinstance(max_enemies, int) or max_enemies < 0 or max_enemies > 10:
                    return {"success": False, "error": "max_enemies must be integer 0-10"}
                edited_level["maxEnemies"] = max_enemies
            elif "maxEnemies" in level_data:
                edited_level["maxEnemies"] = level_data["maxEnemies"]
    
            if enemy_spawn_chance is not None:
                if (
                    not isinstance(enemy_spawn_chance, (int, float))
                    or enemy_spawn_chance < 0
                    or enemy_spawn_chance > 100
                ):
                    return {
                        "success": False,
                        "error": "enemy_spawn_chance must be number 0-100",
                    }
                edited_level["enemySpawnChance"] = float(enemy_spawn_chance)
            elif "enemySpawnChance" in level_data:
                edited_level["enemySpawnChance"] = level_data["enemySpawnChance"]
    
            if coin_spawn_chance is not None:
                if (
                    not isinstance(coin_spawn_chance, (int, float))
                    or coin_spawn_chance < 0
                    or coin_spawn_chance > 100
                ):
                    return {
                        "success": False,
                        "error": "coin_spawn_chance must be number 0-100",
                    }
                edited_level["coinSpawnChance"] = float(coin_spawn_chance)
            elif "coinSpawnChance" in level_data:
                edited_level["coinSpawnChance"] = level_data["coinSpawnChance"]
    
            # Generate encoded version
            try:
                encoded_level = level_encoder.encode(edited_level)
                play_url = f"{VIBE_TIDE_CONFIG['web_player_url']}?level={encoded_level}"
            except Exception as e:
                logger.warning(f"Failed to encode edited level: {e}")
                encoded_level = None
                play_url = None
    
            # Generate visualization
            visualization = visualize_level(edited_level)
    
            return {
                "success": True,
                "level_data": edited_level,
                "encoded_level": encoded_level,
                "play_url": play_url,
                "visualization": visualization,
                "change_summary": f"Replaced entire level: {width}x{height} tiles",
                "message": f"Successfully edited entire level '{edited_level['name']}'",
            }
    
        except Exception as e:
            logger.error(f"Failed to edit entire level: {e}")
            return {"success": False, "error": f"Failed to edit entire level: {str(e)}"}
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 edits and replaces content, implying mutation, but lacks details on permissions, side effects (e.g., overwriting existing data), error handling, or rate limits. The mention of 'Returns the completely modified level data' adds some behavioral context, but it's minimal for a mutation tool.

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 and appropriately sized, with a clear opening sentence stating the purpose, followed by a detailed parameter list. Every sentence adds value, though the parameter explanations could be slightly more concise (e.g., combining similar optional fields).

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

Completeness4/5

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

Given the complexity (7 parameters, mutation tool, no annotations) and an output schema (which handles return values), the description is reasonably complete. It covers the purpose and parameters thoroughly, but lacks usage guidelines and behavioral details like error cases or prerequisites, leaving some gaps for the agent.

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?

The description adds significant meaning beyond the input schema, which has 0% description coverage. It explains each parameter's purpose, constraints (e.g., tile types 0-7, ranges for percentages), and optionality, effectively compensating for the schema's lack of documentation and providing essential context for correct usage.

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

Purpose4/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: 'Edit an entire VibeTide level, replacing all tiles and optionally metadata.' It specifies the verb ('edit'), resource ('VibeTide level'), and scope ('entire'), but doesn't explicitly differentiate from siblings like edit_level_metadata or edit_level_tile, which likely handle partial edits.

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. With siblings like edit_level_metadata and edit_level_tile that handle partial edits, the description doesn't indicate that this tool is for complete replacements or when that's preferable, leaving the agent to infer usage from the name and parameters alone.

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/banjtheman/vibe_tide_mcp'

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