# Eigene Tools — Unreal Engine · AI Game Developer Wiki

Füge eigene KI-Tools, RQL-Module, Prompts und Ressourcen aus jedem C++-Plugin zu Unreal MCP hinzu und biete Gameplay-Tools im laufenden Spiel an.

Diese Seite wurde maschinell aus dem Englischen übersetzt. [Englisches Original lesen](https://ai-game.dev/docs/wiki/unreal/custom-tools).

Unreal MCP ermöglicht jedem Unreal-Plugin – auch den Plugins deines eigenen Spielprojekts –, Fähigkeiten für KI-Agenten hinzuzufügen. Du forkst Unreal MCP nicht: Du implementierst eine kleine öffentliche Schnittstelle, registrierst sie als Unreal **modular feature**, und das Plugin greift sie auf, sobald dein Modul geladen wird.

Diese Seite richtet sich an C++-Entwickler. Wenn du nur mehr Engine-Abdeckung möchtest, schau dir zuerst die fertigen [Erweiterungen](https://ai-game.dev/de/docs/wiki/unreal/extensions) an.

## Die richtige Art von Beitrag wählen

| Du möchtest, dass der Agent … | Beitrag | Schnittstelle |
| --- | --- | --- |
| Editor-Daten für eine Engine-Funktion oder deine eigenen Typen lesen oder ändern | Ein **RQL-Modul** (empfohlen für Editor-Arbeit) | `IUnrealMcpRqlModule` |
| Eine Aktion ausführen, die kein Datenzugriff ist, oder im laufenden Spiel agieren | **Tools** | `IUnrealMcpToolProvider` |
| Eine wiederverwendbare Prompt-Vorlage abrufen | **Prompts** | `IUnrealMcpPromptProvider` |
| Feste Inhalte per URI lesen | **Ressourcen** | `IUnrealMcpResourceProvider` |

Alle Erstanbieter-Erweiterungen sind RQL-Module, sodass der Agent sie über dieselben Tools `rql-query` und `rql-mutate` erreicht wie den Rest des Editors.

## Option 1: ein RQL-Modul

Hänge in der `Build.cs` deines Editor-Moduls vom Modul `UnrealMcpRql` ab und deklariere das Plugin `UnrealMCP` im `Plugins`-Array deiner `.uplugin`. Implementiere dann das Modul:

```cpp
#include "IUnrealMcpRqlModule.h"

class FMyRqlModule : public IUnrealMcpRqlModule
{
public:
    virtual FString GetRqlModuleName() const override { return TEXT("Niagara"); }
    virtual FString GetExtensionId() const override { return TEXT("com.example.niagara-ai"); }
    virtual FString GetExtensionVersion() const override { return UnrealMcpRql::PluginVersion(TEXT("MyNiagaraAI")); }
    virtual void ConfigureRql(FUnrealMcpRqlModuleContext& Context) override
    {
        Context.AddAssetSource(TEXT("niagaraSystems"), TEXT("Niagara system assets"), UNiagaraSystem::StaticClass());
        Context.AddApiSource(TEXT("niagara"), TEXT("Niagara operations"), UMyNiagaraOperations::StaticClass(),
            TEXT("NiagaraOperations"));
        Context.AddGuide(TEXT("Niagara"), TEXT("... markdown with example queries ..."));
    }
};

IMPLEMENT_MODULE(TUnrealMcpRqlEditorModule<FMyRqlModule>, MyNiagaraAI)
```

Was der Kontext hinzufügen kann:

- **Quellen** (wo eine Abfrage beginnt): `AddObjectSource`, `AddObjectListSource`, `AddAssetSource`, `AddClassDefaultsSource`.
- **Operationen** (aufgerufen mit `call`): `AddApiClass` oder `AddApiSource` machen jede `UFUNCTION` einer Klasse aufrufbar. Deklariere sie als `UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))`; der Doc-Kommentar darüber wird zur Beschreibung, die der Agent liest.
- **Member**: `ExposeProperties` für Properties, die Reflection verbirgt, und schreibgeschützte berechnete Member mit `AddJsonMember`, `AddObjectMember`, `AddObjectListMember`.
- **Leitfäden**: `AddGuide` fügt dem Skill `unreal-rql` einen Abschnitt hinzu.

Eine Mutation läuft in einer einzigen Editor-Transaktion, erstelle Objekte daher mit `RF_Transactional` und rufe `Modify()` auf allem auf, was du änderst. Der Abschnitt Extensions des Editors listet dein Modul auf und kann es deaktivieren. Die baubare Referenz ist das Plugin `samples/UnrealAITemplate` im [Unreal-MCP-Repository](https://github.com/IvanMurzak/Unreal-MCP).

## Option 2: eigene Tools

### Schritt 1: Abhängigkeit hinzufügen

In der `Build.cs` deines Moduls:

```csharp
PublicDependencyModuleNames.AddRange(new string[] { "Core" });

PrivateDependencyModuleNames.AddRange(new string[]
{
    "CoreUObject", "Engine", "Projects",
    "Json",            // the registry header includes Dom/JsonObject.h
    "UnrealMcpEditor", // the extension contract and tool registry
});
```

Füge in deiner `.uplugin` die Plugin-Abhängigkeit hinzu, damit die Ladereihenfolge aufgelöst wird:

```json
{
  "Plugins": [ { "Name": "UnrealMCP", "Enabled": true } ]
}
```

### Schritt 2: Provider implementieren

```cpp
#include "IUnrealMcpToolProvider.h"
#include "UnrealMcpToolRegistry.h"

class FMyExtensionProvider : public IUnrealMcpToolProvider
{
public:
    virtual FString GetExtensionId() const override      { return TEXT("com.foo.my-extension"); }
    virtual FText   GetDisplayName() const override      { return NSLOCTEXT("Foo", "Name", "My Extension"); }
    virtual FString GetExtensionVersion() const override { return TEXT("1.0.0"); }

    virtual void RegisterTools(FUnrealMcpToolRegistry& Registry) override
    {
        Registry.Tool(TEXT("hello-extension"))
            .Title(TEXT("Hello Extension"))
            .Description(TEXT("Returns a friendly greeting."))
            .ParamString(TEXT("name"), TEXT("Who to greet. Defaults to 'world'."))
            .ReadOnlyHint(true).DestructiveHint(false).IdempotentHint(true).OpenWorldHint(false)
            .Handle([](const FUnrealMcpToolCall& Call) -> FUnrealMcpToolResult
            {
                const FString Name = Call.Has(TEXT("name")) ? Call.GetString(TEXT("name")) : TEXT("world");
                return FUnrealMcpToolResult::Success(FString::Printf(TEXT("Hello, %s!"), *Name));
            });
    }
};
```

Der Builder bietet `.Title`, `.Description`, die Parameter-Helfer `.ParamString`, `.ParamInt`, `.ParamNumber`, `.ParamBool` und `.ParamVector` (übergib `EUnrealMcpParamRequirement::Required` für einen erforderlichen), die vier MCP-Hints und `.Handle`. Der Handler läuft im Game-Thread, du kannst also Editor- und `UObject`-APIs direkt aufrufen.

Wichtige Regeln:

- Tool-IDs sind Kebab-Case: Kleinbuchstaben und Ziffern, getrennt durch einzelne Bindestriche.
- Gib jedem Tool einen Titel und alle vier Hints. Markiere alles, was löscht oder überschreibt, als destruktiv.
- Rufe `.ExtensionId(...)` nicht selbst auf; deine `GetExtensionId()` wird automatisch eingetragen.

### Schritt 3: als modular feature registrieren

```cpp
virtual void StartupModule() override
{
    Provider = MakeUnique<FMyExtensionProvider>();
    IModularFeatures::Get().RegisterModularFeature(
        IUnrealMcpToolProvider::GetModularFeatureName(), Provider.Get());
}

virtual void ShutdownModule() override
{
    if (Provider.IsValid())
    {
        IModularFeatures::Get().UnregisterModularFeature(
            IUnrealMcpToolProvider::GetModularFeatureName(), Provider.Get());
        Provider.Reset();
    }
}
```

Halte den Provider am Leben, solange er registriert ist, und melde ihn beim Herunterfahren immer ab.

## Wie sich die Registrierung verhält

- **Erkennung und Hot Reload.** Provider werden beim Editor-Start gefunden. Wenn du dein Modul später lädst oder entlädst, wird die Registry neu aufgebaut, und die KI-Clients sehen die Änderung automatisch.
- **Deterministische Reihenfolge.** Provider werden in aufsteigender Extension-ID-Reihenfolge zusammengeführt; Tools innerhalb eines Providers behalten ihre Deklarationsreihenfolge.
- **Isolation.** Ein ungültiges Tool (schlechte ID, fehlerhaftes Schema, kein Handler) oder ein doppelter Tool-Name wird verworfen und im Eintrag deiner Erweiterung vermerkt. Deine anderen Tools und andere Erweiterungen sind nicht betroffen. Ein Absturz in einem Handler ist weiterhin ein Editor-Absturz, also validiere Eingaben und gib `FUnrealMcpToolResult::Error(...)` zurück.
- **Sichtbarkeit und Schalter.** Deine Tools erhalten im Fenster MCP Tools dieselbe **Visible**-Checkbox wie integrierte Tools. Eine deaktivierte Erweiterung trägt nichts bei.

## Prompts und Ressourcen

Prompts und Ressourcen folgen demselben Muster mit `IUnrealMcpPromptProvider` plus `FUnrealMcpPromptRegistry` sowie `IUnrealMcpResourceProvider` plus `FUnrealMcpResourceRegistry`. Ein Prompt deklariert Parameter mit denselben `Param*`-Helfern und gibt rollenmarkierte Nachrichten zurück. Eine Ressource wird über ihre URI identifiziert und gibt entweder Text oder einen base64-Blob mit einem MIME-Typ zurück. Derzeit werden nur feste URIs unterstützt, keine templatisierten. Der integrierte Prompt `level-design-brief` und die Ressource `unreal://project/levels` sind funktionierende Referenzen.

## Ein Tool mit dem Agenten generieren

Mit einer Quellinstallation des Plugins schreibt das System-Tool `unreal-skill-create` eine neue C++-Tool-Datei in das Editor-Modul des Plugins. Das Tool existiert erst, nachdem du den Editor neu baust (Live Coding oder ein Projekt-Rebuild).

## In-Game-(Runtime-)Tools

Unreal MCP kann auch ein laufendes Spiel verbinden (Play In Editor, Standalone oder ein gepackter Development-Build), sodass ein KI-Agent es steuern kann. Eine Runtime-Verbindung bietet keine Engine-Tools: nur die Tools, die dein Spiel registriert.

1. Lass dein Spielmodul von `UnrealMcpRuntime` abhängen (nicht von `UnrealMcpEditor`) und erstelle Tools genau wie oben beschrieben.
2. Aktiviere **Project Settings, Plugins, Unreal MCP (Runtime)**. Der Schalter ist standardmäßig aus und wird in `DefaultGame.ini` gespeichert.
3. Verbinde dich explizit. Das Spiel verbindet sich nie von selbst.

Aus C++:

```cpp
#include "UnrealMcpRuntimeSubsystem.h"

if (UUnrealMcpRuntimeSubsystem* Mcp = UUnrealMcpRuntimeSubsystem::Get(this))
{
    Mcp->RegisterToolProvider(MyToolProvider);
    Mcp->Connect(TEXT("http://localhost:8080"), TEXT("my-token"));
}
```

Verwende in Blueprint **Get Unreal MCP Runtime Subsystem** und dann **Connect**, **Disconnect** und **Is Connected**. Aus der Konsole:

```text
UnrealMcp.Connect <host> [token]
UnrealMcp.Disconnect
```

In `Connect()` eingebaute Sicherheitsregeln:

- Shipping-Builds verweigern die Verbindung, es sei denn, du kompilierst das Flag `bUnrealMcpAllowShipping` ein.
- Nur Loopback-Hosts sind erlaubt, es sei denn, du übergibst `bAllowRemoteHost = true`.
- Der Runtime-Modus funktioniert nur auf Desktop-Plattformen (Windows, macOS, Linux).

Das Plugin `samples/UnrealAIRuntimeSample` im Repository fügt ein Tool `game-time-dilation` hinzu, das die Zeitdilatation der Welt in einem laufenden Spiel liest und setzt. Wenn du keine Runtime-Tools brauchst, schließe das Plugin wie unter [Installation](https://ai-game.dev/de/docs/wiki/unreal/installation#editor-only) beschrieben aus gepackten Builds aus.

---

Source (HTML): https://ai-game.dev/de/docs/wiki/unreal/custom-tools

Machine-translated (de) from the English page: https://ai-game.dev/docs/wiki/unreal/custom-tools
