# io.github.Aureliolo/gdharness (npm · gdharness)

A harness for driving a Godot 4 project from an agent: addons, runtime bridge, MCP server, CLI.

- Trust score: 73/100 (medium)
- Change this week: +18
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-20

## Components

- npm · `gdharness`: 73/100 (this document), [markdown](https://verifymcp.io/servers/aureliolo-gdharness/gdharness.md), [page](https://verifymcp.io/servers/aureliolo-gdharness/gdharness)

## Channel facts

- Registry: `npm`
- Package: `gdharness`
- Version: `0.13.35`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-20.

- **Supply Chain Security**: 63/100
  - No malware found by supply-chain analysis.
  - Known CVEs could not be checked: the version this server declares is not published in its registry.
  - No install/post-install scripts declared.
  - Dependency health could not be checked: the version this server declares is not published in its registry.
- **Provenance & Transparency**: 100/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to Aureliolo/gdharness).
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 0 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 72/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 10275 tokens (~331/item across 31 items; 30 tools + 1 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 22/100
  - Stability check failed: the tool surface changed between 0.5.1 and 0.13.34: 0 tool removals, 1 breaking changes, 0 additions.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 30 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 31 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the io.github.Aureliolo/gdharness MCP server?

io.github.Aureliolo/gdharness runs locally as an npm package, launched with npx -y gdharness. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add aureliolo-gdharness -- npx -y gdharness
```

### Cursor

```json
{
  "mcpServers": {
    "aureliolo-gdharness": {
      "command": "npx",
      "args": [
        "-y",
        "gdharness"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "aureliolo-gdharness": {
      "command": "npx",
      "args": [
        "-y",
        "gdharness"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add aureliolo-gdharness -- npx -y gdharness
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "aureliolo-gdharness": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "gdharness"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add aureliolo-gdharness --command npx --arg -y --arg gdharness
```

### Hermes

```yaml
mcp_servers:
  aureliolo-gdharness:
    command: "npx"
    args: ["-y", "gdharness"]
```

### Netclaw

```json
{
  "McpServers": {
    "aureliolo-gdharness": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "gdharness"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add aureliolo-gdharness -t stdio -c npx -a -y gdharness
```

### Other

```json
{
  "mcpServers": {
    "aureliolo-gdharness": {
      "command": "npx",
      "args": [
        "-y",
        "gdharness"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-20 (score 73, −11)

- [security regression] Stability: fail → unverified
- [security regression] Known CVEs: pass → unverified
- [security regression] Tool safety: pass → unverified
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional regression] Dependency health: pass → unverified
- [functional improvement] Tool coverage: 95% → 100%
- [functional] Package version: 0.13.20 → 0.13.34
- [functional] Package version: 0.13.20 → 0.13.32
- [functional] Package version: 0.13.20 → 0.13.31
- [functional] Package version: 0.13.20 → 0.13.30
- [functional] Package version: 0.13.20 → 0.13.28
- [functional] Package version: 0.13.20 → 0.13.27
- [functional] Package version: 0.13.20 → 0.13.23
- [functional] Package version: 0.13.20 → 0.13.21

### 2026-09-19 (score 84, +16)

- [security regression] Known CVEs: pass → unverified
- [security regression] Stability: fail → unverified
- [security regression] Tool safety: pass → unverified
- [security improvement] Malware scan: unverified → pass
- [functional regression] Dependency health: pass → unverified
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional] Package version: 0.13.2 → 0.13.20
- [functional] Package version: 0.13.2 → 0.13.19
- [functional] Package version: 0.13.2 → 0.13.18
- [functional] Package version: 0.13.2 → 0.13.16
- [functional] Package version: 0.13.2 → 0.13.14
- [functional] Package version: 0.13.2 → 0.13.13
- [functional] Package version: 0.13.2 → 0.13.11
- [functional] Package version: 0.13.2 → 0.13.10
- [functional] Package version: 0.13.2 → 0.13.9
- [functional] Package version: 0.13.2 → 0.13.8
- [functional] Package version: 0.13.2 → 0.13.7
- [functional] Package version: 0.13.2 → 0.13.6
- [functional] Package version: 0.13.2 → 0.13.5
- [functional] Package version: 0.13.2 → 0.13.4

### 2026-09-18 (score 68, −4)

- [security regression] Malware scan: pass → unverified
- [security regression] Stability: fail → unverified
- [security regression] Tool safety: pass → unverified
- [security improvement] Known CVEs: unverified → pass
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional improvement] Dependency health: unverified → pass
- [functional] Package version: 0.12.11 → 0.13.2
- [functional] Package version: 0.12.11 → 0.13.0
- [functional] Package version: 0.12.11 → 0.12.18
- [functional] Package version: 0.12.11 → 0.12.17
- [functional] Package version: 0.12.11 → 0.12.16
- [functional] Package version: 0.12.11 → 0.12.15
- [functional] Package version: 0.12.11 → 0.12.13

### 2026-09-17 (score 72, −10)

- [security regression] Stability: fail → unverified
- [security regression] Tool safety: pass → unverified
- [security regression] Known CVEs: pass → unverified
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional regression] Dependency health: pass → unverified
- [functional] Package version: 0.12.0 → 0.12.11
- [functional] Package version: 0.12.0 → 0.12.9
- [functional] Package version: 0.12.0 → 0.12.7
- [functional] Package version: 0.12.0 → 0.12.6
- [functional] Package version: 0.12.0 → 0.12.5
- [functional] Package version: 0.12.0 → 0.12.4
- [functional] Package version: 0.12.0 → 0.12.3

### 2026-09-16 (score 82, +26)

- [security regression] Stability: fail → unverified
- [security regression] Tool safety: pass → unverified
- [security improvement] Malware scan: unverified → pass
- [security improvement] Known CVEs: unverified → pass
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional improvement] Dependency health: unverified → pass
- [functional] Package version: 0.9.5 → 0.12.0
- [functional] Package version: 0.9.5 → 0.10.2
- [functional] Package version: 0.9.5 → 0.10.1
- [functional] Package version: 0.9.5 → 0.10.0
- [functional] Package version: 0.9.5 → 0.9.7
- [functional] Package version: 0.9.5 → 0.9.6

### 2026-09-15 (score 56, −15)

- [security regression] Malware scan: pass → unverified
- [security regression] Stability: 0.03 → unverified
- [security regression] Tool safety: pass → unverified
- [security regression] Stability: 0.03 → fail
- [security improvement] Known CVEs: unverified → pass
- [functional regression] Schema quality: 218 → 245
- [functional regression] Schema quality: 218 → 242
- [functional regression] Schema quality: 218 → 240
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional improvement] Dependency health: unverified → pass
- [functional] Package version: 0.6.3 → 0.9.5
- [functional] Package version: 0.6.3 → 0.9.4
- [functional] Package version: 0.6.3 → 0.9.3
- [functional] Package version: 0.6.3 → 0.9.2
- [functional] Package version: 0.6.3 → 0.9.1
- [functional] Package version: 0.6.3 → 0.9.0
- [functional] Package version: 0.6.3 → 0.8.0
- [functional] Package version: 0.6.3 → 0.7.0
- [functional] Package version: 0.6.3 → 0.6.9
- [functional] Package version: 0.6.3 → 0.6.8
- [functional] Package version: 0.6.3 → 0.6.7
- [functional] Package version: 0.6.3 → 0.6.6
- [functional] Package version: 0.6.3 → 0.6.4

### 2026-09-14 (score 71, +16)

- [security regression] Tool safety: pass → unverified
- [security improvement] Malware scan: unverified → pass
- [security improvement] Known CVEs: unverified → pass
- [security] Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet.
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional improvement] Dependency health: unverified → pass
- [functional improvement] Stability: unverified → 0.03
- [functional] Package version: 0.5.1 → 0.6.3
- [functional] Package version: 0.5.1 → 0.6.1
- [functional] Package version: 0.5.1 → 0.6.0
- [functional] Package version: 0.5.1 → 0.5.11
- [functional] Package version: 0.5.1 → 0.5.9
- [functional] Package version: 0.5.1 → 0.5.8
- [functional] Package version: 0.5.1 → 0.5.7
- [functional] Package version: 0.5.1 → 0.5.6
- [functional] Package version: 0.5.1 → 0.5.4
- [functional] Package version: 0.5.1 → 0.5.3
- [functional] Package version: 0.5.1 → 0.5.2

### 2026-09-13 (score 55)

First indexed and scored.

## MCP tools (30)

### `project_info` (~143 tokens)

What a project is: its name and main scene from project.godot, the Godot that answers, and how many scenes, scripts and assets it holds, with optional sections on top.

Input parameters:

- `detail` (string): full adds what to do about it to every validation finding. Default summary.
- `include` (array): Extra sections: registered autoloads, addons and whether each is enabled, export presets, the audio bus layout, a health report, or export validation.
- `preset` (string): For validation: the export preset to validate against.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.

### `project_settings` (~686 tokens)

Reads or writes project.godot: settings, autoloads, the main scene, input actions, plugins and audio buses. Operations: get: read one setting, or every setting under prefix; set (needs setting, value): write one setting; add_autoload (needs name, path): register an autoload singleton; remove_autoload (needs name): unregister an autoload; set_main_scene (needs scenePath): choose the scene the game starts in; add_input_action (needs actionName, events): register an input action and its events; enable_plugin (needs pluginName): enable an addon; disable_plugin (needs pluginName): disable an addon; add_audio_bus (needs busName): add an audio bus; set_audio_bus_effect (needs busIndex, effectIndex, effectType): add or configure an effect on a bus; set_audio_bus_volume (needs busIndex, volumeDb): set a bus volume.

Input parameters:

- `actionName` (string): Input action name, such as "jump".
- `busIndex` (number): Audio bus index.
- `busName` (string): Audio bus name.
- `deadzone` (number): Input actions: analogue deadzone, 0 to 1. Default 0.5.
- `effectIndex` (number): Slot on the bus for the effect.
- `effectType` (string): Effect class, such as "AudioEffectReverb".
- `enabled` (boolean): Autoloads: register enabled. Default true.
- `events` (array): The events that trigger the action.
- `from` (string): get: where to read. Default disk, which starts a short-lived engine and reads project.godot, needs no editor and is what an automatic check can reproduce. editor asks the open editor instead, which c…
- `name` (string): Autoload name.
- `op` (string, required): What to do.
- `parentBusIndex` (number): Audio buses: the bus to send to. Default 0, Master.
- `path` (string): Autoload script or scene inside the project.
- `pluginName` (string): Folder name under addons/.
- `prefix` (string): get: answer with every setting whose name starts with this, and the type the engine registers for each, instead of one setting by name. "debug/gdscript/warnings/" answers the whole family. The type m…
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `scenePath` (string): Scene file inside the project, such as "scenes/main.tscn" or "res://scenes/main.tscn".
- `setting` (string): Setting path, such as "display/window/size/viewport_width".
- `value`: The value to write. Engine types may be tagged, {"_type": "Vector2", "x": 1, "y": 2}. "" writes an empty string.
- `volumeDb` (number): Bus volume in decibels.

### `project_search` (~180 tokens)

Searches text or a regular expression across project files and returns file paths with line numbers. What the engine steps over is not searched: directories spelled with a dot, node_modules, and any directory holding a .gdignore. A vendored engine or an export directory is therefore absent from the results rather than matching the code you are looking for in a copy nobody runs.

Input parameters:

- `caseSensitive` (boolean): Default false.
- `fileTypes` (array): Extensions to search, such as ["gd", "tscn"]. Default: every text file.
- `maxResults` (number): Default 100.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `query` (string, required): The text or pattern to find.
- `regex` (boolean): Read the query as a regular expression. Default false.

### `project_dependencies` (~264 tokens)

What a resource depends on, or what depends on it.

Input parameters:

- `depth` (number): forward: how many levels to follow. Default unlimited.
- `direction` (string): forward: what this resource loads, with cycles reported. reverse: every file that refers to it and how, a scene instancing it, a script extending, preloading or loading it, and for a script with a cl…
- `fileTypes` (array): reverse: extensions to look in.
- `includeBuiltin` (boolean): forward: include the engine's own res://. resources. Default false.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `resourcePath` (string, required): File inside the project, such as "sprites/hero.png" or "materials/steel.tres".

### `project_import` (~390 tokens)

The import pipeline: what needs importing, how a resource is imported, reimports, UIDs, and the global class list the editor and the engine read. Operations: status: which resources are outdated or failed, or one resource with resourcePath; options (needs resourcePath): the import options of one resource; set_options (needs resourcePath, options): change import options; reimport: reimport one resource, or everything modified without resourcePath; uid (needs resourcePath): the UID of one file; refresh_uids: import the project so every script and shader has its .uid sidecar, and name under uidsCreated the ones this made and under stillWithoutUid the ones the engine would not import: it writes no scene and no script, so a project whose sidecars are all present is left untouched; refresh_classes: rewrite .godot/global_script_class_cache.cfg from the class_name declarations on disk, and name under unseenByEditor any class the editor open on this project still cannot resolve: rewriting the file does not reach the list a running editor loaded, so "added: []" means the file was already right rather than that nothing is wrong.

Input parameters:

- `force` (boolean): reimport: reimport even what is current. Default false.
- `includeUpToDate` (boolean): status: list resources that are current as well. Default false.
- `op` (string, required): What to do.
- `options` (object): set_options: import options keyed as the .import file spells them, {"compress/mode": 1}.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `reimport` (boolean): set_options: reimport afterwards. Default true.
- `resourcePath` (string): File inside the project, such as "sprites/hero.png" or "materials/steel.tres".

### `project_export` (~156 tokens)

Export presets and exports. Operations: list: the presets in export_presets.cfg; run (needs preset, outputPath): export with a preset.

Input parameters:

- `debug` (boolean): run: a debug export. Default false.
- `op` (string, required): What to do.
- `outputPath` (string): Where the export is written, inside the project. The directory is created if it is not there: Godot's command-line exporter refuses a missing one with "The given export path doesn't exist", which rea…
- `preset` (string): Preset name from export_presets.cfg.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.

### `project_test` (~374 tokens)

Runs the project's gdUnit4 tests headless and answers with every case that did not pass: where it is, and what the assertion said. Suites where everything passed are counted rather than listed, and an engine message keeps the frames above gdUnit4 rather than the twenty inside it, so a clean tier answers in a few lines. The class list is rebuilt first, so a suite written a moment ago is found. On Windows and Linux the run gets a user:// of its own, so a suite that saves a game writes nowhere near the saves of the copy somebody plays. A run that found nothing to run is never called a pass: gdUnit4 exits cleanly for one, so the answer says so and names the path it looked in. A run where nothing failed but nodes were left in the tree comes back under warnings, with the count per suite: gdUnit4 decides its verdict on those and keeps them out of its report, so they are read off what it printed. Needs gdUnit4 under addons/gdUnit4.

Input parameters:

- `failFast` (boolean): Stop each suite at its first failing case. Default false: every case runs. With it on, the counts are of what ran, notRun says how many cases were left, and fixing what is named and running again fin…
- `ignore` (array): Suites or cases to leave out, as "suite_name" or "suite_name:test_name".
- `path` (string): A test directory or one suite file inside the project. Default test.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `timeoutMs` (number): How long the run may take before it is killed. Default 600000.

### `scene_create` (~172 tokens)

Creates a scene file, saves one, or saves a copy under a new path. Needs the editor connected. Operations: create: a new scene with one root node; save: save the scene as it is in the editor; save_as (needs newPath): save a copy under newPath. Default create.

Input parameters:

- `newPath` (string): save_as: where the copy goes.
- `op` (string): What to do.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `rootNodeType` (string): create: the root node class. Default Node2D.
- `scenePath` (string, required): Scene file inside the project, such as "scenes/main.tscn" or "res://scenes/main.tscn".

### `scene_tree` (~119 tokens)

The nodes of a scene file: names, classes and hierarchy, with properties when asked. Needs the editor connected.

Input parameters:

- `depth` (number): How many levels to descend. Default: all.
- `includeProperties` (boolean): Include each node's properties. Default false.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `scenePath` (string, required): Scene file inside the project, such as "scenes/main.tscn" or "res://scenes/main.tscn".

### `scene_node` (~532 tokens)

One node in a scene file: add, read, set, duplicate, reparent or delete it, or paint TileMap cells. Any ClassDB node type can be added, so a NavigationRegion2D, an AnimationTree or a Camera3D is an add with that nodeType and its properties. A property holding a Resource takes the res:// path of one, so a texture, a material or a theme is a set like any other. Needs the editor connected. Operations: add (needs nodeType, nodeName): add a node of any class; get (needs nodePath): read a node's properties; set (needs nodePath, properties): set properties on a node; duplicate (needs nodePath, newName): copy a node and its children; reparent (needs nodePath, newParentPath): move a node under another parent; delete (needs nodePath): remove a node and its children; set_tilemap_cells (needs nodePath, cells): place tiles in a TileMap.

Input parameters:

- `cells` (array): Cells to place.
- `includeDefaults` (boolean): get: include properties still at their default. Default false.
- `layer` (number): set_tilemap_cells: the TileMap layer. Default 0.
- `newName` (string): duplicate: the copy's name.
- `newParentPath` (string): reparent: the new parent.
- `nodeName` (string): add: the new node's name.
- `nodePath` (string): Node path from the scene root, such as "Player/Sprite2D". "." is the root.
- `nodeType` (string): add: the node class, such as "CharacterBody2D".
- `op` (string, required): What to do.
- `parentNodePath` (string): add: where the node goes. Default the root. duplicate: where the copy goes.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `properties` (object): Properties to set, keyed by Godot property name. Vectors, colours and the like may be written as {"x": 1, "y": 2} or tagged {"_type": "Vector2", "x": 1, "y": 2}, which is the form a read answers with…
- `scenePath` (string, required): Scene file inside the project, such as "scenes/main.tscn" or "res://scenes/main.tscn".

### `scene_signal` (~238 tokens)

Signal connections in a scene file. Needs the editor connected. Operations: connect (needs sourceNodePath, signalName, targetNodePath, methodName): connect a signal to a method; disconnect (needs sourceNodePath, signalName, targetNodePath, methodName): remove a connection; list: every connection in the scene.

Input parameters:

- `flags` (number): connect: Object.ConnectFlags, such as 1 for deferred.
- `methodName` (string): The method on that node, called when it emits.
- `nodePath` (string): list: only connections involving this node.
- `op` (string, required): What to do.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `scenePath` (string, required): Scene file inside the project, such as "scenes/main.tscn" or "res://scenes/main.tscn".
- `signalName` (string): The signal it emits, such as "pressed".
- `sourceNodePath` (string): The node that emits.
- `targetNodePath` (string): The node whose method is called.

### `scene_animation` (~382 tokens)

Animations in an AnimationPlayer and states in an AnimationTree state machine. Needs the editor connected. Operations: create (needs playerNodePath, animationName): a new animation in an AnimationPlayer; add_track (needs playerNodePath, animationName, track): a property or method track with keyframes; add_state (needs animTreePath, stateName, animationName): a state playing an animation, in an AnimationTree; connect_states (needs animTreePath, fromState, toState): a transition between two states.

Input parameters:

- `advanceCondition` (string): connect_states: the condition parameter that advances.
- `animTreePath` (string): The AnimationTree node.
- `animationName` (string): The animation in the player. add_state: the one that state plays.
- `fromState` (string): connect_states: the state the transition leaves.
- `length` (number): create: seconds. Default 1.
- `loopMode` (string): create: default none.
- `op` (string, required): What to do.
- `playerNodePath` (string): The AnimationPlayer node.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `scenePath` (string, required): Scene file inside the project, such as "scenes/main.tscn" or "res://scenes/main.tscn".
- `stateMachinePath` (string): add_state: a nested state machine. Default the root.
- `stateName` (string): add_state: the state to add.
- `step` (number): create: keyframe snap in seconds. Default 0.1.
- `toState` (string): connect_states: the state it arrives at.
- `track` (object): The track to add.
- `transitionType` (string): connect_states: default immediate.

### `script_edit` (~208 tokens)

Creates a GDScript file, or adds functions, variables and signals to one. Every declaration written carries a type. create loads what it wrote under the project's own warning settings and answers with parses; the engine's reasons for a refusal come back under engine_messages. Operations: create: a new script file; modify (needs modifications): add to an existing script.

Input parameters:

- `className` (string): create: a class_name for the script.
- `content` (string): create: the whole file, instead of a template.
- `extends` (string): create: the base class. Default Node.
- `modifications` (array): Additions to make, in order.
- `op` (string, required): What to do.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `scriptPath` (string, required): Script file inside the project, such as "scripts/player.gd".
- `template` (string): create: a starting shape.

### `script_info` (~262 tokens)

What a script contains: its structure from the file, or symbols, completions and hover text from the editor's language server. Operations: structure: functions, variables, signals, class_name and extends, read from the file; symbols: document symbols from the language server; completion (needs line, character): completions at a position; hover (needs line, character): hover text at a position. Default structure.

Input parameters:

- `character` (number): completion, hover: zero-based column.
- `includeInherited` (boolean): structure: also list what the script inherits, walking extends through the project's other scripts. Each such member carries inherited_from, the file declaring it, and the answer gains inherits_from,…
- `line` (number): completion, hover: zero-based line.
- `op` (string): What to do.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `scriptPath` (string, required): Script file inside the project, such as "scripts/player.gd".

### `script_diagnostics` (~188 tokens)

Errors and warnings for a script from the editor's language server, and whether the script is clean. Needs the editor running. Diagnostics are checked against the project's own files, and the two that the files disprove are named rather than passed on: a member the class cache's file declares comes back under contradictedByTheFile, and a class this project declares that the diagnostic could not resolve comes back under typesTheEditorHasNotLoaded, with inTheClassCache saying whether a launched game would resolve it. staleAnalysis then says which remedy applies, because they differ: a stale analysed type needs editor_launch restart, while a class missing from the cache needs project_import refresh_classes.

Input parameters:

- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `scriptPath` (string, required): Script file inside the project, such as "scripts/player.gd".

### `resource_edit` (~494 tokens)

Resource files: create any ClassDB resource as .tres, change one, write a shader, build a TileSet, or set a Theme colour or font size. A material is a create with resourceType StandardMaterial3D, ShaderMaterial or CanvasItemMaterial. Needs the editor connected. Operations: create (needs resourceType): a new resource of any class; modify (needs properties): set properties on an existing resource; create_shader (needs shaderType): a .gdshader file; create_tileset (needs sources): a TileSet from texture atlases; set_theme_color (needs controlType, colorName, color): a colour in a Theme; set_theme_font_size (needs controlType, fontSizeName, size): a font size in a Theme.

Input parameters:

- `code` (string): create_shader: the shader source. Default: a minimal shader of that type.
- `color` (object): set_theme_color: r, g and b from 0 to 1, with a optional and opaque by default.
- `colorName` (string): set_theme_color: such as "font_color".
- `controlType` (string): Theme ops: the Control class, such as "Button".
- `fontSizeName` (string): set_theme_font_size: such as "font_size".
- `op` (string, required): What to do.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `properties` (object): Properties to set, keyed by Godot property name. Vectors, colours and the like may be written as {"x": 1, "y": 2} or tagged {"_type": "Vector2", "x": 1, "y": 2}, which is the form a read answers with…
- `resourcePath` (string, required): File inside the project, such as "sprites/hero.png" or "materials/steel.tres".
- `resourceType` (string): create: the resource class, such as "PhysicsMaterial" or "StandardMaterial3D".
- `script` (string): create: a script to attach, for custom resources.
- `shaderType` (string): create_shader.
- `size` (number): set_theme_font_size: pixels.
- `sources` (array): Atlas sources, one per texture.

### `editor_launch` (~307 tokens)

Opens the Godot editor on a project, in a window on this machine, or restarts the one already connected. An editor goes on serving the addon it read at startup, so restart is what puts a gdharness upgrade into effect; it saves open scenes on the way out and answers with the version that came back. Only an editor with a window can be restarted, because the engine hands back none of the arguments it was started with. editor_status says which editor is connected and whether it is holding an old addon. Opening a project is a save and so is closing one, which is the part that is not obvious from outside: the editor imports the project on open and writes project.godot back, and Godot writes only what differs from its own defaults, so a key named deliberately at its default value is dropped either way. A restart says which under settingsDropped in its own answer because it waits for the editor to return. An open cannot, since it answers as soon as the process exists and the save happens during the import minutes later, so editor_status carries that reading once the editor has connected. Nothing else will say a key went until something depends on one. Operations: open (needs projectPath): open the editor on a project; restart: restart the connected editor and wait for it. Default open.

Input parameters:

- `op` (string): What to do.
- `projectPath` (string): Absolute path to the project directory, the one holding project.godot.

### `editor_run` (~776 tokens)

The run: starting the project, stopping it, or booting it once to see whether it comes up clean. start keeps it running and collecting output until it quits or is stopped, windowed where there is a display and headless where there is not, unless headless says otherwise; only runtime_capture needs the window. A run that quits on its own is kept, so a scene that prints an answer and quits is start, then editor_output until running is false. What runs is a scene: a SceneTree script is not an entry point here, so put the script on the root of a scene of its own and name that in scene. args hands the game its own flags, the ones it reads with OS.get_cmdline_user_args(), and a run carrying any is started by this server rather than by the editor. check boots it headless for a few frames, waits for it to quit, and answers with the verdict: whether it came up, and every error and warning it printed on the way. A start waits for the game to become something the runtime_* tools can talk to and says which it is under runtime: listening with the port it took, or why not, so the first call after a start does not have to be made twice. When it is not listening, mayYetAnnounce says whether that is final: false is a runtime that is not coming, true is a game still on its way up, which editor_status will see and runtimeWaitMs waits longer for. A start this server made also answers with transcript, the file both the run's streams are written to, so a watch on it can be armed off the start rather than off a second call. Operations: start (needs projectPath): run the project until it quits or is stopped; stop: end the run and answer with what it printed last, naming the process ended under endedPid: a game that started processes of its own keeps them; check (needs projectPath): boot headless, quit after a few frames, and report the verdict; wait: wait for the run to end, then answer as editor_output does. Default start.

Input parameters:

- `args` (array): The game's own arguments, what OS.get_cmdline_user_args() answers, such as ["--level=2"]. The separator is added here. A run with any is started by this server rather than by the editor, which fixes…
- `frames` (number): check: frames to run before quitting. Default 3.
- `headless` (boolean): start: force a window or no window.
- `op` (string): What to do.
- `projectPath` (string): Absolute path to the project directory, the one holding project.godot.
- `runtimeWaitMs` (number): start: how long to wait for the game to announce its runtime before answering. Default 5000. What it waits for is the first frame, so everything the game does before drawing one is inside it, includi…
- `scene` (string): A scene to run instead of the main scene.
- `timeoutMs` (number): check: how long to give the boot before it is called hung. Default 60000. wait: how long to wait for the run to end before answering anyway. Default 600000.

### `editor_output` (~394 tokens)

What the project started by editor_run has printed, as entries with a severity: the errors and warnings the engine reported, each with where it happened, and everything else as info. Answers with the counts and the verdict as well as the entries. A run that has quit still answers here, with running false and its exit code, until the next one starts. A run this server started also answers with transcript, the file both its streams are written to: uncapped, written while the run is going, and the thing to read or tail for a long run rather than the engine's own log, which every engine start rotates away. Read the file for output and this answer for state: running is asked of the operating system, endedBy says whether gdharness ended the run, and a transcript that has stopped growing is a run between prints rather than a run that is over.

Input parameters:

- `contains` (string): Only entries mentioning this text, matched against everything the run has printed rather than against the entries this answer would otherwise carry: a line is found however much was printed after it.
- `cpu` (boolean): Also answer with cpuSeconds, the processor time the run has used. Default false, because asking costs a subprocess. Worth it when elapsedMs is climbing and nothing is being printed: processor time st…
- `limit` (number): The most entries to answer with, newest kept. Default 200, and omitted says how many matching entries that left out. A run long enough to pass it needs this raised, not just filtered: filtering narro…
- `severity` (string): The least severe entry to include. Default info, which is everything.
- `sinceLastCall` (boolean): Only entries printed since the previous editor_output. Default false.

### `editor_status` (~218 tokens)

Whether the editor addon is connected, which Godot answers, whether the editor is playing something, and whether a game with the runtime addon is reachable. When connected is false, mayYetConnect says whether that is final: the editor dials this server rather than the other way round and backs off between tries, so for the first half-minute after a server starts, false means "not reached yet" as often as it means "no editor". True is worth waiting out; false is an editor that is not there. listeningSince is when this server took the bridge port, which is what that window is measured from and what a caller wanting its own window should read. An editor this server opened counts for as long as its process lives, however far past that window the import runs, and awaitingLaunchedEditor names its pid so the two reasons for true are told apart. settingsDropped appears here once when the editor this server opened saved project.godot on its way in, which is the same reading editor_launch restart makes in its own answer.

### `editor_rescan` (~576 tokens)

Makes the running editor scan the project filesystem, so files written outside it are picked up. The scan is a change-detecting walk rather than an unconditional reparse, so a file another engine has already imported reads as settled and the walk does not look inside it: its class_name then stays out of the list the editor resolves against, however many times you scan. Any class in that state is named under unseenByEditor, which is what no check on disk can see, since the declaration and the cache are both correct there and only the editor disagrees. The cure is this call on its own, with no change to the declaring script: measured against a real editor on three platforms, with idle waits of the same length ruled out so the scan is credited rather than the time it takes, and reproduced in a second project against its own reproduction in 203ms. editor_launch restart also does it and costs a window, and project_import refresh_classes does not: it rewrites the cache and does not touch what the editor is holding. A scan writes .godot/global_script_class_cache.cfg from the list the editor is holding, so a class the editor cannot resolve goes out of that file with it. That is not a reason to refuse the scan, because on a class the editor has merely not walked yet the scan is the cure; what the answer does instead is name the loss under cacheLost and rebuild the cache from the files, naming what came back under cacheRestored, so no fresh engine, CI run or clone inherits the short file. An editor that lost classes is still holding the short list, so the note says to restart it before scanning again. Needs the editor connected.

Input parameters:

- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `reloadScript` (string): A script to recompile in the editor after the scan, for the half a scan does not reach: a script the editor has loaded keeps the copy it built, that copy is refreshed when one of its dependencies cha…
- `timeoutMs` (number): How long to wait for the scan. Default 30000.

### `editor_classes` (~181 tokens)

The engine's ClassDB: find classes, read one in full, or walk an inheritance tree. Operations: query: classes matching a filter or category; info (needs className): methods, properties, signals and enums of one class; inheritance (needs className): ancestors and descendants of one class. Default query.

Input parameters:

- `category` (string): query: limit to one family.
- `className` (string): info, inheritance: the class.
- `filter` (string): query: a substring of the class name.
- `includeInherited` (boolean): info: include inherited members. Default false.
- `instantiableOnly` (boolean): query: leave out abstract classes. Default false.
- `op` (string): What to do.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.

### `runtime_inspect` (~909 tokens)

Questions about the running game: what is written on the screen, the scene tree, the nodes matching a query, where one node is on screen, what one property reads, or the performance metrics. Needs the game running with the runtime addon. Operations: tree: the live scene tree; text: every line of text under nodePath, the values in its fields included, in the order somebody reads the screen, leaving out what is hidden and everything under it; find: the paths of every node matching className, script, namePattern, group or says, with property read off each, hidden ones included unless includeHidden says otherwise; rect (needs nodePath): one node's rectangle or position, in canvas and in window pixels. A 3D node answers with the point to aim at, which is the middle of what it draws rather than the origin it stands on, the rectangle it covers under covers, the camera that drew it, and behind_camera when it is not in front of one; property (needs nodePath, property): what one property reads on a node, or through the objects it holds, refusing a name nothing along the way has; metrics: frame time, memory, draw calls and the rest. Default tree.

Input parameters:

- `className` (string): find: a native class, matching its subclasses too, or a class_name.
- `depth` (number): tree: levels to descend. Default 3.
- `group` (string): find: a group the node is in.
- `includeHidden` (boolean): text: read hidden nodes as well, for checking that something is not showing. Default false. find: default true, since a find means the node whether or not it is drawn; false answers with what the pla…
- `includeProperties` (boolean): tree: include each node's properties. Default false.
- `limit` (number): find: the most nodes to answer with, default 100. text: the most lines, default 500, with omitted saying how many lines that left behind. A screen whose dialog sits under a long list is a screen read…
- `metrics` (array): metrics: which to read. Default all.
- `namePattern` (string): find: a case-insensitive glob on the node name, such as "Enemy*". Matched against the whole name, so a bare word finds only a node called exactly that; an answer of none says how many names contain i…
- `nodePath` (string): tree, find, text: where to start, default /root. rect: the node to place. property: the node to read.
- `op` (string): What to do.
- `projectPath` (string): Which game, when more than one is running: the project directory it was started from. Not needed with one game.
- `property` (string): property: which one to read. find: read this one off every node matched, so a panel of labels is one call rather than one per label. Colons read through what a node holds, "_game:clock:speed", which…
- `says` (string): find: part of what the node has written on it, case-insensitively, which is how a button is reached by the word on it rather than by a generated path. Its own text, so a row is found by the label in…
- `script` (string): find: the script file the node carries.

### `runtime_invoke` (~333 tokens)

Sets a property or calls a method on a node in the running game. Needs the game running with the runtime addon. Operations: set (needs property, value): set a property, on a node or on an object it holds; call (needs method): call a method, on a node or on an object it holds, and return its result.

Input parameters:

- `args` (array): call: the arguments, fitted to the method's parameter types.
- `method` (string): call: which one to call. Colons call through what a node holds, "_game:run:advance", the same way a property is written through them, and a list or a map is stepped into by index or key, "_game:run:r…
- `nodePath` (string, required): Absolute node path, such as "/root/Main/Player".
- `op` (string, required): What to do.
- `projectPath` (string): Which game, when more than one is running: the project directory it was started from. Not needed with one game.
- `property` (string): set: which one to write. Colons write through what a node holds, "_game:run:day", and a number or a key steps into a list or a map on the way, "_game:run:roster:0:name", a negative number counting fr…
- `value`: set: the value, fitted to the property's type. "" writes an empty string.

### `runtime_capture` (~137 tokens)

A picture of the running game: the whole screen or one viewport, as an image. Needs the game running with a window. Operations: screenshot: the screen; viewport: one viewport's texture. Default screenshot.

Input parameters:

- `height` (number): Scale the image to this height.
- `op` (string): What to do.
- `projectPath` (string): Which game, when more than one is running: the project directory it was started from. Not needed with one game.
- `viewportPath` (string): viewport: the Viewport node. Default the root viewport.
- `width` (number): Scale the image to this width.

### `runtime_input` (~899 tokens)

Input to the running game: a whole click on a Control or a 3D node named by path, an item chosen out of a menu, typing into whatever has the focus, or a raw action, key, mouse button or mouse motion. All of it works headless, where the window is 64 by 64 and the GUI only takes what is inside it. Operations: click (needs nodePath): press and release on a Control, a frame apart, and answer with what was under the pointer and what became of the control: in_tree, removed or freed. A control out of sight inside a ScrollContainer is scrolled to first, and scrolled_into_view says whether the view moved. A 3D node is clicked where it is drawn, and landed then says the interface did not swallow the press; choose (needs nodePath): take an item out of a menu, by what it says or by where it is in the list. A menu's items are drawn rather than built, so there is nothing to click: the item takes the focus and Enter presses it, which is the engine's own path and needs no window. Answers with what was chosen and what the button in front of it shows now; action (needs action): press an action, or hold it; key (needs keycode): press a key, or hold it; text (needs text): type a string into the field being edited, a character at a time, and say what it landed in; mouse_click (needs x, y): one mouse button event at a position; mouse_motion (needs x, y): move the mouse to a position.

Input parameters:

- `action` (string): action: the InputMap action name. An engine dialog is not answered this way: AcceptDialog reads the Escape key itself and never asks the InputMap, so ui_cancel goes in and the question stays up. Dism…
- `alt` (boolean): key: hold Alt with it. Default false.
- `button` (string|number): click, mouse_click: left, right, middle, wheel_up or wheel_down, or a button number. Default left.
- `ctrl` (boolean): key: hold Ctrl with it. Default false.
- `doubleClick` (boolean): click, mouse_click: default false.
- `index` (number): choose: the item to take, by where it is in the list, when text will not do.
- `keycode` (string|number): key: the key name, such as "Space" or "A", or its Godot keycode.
- `nodePath` (string): click: the Control to click, at its centre, or the 3D node to click, where it is drawn. choose: the PopupMenu, or the OptionButton or MenuButton in front of one.
- `op` (string, required): What to do.
- `pressed` (boolean): action, key: leave it out and the press is a whole one, down and up a frame apart. true holds it down, false lets go of one being held. mouse_click is one raw event, so it is down unless you say fals…
- `projectPath` (string): Which game, when more than one is running: the project directory it was started from. Not needed with one game.
- `relativeX` (number): mouse_motion: movement since the last event.
- `relativeY` (number): mouse_motion: movement since the last event.
- `replace` (boolean): text: true writes over what the field already says, which is what filling one in means. Default false types at the caret, so a field reading 2.1 typed "0.3" at reads 2.10.3. The answer says what the…
- `shift` (boolean): key: hold Shift with it. Default false.
- `strength` (number): action: 0 to 1. Default 1.
- `text` (string): text: what to type. A newline is Enter and a tab is Tab, a space is a space, and "" with replace empties the field. choose: the item to take, by what it says.
- `x` (number): mouse_click, mouse_motion: window pixels.
- `y` (number): mouse_click, mouse_motion: window pixels.

### `runtime_wait` (~382 tokens)

Lets the running game get on with it and answers when something has happened: a number of frames, a signal, a property reaching a value, or words appearing on a screen. Needs the game running with the runtime addon. Operations: frames (needs frames): let frames pass; signal (needs nodePath, signal): wait for a signal and answer with what it carried; until (needs nodePath): wait for a property to read as a value, or for words to appear under a node, and answer with what it found.

Input parameters:

- `frames` (number): frames: how many to let pass, 1 to 600. More than that is refused.
- `nodePath` (string): signal, until: the node.
- `op` (string, required): What to do.
- `projectPath` (string): Which game, when more than one is running: the project directory it was started from. Not needed with one game.
- `property` (string): until: the property name.
- `says` (string): until: wait for these words to appear anywhere under nodePath instead of for a property, which is how a panel that rebuilds its labels is waited on at all: the labels are named afresh each redraw and…
- `signal` (string): signal: the signal name.
- `timeoutMs` (number): signal, until: how long to wait before answering anyway, 1 to 120000. Default 5000.
- `value`: until: the value to wait for, fitted to the property's type.

### `debug_breakpoint` (~123 tokens)

Sets or removes a breakpoint through the editor's debug adapter. Needs the editor, not a running game: set them first, then editor_run, and the game stops where you asked. Operations: set: set a breakpoint; remove: remove a breakpoint.

Input parameters:

- `line` (number, required): One-based line.
- `op` (string, required): What to do.
- `projectPath` (string, required): Absolute path to the project directory, the one holding project.godot.
- `scriptPath` (string, required): Script file inside the project, such as "scripts/player.gd".

### `debug_control` (~126 tokens)

Continues or steps the debugged game through the editor's debug adapter, answering with the stack where it ended up. There is no pause and no step_out: Godot's adapter answers a pause by reporting the game stopped and leaving it running, and implements no stepOut at all, so hold the game where you want it with a breakpoint and step over or into from there. Operations: continue: resume after a breakpoint; step_over: run the current line; step_into: run the current line, stopping inside whatever it calls.

Input parameters:

- `op` (string, required): What to do.

### `debug_state` (~110 tokens)

Where the debugged game is stopped: the stack trace, what is in scope at a frame with the values, or the debug adapter's console output so far. Operations: stack: the stack trace; variables: locals, members and globals at a frame, with their values; output: console output captured through the debug adapter. Default stack.

Input parameters:

- `frameId` (number): variables: which frame, from a stack answer. Default the innermost.
- `op` (string): What to do.

## Diagnostics

Captured diagnostic sections: Provenance. The full working is on the page: https://verifymcp.io/servers/aureliolo-gdharness/gdharness#diagnostics

## Score history

- 2026-09-20: 73
- 2026-09-19: 84
- 2026-09-18: 68
- 2026-09-17: 72
- 2026-09-16: 82
- 2026-09-15: 56
- 2026-09-14: 71
- 2026-09-13: 55

## Common questions

### What is the io.github.Aureliolo/gdharness MCP server?

io.github.Aureliolo/gdharness is an MCP server listed in the public MCP registry as io.github.Aureliolo/gdharness. A harness for driving a Godot 4 project from an agent: addons, runtime bridge, MCP server, CLI. This page covers its npm package (gdharness).

### Is the io.github.Aureliolo/gdharness MCP server safe to use?

io.github.Aureliolo/gdharness scores 73 out of 100 on VerifyMCP. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the io.github.Aureliolo/gdharness MCP server expose?

io.github.Aureliolo/gdharness exposes 30 tools: project_info, project_settings, project_search, project_dependencies, project_import, and 25 more. Their descriptions and schemas cost roughly 10,259 tokens of context every time the server is loaded.

### Is the io.github.Aureliolo/gdharness MCP server still maintained?

io.github.Aureliolo/gdharness is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the io.github.Aureliolo/gdharness MCP server under?

io.github.Aureliolo/gdharness declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/gdharness
- Socket report: https://socket.dev/npm/package/gdharness
- Repository: https://github.com/Aureliolo/gdharness
- Changelog RSS feed: https://verifymcp.io/servers/aureliolo-gdharness/gdharness.xml
- Changelog JSON feed: https://verifymcp.io/servers/aureliolo-gdharness/gdharness.json
- HTML version of this page: https://verifymcp.io/servers/aureliolo-gdharness/gdharness
