Skip to main content
Glama

godot_edit_scene

Modify existing nodes in Godot scenes by updating transforms, renaming, reparenting, or deleting them to edit game objects and structure.

Instructions

Modify an existing node in a saved scene by updating its transform, renaming it, reparenting it, or deleting it.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_pathYesPath to the Godot project directory or its project.godot file.
scene_pathYesPath to the target .tscn file. Absolute, relative, and res:// paths are supported.
node_pathNoScene-relative node path to edit. Use '.' for the root node..
transformNoOptional transform fields to update. Vector values can be passed as objects like {x, y} or {x, y, z}.
new_nameNoOptional new name for the target node.
new_parent_pathNoOptional new scene-relative parent path for the target node. Use '.' for the root.
deleteNoDelete the target node. This cannot be combined with other edits.
godot_executableNoOptional explicit path to the Godot executable or .app bundle.

Implementation Reference

  • The implementation of the `edit_scene` method in `GodotController`, which handles scene editing by invoking the `edit_scene.gd` helper script.
    def edit_scene(
        self,
        project_path: str,
        scene_path: str,
        node_path: str = ".",
        transform: dict[str, Any] | None = None,
        new_name: str | None = None,
        new_parent_path: str | None = None,
        delete: bool = False,
        godot_executable: str | None = None,
    ) -> dict[str, Any]:
        project_dir = ensure_project_path(project_path)
        executable, version = resolve_godot_executable(godot_executable)
        absolute_scene_path, resource_scene_path = resolve_scene_path(project_dir, scene_path)
    
        if not absolute_scene_path.exists():
            raise GodotError(f"Scene not found: {absolute_scene_path}")
    
        normalized_node_path = normalize_scene_node_path(node_path)
        changes: dict[str, Any] = {}
    
        if transform is not None:
            if not isinstance(transform, dict):
                raise GodotError("`transform` must be an object.")
            if not transform:
                raise GodotError("`transform` must contain at least one field to update.")
            changes["transform"] = transform
    
        if new_name is not None:
            final_new_name = new_name.strip()
            if not final_new_name:
                raise GodotError("`new_name` must not be empty.")
            changes["new_name"] = final_new_name
    
        if new_parent_path is not None:
            changes["new_parent_path"] = normalize_scene_node_path(new_parent_path)
    
        if delete:
            if changes:
                raise GodotError("`delete` cannot be combined with rename, reparent, or transform updates.")
            changes["delete"] = True
    
        if not changes:
            raise GodotError(
                "Provide at least one scene edit: `transform`, `new_name`, `new_parent_path`, or `delete`."
            )
    
        try:
            with tempfile.NamedTemporaryFile(
                mode="w",
                encoding="utf-8",
                suffix="-godot-scene-edit.json",
                delete=False,
            ) as handle:
                json.dump(changes, handle, ensure_ascii=False)
                changes_path = handle.name
        except TypeError as exc:
            raise GodotError("The requested scene edits contain a value that could not be serialized to JSON.") from exc
    
        try:
            output = _run_godot_script(
                executable=executable,
                project_dir=project_dir,
                script_name="edit_scene.gd",
                user_args=[
                    "--scene-path",
                    resource_scene_path,
                    "--node-path",
                    normalized_node_path,
                    "--changes-path",
                    changes_path,
                ],
            )
        finally:
            Path(changes_path).unlink(missing_ok=True)
    
        parsed = _parse_script_json_output(output, "edit_scene.gd")
    
        return {
            "project_path": str(project_dir),
            "scene_path": str(absolute_scene_path),
            "scene_resource_path": resource_scene_path,
            "node_path_before": parsed.get("node_path_before", normalized_node_path),
            "node_path_after": parsed.get("node_path_after"),
            "parent_path_before": parsed.get("parent_path_before"),
            "parent_path_after": parsed.get("parent_path_after"),
            "node_name_before": parsed.get("node_name_before"),
            "node_name_after": parsed.get("node_name_after"),
            "node_type": parsed.get("node_type"),
            "deleted": bool(parsed.get("deleted", False)),
            "applied_changes": parsed.get("applied_changes", []),
            "updated_transform_fields": parsed.get("updated_transform_fields", []),
            "transform_kind": parsed.get("transform_kind"),
            "supported_fields": parsed.get("supported_fields", []),
            "transform": parsed.get("transform", {}),
            "godot_executable": str(executable),
            "godot_version": version,
        }
  • The `godot_edit_scene` tool definition and its handler registration in `GodotMcpServer`.
        name="godot_edit_scene",
        description="Modify an existing node in a saved scene by updating its transform, renaming it, reparenting it, or deleting it.",
        input_schema={
            "type": "object",
            "properties": {
                "project_path": {
                    "type": "string",
                    "description": "Path to the Godot project directory or its project.godot file.",
                },
                "scene_path": {
                    "type": "string",
                    "description": "Path to the target .tscn file. Absolute, relative, and res:// paths are supported.",
                },
                "node_path": {
                    "type": "string",
                    "description": "Scene-relative node path to edit. Use '.' for the root node.",
                    "default": ".",
                },
                "transform": {
                    "type": "object",
                    "description": "Optional transform fields to update. Vector values can be passed as objects like {x, y} or {x, y, z}.",
                },
                "new_name": {
                    "type": "string",
                    "description": "Optional new name for the target node.",
                },
                "new_parent_path": {
                    "type": "string",
                    "description": "Optional new scene-relative parent path for the target node. Use '.' for the root.",
                },
                "delete": {
                    "type": "boolean",
                    "description": "Delete the target node. This cannot be combined with other edits.",
                    "default": False,
                },
                "godot_executable": {
                    "type": "string",
                    "description": "Optional explicit path to the Godot executable or .app bundle.",
                },
            },
            "required": ["project_path", "scene_path"],
            "additionalProperties": False,
        },
        handler=lambda args: self.controller.edit_scene(
            project_path=args["project_path"],
            scene_path=args["scene_path"],
            node_path=args.get("node_path", "."),
            transform=args.get("transform"),
            new_name=args.get("new_name"),
            new_parent_path=args.get("new_parent_path"),
            delete=bool(args.get("delete", False)),
            godot_executable=args.get("godot_executable"),
        ),
    ),

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/MhrnMhrn/godot-mcp'

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