Skip to main content
Glama
finder.ts4.75 kB
import * as fs from "fs/promises"; import * as path from "path"; import { exec } from "child_process"; import { promisify } from "util"; const execAsync = promisify(exec); /** * Common Godot installation paths by platform */ const GODOT_PATHS: Record<string, string[]> = { darwin: [ "/Applications/Godot.app/Contents/MacOS/Godot", "/Applications/Godot_mono.app/Contents/MacOS/Godot", `${process.env.HOME}/Applications/Godot.app/Contents/MacOS/Godot`, `${process.env.HOME}/Applications/Godot_mono.app/Contents/MacOS/Godot`, ], win32: [ "C:\\Program Files\\Godot\\Godot.exe", "C:\\Program Files (x86)\\Godot\\Godot.exe", `${process.env.LOCALAPPDATA}\\Godot\\Godot.exe`, `${process.env.USERPROFILE}\\scoop\\apps\\godot\\current\\godot.exe`, ], linux: [ "/usr/bin/godot", "/usr/local/bin/godot", "/usr/bin/godot4", "/usr/local/bin/godot4", `${process.env.HOME}/.local/bin/godot`, "/snap/bin/godot", "/var/lib/flatpak/exports/bin/org.godotengine.Godot", ], }; /** * Check if a file exists and is executable */ async function isExecutable(filePath: string): Promise<boolean> { try { await fs.access(filePath, fs.constants.X_OK); return true; } catch { return false; } } /** * Try to find Godot in PATH */ async function findInPath(): Promise<string | null> { try { const command = process.platform === "win32" ? "where godot" : "which godot"; const { stdout } = await execAsync(command); const godotPath = stdout.trim().split("\n")[0]; if (await isExecutable(godotPath)) { return godotPath; } } catch { // Not found in PATH } // Also try godot4 on Unix systems if (process.platform !== "win32") { try { const { stdout } = await execAsync("which godot4"); const godotPath = stdout.trim(); if (await isExecutable(godotPath)) { return godotPath; } } catch { // Not found } } return null; } /** * Find Godot executable path */ export async function findGodotPath(): Promise<string | null> { // Check environment variable first const envPath = process.env.GODOT_PATH; if (envPath && (await isExecutable(envPath))) { return envPath; } // Try to find in PATH const pathResult = await findInPath(); if (pathResult) { return pathResult; } // Check common installation paths const platform = process.platform as keyof typeof GODOT_PATHS; const paths = GODOT_PATHS[platform] || []; for (const godotPath of paths) { if (await isExecutable(godotPath)) { return godotPath; } } return null; } /** * Validate that a path is a valid Godot project */ export async function isGodotProject(projectPath: string): Promise<boolean> { try { const projectFile = path.join(projectPath, "project.godot"); await fs.access(projectFile, fs.constants.R_OK); return true; } catch { return false; } } /** * Find all scene files in a Godot project */ export async function findSceneFiles(projectPath: string): Promise<string[]> { const scenes: string[] = []; async function scanDir(dir: string): Promise<void> { const entries = await fs.readdir(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); // Skip hidden directories and addons if (entry.name.startsWith(".") || entry.name === "addons") { continue; } if (entry.isDirectory()) { await scanDir(fullPath); } else if (entry.name.endsWith(".tscn") || entry.name.endsWith(".scn")) { // Convert to res:// path const relativePath = path.relative(projectPath, fullPath).replace(/\\/g, "/"); scenes.push(`res://${relativePath}`); } } } try { await scanDir(projectPath); } catch { // Ignore errors during scanning } return scenes; } /** * Find all script files in a Godot project */ export async function findScriptFiles(projectPath: string): Promise<string[]> { const scripts: string[] = []; async function scanDir(dir: string): Promise<void> { const entries = await fs.readdir(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.name.startsWith(".") || entry.name === "addons") { continue; } if (entry.isDirectory()) { await scanDir(fullPath); } else if (entry.name.endsWith(".gd")) { const relativePath = path.relative(projectPath, fullPath).replace(/\\/g, "/"); scripts.push(`res://${relativePath}`); } } } try { await scanDir(projectPath); } catch { // Ignore errors } return scripts; }

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