Files
server-deploy/windows-dev-stack/godot-mcp-pro-v1.14.1/server/build/tools/project-tools.js
Joywayer dd3eb24d0f refactor: 拆分 claude-dev-stack 为 windows-dev-stack 和 wsl-dev-stack
将原 claude-dev-stack 目录拆分为独立的 Windows 和 WSL 部署栈,便于分别维护和使用。

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-29 01:11:20 +08:00

125 lines
6.9 KiB
JavaScript

import { z } from "zod";
import { formatErrorForMcp } from "../utils/errors.js";
export function registerProjectTools(server, godot) {
server.tool("get_project_info", "Get Godot project metadata including name, version, viewport settings, renderer, and autoloads", {}, async () => {
try {
const result = await godot.sendCommand("get_project_info");
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("get_filesystem_tree", "Get the project's file/directory tree with optional filtering by extension (e.g. *.gd, *.tscn)", {
path: z.string().optional().describe("Root path to scan (default: res://)"),
filter: z.string().optional().describe("Glob filter pattern (e.g. '*.gd', '*.tscn')"),
max_depth: z.number().optional().describe("Maximum directory depth to scan (default: 10)"),
}, async (params) => {
try {
const result = await godot.sendCommand("get_filesystem_tree", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("search_files", "Search for files by name using fuzzy matching or glob patterns", {
query: z.string().describe("Search query (fuzzy match or glob pattern)"),
path: z.string().optional().describe("Root path to search (default: res://)"),
file_type: z.string().optional().describe("Filter by file extension (e.g. 'gd', 'tscn')"),
max_results: z.number().optional().describe("Maximum results to return (default: 50)"),
}, async (params) => {
try {
const result = await godot.sendCommand("search_files", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("search_in_files", "Search for text content inside project files (grep-like). Searches through GDScript, scenes, resources, shaders, and other text files. Skips addons/ and .godot/ directories.", {
query: z.string().describe("Text to search for (plain text or regex pattern)"),
path: z.string().optional().describe("Root path to search (default: res://)"),
regex: z.boolean().optional().describe("Use regex matching (default: false)"),
file_type: z.string().optional().describe("Filter by file extension (e.g. 'gd', 'tscn'). Default: all text files"),
max_results: z.number().optional().describe("Maximum results to return (default: 50)"),
}, async (params) => {
try {
const result = await godot.sendCommand("search_in_files", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("get_project_settings", "Read project.godot settings by section or specific key", {
section: z.string().optional().describe("Settings section prefix (e.g. 'display/window')"),
key: z.string().optional().describe("Specific setting key (e.g. 'display/window/size/viewport_width')"),
}, async (params) => {
try {
const result = await godot.sendCommand("get_project_settings", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("set_project_setting", "Set a project setting value (e.g. viewport size, main scene). Saves to project.godot via the editor API.", {
key: z.string().describe("Setting key (e.g. 'display/window/size/viewport_width', 'application/run/main_scene')"),
value: z.union([z.string(), z.number(), z.boolean()]).describe("Value to set. Strings are auto-parsed for Vector2, bool, int, float."),
}, async (params) => {
try {
const result = await godot.sendCommand("set_project_setting", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("uid_to_project_path", "Convert a Godot UID (uid://...) to a project resource path (res://...)", {
uid: z.string().describe("The UID string (e.g. 'uid://abc123')"),
}, async (params) => {
try {
const result = await godot.sendCommand("uid_to_project_path", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("project_path_to_uid", "Convert a project resource path (res://...) to its UID (uid://...)", {
path: z.string().describe("The resource path (e.g. 'res://scenes/player.tscn')"),
}, async (params) => {
try {
const result = await godot.sendCommand("project_path_to_uid", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("add_autoload", "Add an autoload (singleton) to the project. The script/scene will be auto-loaded when the project starts.", {
name: z.string().describe("Autoload name (e.g. 'GameManager', 'AudioManager')"),
path: z.string().describe("Path to the script or scene file (e.g. 'res://scripts/autoload/game_manager.gd')"),
}, async (params) => {
try {
const result = await godot.sendCommand("add_autoload", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
server.tool("remove_autoload", "Remove an autoload (singleton) from the project settings", {
name: z.string().describe("Autoload name to remove (e.g. 'GameManager')"),
}, async (params) => {
try {
const result = await godot.sendCommand("remove_autoload", params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
catch (e) {
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
}
});
}
//# sourceMappingURL=project-tools.js.map