chore: 重命名 Tools/godot-mcp-pro-v1.15.1 → Tools/godot-mcp-pro,更新 .mcp.json
- 去掉版本号后缀,路径更稳定(后续更新工具不必再改 .mcp.json) - .mcp.json 指向新路径 server/build/index.js - server 依赖已 npm install 就绪;node_modules 由 .gitignore 忽略,未入库 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { z } from "zod";
|
||||
import { GodotConnection } from "../godot-connection.js";
|
||||
import { formatErrorForMcp } from "../utils/errors.js";
|
||||
|
||||
export function registerShaderTools(
|
||||
server: McpServer,
|
||||
godot: GodotConnection
|
||||
): void {
|
||||
server.tool(
|
||||
"create_shader",
|
||||
"Create a new shader file with a template or custom content. Refuses to overwrite a shader that is currently loaded/open in the editor unless force=true.",
|
||||
{
|
||||
path: z.string().describe("Path for the shader file (e.g. 'res://shaders/dissolve.gdshader')"),
|
||||
shader_type: z.string().optional().describe("Shader type: spatial, canvas_item, particles, sky (default: spatial)"),
|
||||
content: z.string().optional().describe("Full shader code. If empty, generates a template."),
|
||||
force: z.boolean().optional().describe("Override the open/cached-shader guard and write anyway."),
|
||||
},
|
||||
async (params) => {
|
||||
try {
|
||||
const result = await godot.sendCommand("create_shader", params);
|
||||
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
||||
} catch (e) {
|
||||
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
server.tool(
|
||||
"read_shader",
|
||||
"Read the content of a shader file",
|
||||
{
|
||||
path: z.string().describe("Path to the shader file"),
|
||||
},
|
||||
async (params) => {
|
||||
try {
|
||||
const result = await godot.sendCommand("read_shader", params);
|
||||
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
||||
} catch (e) {
|
||||
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
server.tool(
|
||||
"edit_shader",
|
||||
"Edit a shader file using full replacement or search-and-replace. Refreshes any cached/loaded copy of the shader via take_over_path + emit_changed so live materials pick up changes. Refuses to write if the shader is currently loaded/open in the editor unless force=true.",
|
||||
{
|
||||
path: z.string().describe("Path to the shader file"),
|
||||
content: z.string().optional().describe("Full replacement content"),
|
||||
replacements: z.array(z.object({
|
||||
search: z.string().describe("Text to find"),
|
||||
replace: z.string().describe("Text to replace with"),
|
||||
})).optional().describe("Array of search-and-replace operations"),
|
||||
force: z.boolean().optional().describe("Override the open/cached-shader guard and write anyway."),
|
||||
},
|
||||
async (params) => {
|
||||
try {
|
||||
const result = await godot.sendCommand("edit_shader", params);
|
||||
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
||||
} catch (e) {
|
||||
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
server.tool(
|
||||
"assign_shader_material",
|
||||
"Create a ShaderMaterial from a shader file and assign it to a node",
|
||||
{
|
||||
node_path: z.string().describe("Path to the target node (CanvasItem or MeshInstance3D)"),
|
||||
shader_path: z.string().describe("Path to the shader file"),
|
||||
},
|
||||
async (params) => {
|
||||
try {
|
||||
const result = await godot.sendCommand("assign_shader_material", 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_shader_param",
|
||||
"Set a shader parameter on a node's ShaderMaterial",
|
||||
{
|
||||
node_path: z.string().describe("Path to the node with a ShaderMaterial"),
|
||||
param: z.string().describe("Shader parameter name"),
|
||||
value: z.union([z.string(), z.number(), z.boolean()]).describe("Parameter value. Strings auto-parsed for Vector2, Color, etc."),
|
||||
},
|
||||
async (params) => {
|
||||
try {
|
||||
const result = await godot.sendCommand("set_shader_param", 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_shader_params",
|
||||
"Get all shader parameters and their current values from a node's ShaderMaterial",
|
||||
{
|
||||
node_path: z.string().describe("Path to the node with a ShaderMaterial"),
|
||||
},
|
||||
async (params) => {
|
||||
try {
|
||||
const result = await godot.sendCommand("get_shader_params", params);
|
||||
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
||||
} catch (e) {
|
||||
return { content: [{ type: "text", text: formatErrorForMcp(e) }], isError: true };
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user