Skip to main content
Glama

godot_attach_script

Attach GDScript files to Godot scene nodes, creating scripts automatically when needed to streamline game development workflows.

Instructions

Attach a GDScript file to a specific node in a saved scene, creating the script file first when needed.

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 receive the script. Use '.' for the root node..
script_pathNoOptional absolute, relative, or res:// path for the target `.gd` file inside the project.
script_nameNoOptional human-friendly script name or filename when creating a new script, such as 'Hero Controller' or 'hero_controller.gd'.
folderNoProject-relative folder where a new script should be created when `script_path` is omitted.scripts
script_codeNoOptional explicit GDScript source. When omitted and the script does not exist yet, a starter template is generated.
overwriteNoWhether to replace an existing script file when `script_code` is provided.
godot_executableNoOptional explicit path to the Godot executable or .app bundle.

Implementation Reference

  • Implementation of the 'attach_script' tool, which attaches a GDScript file to a node in a Godot scene.
    def attach_script(
        self,
        project_path: str,
        scene_path: str,
        node_path: str = ".",
        script_path: str | None = None,
        script_name: str | None = None,
        folder: str = "scripts",
        script_code: str | None = None,
        overwrite: 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)
        scene_tree = self.get_scene_tree(
            project_path=str(project_dir),
            scene_path=resource_scene_path,
            godot_executable=str(executable),
        )
    
        node_info = next(
            (node for node in scene_tree["nodes"] if node.get("path") == normalized_node_path),
            None,
        )
        if node_info is None:
            raise GodotError(
                f"Node not found at path `{normalized_node_path}` in scene {resource_scene_path}."
            )
    
        node_name = str(node_info.get("name", "")).strip() or "Node"
        node_type = str(node_info.get("type", "")).strip() or "Node"
    
        if script_path:
            absolute_script_path, resource_script_path = resolve_project_file_path(project_dir, script_path)
        else:
            normalized_folder = normalize_project_subdir(folder)
            script_dir = project_dir / normalized_folder if normalized_folder else project_dir
            base_name = (script_name or "").strip() or node_name
            filename_base = base_name[:-3] if base_name.lower().endswith(".gd") else base_name
            filename = f"{snake_case_name(filename_base, default='script')}.gd"
            absolute_script_path = (script_dir / filename).resolve()
            relative_script_path = absolute_script_path.relative_to(project_dir)
            resource_script_path = f"res://{relative_script_path.as_posix()}"
    
        if absolute_script_path.suffix.lower() != ".gd":
            raise GodotError("Attached scripts must point to a `.gd` file.")
    
        absolute_script_path.parent.mkdir(parents=True, exist_ok=True)
        existed_before = absolute_script_path.exists()
        wrote_script = False
        created_from_template = False
    
        if script_code is not None:
            if existed_before and not overwrite:
                raise GodotError(
                    f"Script already exists at {absolute_script_path}. Pass `overwrite=true` to replace it."
                )
            final_script_code = script_code if script_code.endswith("\n") else script_code + "\n"
            absolute_script_path.write_text(final_script_code, encoding="utf-8")
            wrote_script = True
        elif not existed_before:
            absolute_script_path.write_text(_default_script_source(node_type), encoding="utf-8")
            wrote_script = True
            created_from_template = True
    
        if not absolute_script_path.exists():
            raise GodotError(f"Script not found: {absolute_script_path}")
    
        output = _run_godot_script(
            executable=executable,
            project_dir=project_dir,
            script_name="attach_script.gd",
            user_args=[
                "--scene-path",
                resource_scene_path,
                "--node-path",
                normalized_node_path,
                "--script-path",
                resource_script_path,
            ],
        )
        parsed = _parse_script_json_output(output, "attach_script.gd")
    
        return {
            "project_path": str(project_dir),
            "scene_path": str(absolute_scene_path),
            "scene_resource_path": resource_scene_path,
            "node_path": parsed.get("node_path", normalized_node_path),
            "node_name": parsed.get("node_name", node_name),
            "node_type": parsed.get("node_type", node_type),
            "script_path": str(absolute_script_path),
            "script_resource_path": resource_script_path,
            "created_script": wrote_script and not existed_before,
            "updated_script": wrote_script and existed_before,
            "created_from_template": created_from_template,
            "previous_script_resource_path": parsed.get("previous_script_path", ""),
            "replaced_existing_script": bool(parsed.get("previous_script_path")),
            "godot_executable": str(executable),
            "godot_version": version,
        }
  • Registration of the 'godot_attach_script' tool in the Godot MCP server.
        name="godot_attach_script",
        description="Attach a GDScript file to a specific node in a saved scene, creating the script file first when needed.",
        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 receive the script. Use '.' for the root node.",
                    "default": ".",
                },
                "script_path": {
                    "type": "string",
                    "description": "Optional absolute, relative, or res:// path for the target `.gd` file inside the project.",
                },
                "script_name": {
                    "type": "string",
                    "description": "Optional human-friendly script name or filename when creating a new script, such as 'Hero Controller' or 'hero_controller.gd'.",
                },
                "folder": {
                    "type": "string",
                    "description": "Project-relative folder where a new script should be created when `script_path` is omitted.",
                    "default": "scripts",
                },
                "script_code": {
                    "type": "string",
                    "description": "Optional explicit GDScript source. When omitted and the script does not exist yet, a starter template is generated.",
                },
                "overwrite": {
                    "type": "boolean",
                    "description": "Whether to replace an existing script file when `script_code` is provided.",
                    "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.attach_script(
            project_path=args["project_path"],
            scene_path=args["scene_path"],
            node_path=args.get("node_path", "."),
            script_path=args.get("script_path"),
            script_name=args.get("script_name"),
            folder=args.get("folder", "scripts"),
            script_code=args.get("script_code"),
            overwrite=bool(args.get("overwrite", 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