Skip to main content
Glama
script-tools.ts7.77 kB
import type { ToolHandler } from "./types.js"; import type { GodotExecutor } from "../godot/executor.js"; import { isGodotProject } from "../godot/finder.js"; import * as fs from "fs/promises"; import * as path from "path"; // Create Script Tool export const createScriptTool: ToolHandler = { definition: { name: "create_script", description: "Create a new GDScript file with optional template or custom content", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "Absolute path to the Godot project directory", }, script_path: { type: "string", description: "Path for the new script file (e.g., 'res://scripts/player.gd')", }, extends: { type: "string", description: "Base class the script extends (e.g., 'CharacterBody2D', 'Node')", default: "Node", }, class_name: { type: "string", description: "Optional class_name for the script (makes it globally accessible)", }, content: { type: "string", description: "Full script content. If provided, overrides template generation", }, template: { type: "string", enum: ["default", "empty", "character_2d", "character_3d"], description: "Template to use if content is not provided", default: "default", }, }, required: ["project_path", "script_path"], }, }, async execute(args, executor) { const projectPath = args.project_path as string; const scriptPath = args.script_path as string; const extendsType = (args.extends as string) || "Node"; const className = args.class_name as string | undefined; const content = args.content as string | undefined; const template = (args.template as string) || "default"; if (!executor) { throw new Error("Godot is not available"); } if (!(await isGodotProject(projectPath))) { throw new Error(`Not a valid Godot project: ${projectPath}`); } const result = await executor.execute(projectPath, "create_script", { script_path: scriptPath, extends: extendsType, class_name: className || "", content: content || "", template, }); if (!result.success) { throw new Error(result.error || "Failed to create script"); } return result.output; }, }; // Attach Script Tool export const attachScriptTool: ToolHandler = { definition: { name: "attach_script", description: "Attach an existing GDScript to a node in a scene", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "Absolute path to the Godot project directory", }, scene_path: { type: "string", description: "Path to the scene file", }, node_path: { type: "string", description: "Path to the node to attach the script to (use '.' for root)", default: ".", }, script_path: { type: "string", description: "Path to the GDScript file to attach", }, }, required: ["project_path", "scene_path", "script_path"], }, }, async execute(args, executor) { const projectPath = args.project_path as string; const scenePath = args.scene_path as string; const nodePath = (args.node_path as string) || "."; const scriptPath = args.script_path as string; if (!executor) { throw new Error("Godot is not available"); } const result = await executor.execute(projectPath, "attach_script", { scene_path: scenePath, node_path: nodePath, script_path: scriptPath, }); if (!result.success) { throw new Error(result.error || "Failed to attach script"); } return result.output; }, }; // Read Script Tool (direct file read, doesn't need Godot) export const readScriptTool: ToolHandler = { definition: { name: "read_script", description: "Read the contents of a GDScript file", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "Absolute path to the Godot project directory", }, script_path: { type: "string", description: "Path to the script file (e.g., 'res://scripts/player.gd')", }, }, required: ["project_path", "script_path"], }, }, async execute(args, _executor) { const projectPath = args.project_path as string; const scriptPath = args.script_path as string; // Convert res:// path to filesystem path let fsPath: string; if (scriptPath.startsWith("res://")) { fsPath = path.join(projectPath, scriptPath.substring(6)); } else { fsPath = path.join(projectPath, scriptPath); } try { const content = await fs.readFile(fsPath, "utf-8"); return { script_path: scriptPath, content, line_count: content.split("\n").length, }; } catch (error) { throw new Error(`Failed to read script: ${error instanceof Error ? error.message : String(error)}`); } }, }; // Edit Script Tool (direct file write) export const editScriptTool: ToolHandler = { definition: { name: "edit_script", description: "Edit an existing GDScript file by replacing its content", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "Absolute path to the Godot project directory", }, script_path: { type: "string", description: "Path to the script file", }, content: { type: "string", description: "New content for the script file", }, }, required: ["project_path", "script_path", "content"], }, }, async execute(args, _executor) { const projectPath = args.project_path as string; const scriptPath = args.script_path as string; const content = args.content as string; // Convert res:// path to filesystem path let fsPath: string; if (scriptPath.startsWith("res://")) { fsPath = path.join(projectPath, scriptPath.substring(6)); } else { fsPath = path.join(projectPath, scriptPath); } try { // Ensure directory exists await fs.mkdir(path.dirname(fsPath), { recursive: true }); await fs.writeFile(fsPath, content, "utf-8"); return { success: true, message: `Updated script at ${scriptPath}`, script_path: scriptPath, }; } catch (error) { throw new Error(`Failed to edit script: ${error instanceof Error ? error.message : String(error)}`); } }, }; // List Scripts Tool export const listScriptsTool: ToolHandler = { definition: { name: "list_scripts", description: "List all GDScript files in the Godot project", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "Absolute path to the Godot project directory", }, }, required: ["project_path"], }, }, async execute(args, executor) { const projectPath = args.project_path as string; if (!executor) { throw new Error("Godot is not available"); } const result = await executor.execute(projectPath, "list_scripts", {}); if (!result.success) { throw new Error(result.error || "Failed to list scripts"); } return result.output; }, }; export const scriptTools = [ createScriptTool, attachScriptTool, readScriptTool, editScriptTool, listScriptsTool, ];

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

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