# Discover, then drive Ground on the live 4.7 API with the engine group, then act through typed or generic commands. The commands deliberately do not hard-code the engine's feature list. The design principle is **version-agnostic access, introspection for discovery**. ## Introspection is the feature list `node.set` / `node.get` for properties, `node.call` / `runtime.call` for methods, their `runtime.*` twins for the running game, and `editor.run_script` / `runtime.eval` for anything that needs several statements: all of them reflect whatever the *running* binary exposes. Any 4.7 (or later) feature surfaced as a property or a callable is reachable with no per-feature wrapper. The one remaining gap is *discovery*: an agent may not know a new feature's name. That is what the `engine` group closes, by reading `ClassDB` from the live build. ```bash # what members match a term, across every class? swallowtail engine search --query navigation_layer # the full API of one class, optionally filtered swallowtail engine class-info --class CharacterBody3D --filter velocity # registered singletons and global class_name scripts swallowtail engine singletons swallowtail engine script-classes ``` `engine search` matches by substring. On **Godot 4.8+**, a query that matches nothing is retried fuzzily, so a half-remembered abbreviation still lands: `linvel` reaches `RigidBody2D.linear_velocity`, `glbpos` reaches `Node3D.global_position`. The result's `match_mode` reports which pass answered. On 4.7 there is no fuzzy pass, so widen to a real substring instead. > **Tip** > > Lead with `engine.search` / `engine.class_info` before authoring. This repeatedly catches silent mistakes that training memory would introduce: for example, only `VoxelGI` exposes a script `bake()` in 4.7 (Lightmap and Occluder are toolbar-only), and `surface_get_primitive_type` is ArrayMesh-only. ## Read what it means Structure answers what exists; the docs answer what it does. `engine docs` serves the running build's own documentation prose, the same text as the editor's Help panel, read from the editor's doc cache. `engine doc-search` searches that prose by concept, for when you know the behavior you want but not the term: ```bash # search the prose: "make text wrap" without knowing the property name swallowtail engine doc-search --query "wrap text" # then read the meaning, class-level or one member swallowtail engine docs --class Label --member autowrap_mode swallowtail engine docs --class Node --member queue_free ``` Member lookup walks the inheritance chain (asking `Sprite2D` about `queue_free` finds `Node`'s), reaches annotations with or without the `@` (`export` finds `@export`), and covers pages `ClassDB` has never held: `@GlobalScope`, `@GDScript`, and the Variant types. A name that only matches an enum returns that enum's values, so `engine docs --class @GlobalScope --member Key` lists the key constants. ## Then drive, generically or typed With the name confirmed, act. There is usually a typed command, but the generic path always works: ```bash # generic: works on any property the live node exposes swallowtail node set --node-path Player --property motion_mode --value 1 # arbitrary GDScript, editor-side or in the running game swallowtail editor run-script --code "print(ProjectSettings.get_setting('application/config/name'))" ``` > **Note** > > When a command returns something surprising, re-check the API with `engine search` / `engine class-info` before assuming the write landed. Most "it didn't work" moments are a property or signature that 4.7 spells differently. See [Live-engine gotchas](https://regiellis.github.io/godot-mcp-go/docs/gotchas) for the known ones.