find_node
Locate nodes in Godot scenes by name, type, group, or script to manage scene trees and debug projects.
Instructions
Find nodes across all indexed scenes by name, type, group, or attached script.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Node name to search for | |
| type | No | Godot class name to filter by | |
| group | No | Group name to filter by | |
| script | No | Script path to filter by | |
| maxResults | No | Maximum results to return |
Implementation Reference
- src/tools/scene-tools.ts:168-208 (handler)The 'find_node' tool registration and handler implementation in 'src/tools/scene-tools.ts', which accepts search parameters and calls the index's 'findNode' method.
{ name: "find_node", description: "Find nodes across all indexed scenes by name, type, group, or attached script.", schema: { name: z.string().optional().describe("Node name to search for"), type: z.string().optional().describe("Godot class name to filter by"), group: z.string().optional().describe("Group name to filter by"), script: z.string().optional().describe("Script path to filter by"), maxResults: z .number() .int() .min(1) .max(500) .optional() .default(50) .describe("Maximum results to return"), }, handler: async (ctx) => { const { name, type, group, script, maxResults = 50 } = ctx.args; const results = await index.findNode({ name, type, group, script }); const truncated = results.length > maxResults; const data = results.slice(0, maxResults).map((r) => ({ name: r.node.name, type: r.node.type, nodePath: r.node.nodePath, scenePath: r.scenePath, script: r.node.script, groups: r.node.groups, })); return makeTextResponse({ data, truncated, totalCount: results.length, metadata: { source: "index" }, }); }, }, { - src/index/unified-index.ts:269-315 (helper)The 'findNode' method implementation in 'src/index/unified-index.ts', which executes the search logic across indices.
async findNode(options: { name?: string; type?: string; group?: string; script?: string; }): Promise<Array<{ node: NodeInfo; scenePath: string }>> { await this.ensureDerivedFresh(); // Pick the narrowest index as the candidate set let candidates: Array<{ node: NodeInfo; scenePath: string }> | null = null; if (options.name) { candidates = this.byName.get(options.name) ?? []; } if (options.type) { const byType = this.nodeTypeIndex.findByType(options.type); if (!candidates || byType.length < candidates.length) { candidates = byType; } } if (options.group) { const byGroup = this.groupIndex.findByGroup(options.group); if (!candidates || byGroup.length < candidates.length) { candidates = byGroup; } } if (options.script) { const byScript = this.byScript.get(options.script) ?? []; if (!candidates || byScript.length < candidates.length) { candidates = byScript; } } // No filters specified — return all nodes if (!candidates) { const all: Array<{ node: NodeInfo; scenePath: string }> = []; for (const [scenePath, scene] of await this.sceneIndex.all()) { for (const [_nodePath, node] of scene.nodes) { all.push({ node, scenePath }); } } return all; } // Apply remaining filters to the candidate set return candidates.filter((entry) => { if (options.name && entry.node.name !== options.name) return false;