CREATE CUSTOM TOOLS
Extend VibeUE with custom tools built as Unreal Engine plugins
📚 Example Repository
For a complete working example with all source code, visit the SampleExtension repository:
🔗 View SampleExtension on GitHubVibeUE can be extended with custom tools in two ways:
Via MCP Servers
Connect external MCP servers with their own tools. See Configure MCP Servers for details.
Via Unreal Plugins
Build custom tools as Unreal Engine plugins using VibeUE's macros. This is the focus of this guide.
Example Repository: See kevinpbuckley/SampleExtension for a complete working example.
⚡ Quick Start
- Create Plugin - Use Unreal Editor's plugin wizard: File → New → New Plugin
- Add VibeUE Dependency - Configure plugin to depend on VibeUE
- Register Tools - Use REGISTER_VIBEUE_TOOL macro to define your tools
- Build & Test - Compile and restart Unreal Editor
- Use in VibeUE - Your tools appear in AI Chat and can be called directly
📁 Plugin Structure
Recommended Directory Layout
MyCustomTools/
├── MyCustomTools.uplugin # Plugin descriptor
├── Source/
│ └── MyCustomTools/
│ ├── MyCustomTools.Build.cs # Build configuration
│ ├── Public/
│ │ ├── MyCustomToolsModule.h
│ │ └── Tools/
│ │ └── MyTools.h # Tool declarations
│ └── Private/
│ ├── MyCustomToolsModule.cpp
│ ├── MyToolRegistration.cpp # Tool registration
│ └── Tools/
│ └── MyTools.cpp # Tool implementations
└── Binaries/ # Compiled output
└── Intermediate/ # Build intermediate files ⚙️ Plugin Configuration
1. Create Plugin Descriptor (MyCustomTools.uplugin)
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"EngineVersion": "5.7",
"FriendlyName": "My Custom Tools",
"Description": "Custom tools for VibeUE",
"Category": "Editor",
"CreatedBy": "Your Name",
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "MyCustomTools",
"Type": "Editor",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "VibeUE",
"Enabled": true
}
]
} 2. Configure Build (Source/MyCustomTools/MyCustomTools.Build.cs)
using UnrealBuildTool;
public class MyCustomTools : ModuleRules
{
public MyCustomTools(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"VibeUE" // Required for tool registration
});
PrivateDependencyModuleNames.AddRange(new string[]
{
"UnrealEd",
"Slate",
"SlateCore"
});
}
} 🛠️ Creating Tools
Header File (Public/Tools/SampleTools.h)
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "SampleTools.generated.h"
/**
* Sample tools class demonstrating VibeUE tool registration
*/
UCLASS()
class USampleTools : public UObject
{
GENERATED_BODY()
public:
/**
* Create a new level with specified parameters
* @param LevelPath The path where to create the level
* @param LevelName The name of the new level
* @param bOpenWorld Whether to create an open world level
* @return Success message or error description
*/
static FString CreateNewLevel(const FString& LevelPath, const FString& LevelName, bool bOpenWorld);
}; Implementation File (Private/Tools/SampleTools.cpp)
// Copyright Epic Games, Inc. All Rights Reserved.
#include "Tools/SampleTools.h"
#include "Engine/World.h"
#include "Engine/Level.h"
#include "EditorLevelLibrary.h"
#include "AssetRegistry/AssetRegistryModule.h"
#include "FileHelpers.h"
FString USampleTools::CreateNewLevel(const FString& LevelPath, const FString& LevelName, bool bOpenWorld)
{
// Validate inputs
if (LevelPath.IsEmpty() || LevelName.IsEmpty())
{
return TEXT("Error: Level path and name cannot be empty");
}
// Construct the full level path
FString FullLevelPath = FString::Printf(TEXT("%s/%s"), *LevelPath, *LevelName);
// Create the new level
UWorld* NewWorld = UEditorLevelLibrary::CreateNewLevel(FullLevelPath, bOpenWorld);
if (!NewWorld)
{
return FString::Printf(TEXT("Error: Failed to create level at %s"), *FullLevelPath);
}
return FString::Printf(TEXT("Successfully created %s level: %s"),
bOpenWorld ? TEXT("open world") : TEXT("normal"),
*FullLevelPath);
} 📝 Register Tools
Registration File (Private/SampleToolRegistration.cpp)
#include "Tools/SampleTools.h"
#include "VibeUE/Public/Core/ToolRegistry.h"
// Register the create_new_level tool with VibeUE
REGISTER_VIBEUE_TOOL(create_new_level,
"Create a new level in the editor",
"Levels",
TOOL_PARAMS(
TOOL_PARAM("LevelPath", "Path where to save the level (e.g., /Game/Maps/)", "string", true),
TOOL_PARAM("LevelName", "Name for the new level", "string", true),
TOOL_PARAM("OpenWorld", "Whether to open the level after creation", "boolean", false)
),
{
FString LevelPath = Params.FindRef(TEXT("LevelPath"));
FString LevelName = Params.FindRef(TEXT("LevelName"));
bool bOpenWorld = Params.FindRef(TEXT("OpenWorld")).Equals(TEXT("true"), ESearchCase::IgnoreCase);
return USampleTools::CreateNewLevel(LevelPath, LevelName, bOpenWorld);
}
); REGISTER_VIBEUE_TOOL Macro Reference
String identifier for the tool (snake_case recommended)
Human-readable description shown in AI chat
Category for tool organization (e.g., "Custom", "Assets", "Actors")
Define parameters with TOOL_PARAM("name", "description", "type", required)
Lambda function receiving TMap<FString, FString> of parameters, returns FString
📦 Parameter Types
| Type | Description | Usage |
|---|---|---|
| string | Text input | Params.FindRef(TEXT("param_name")) |
| number | Numeric input (float/int) | FCString::Atof() or FCString::Atoi() |
| boolean | True/false value | FString::ToBool() |
| array | Array of values | Parse as comma-separated values |
| object | Complex JSON object | Parse with FJsonObject |
🚀 Installation & Usage
Step 1: Copy Plugin to Your Project
YourProject/
├── Plugins/
│ ├── VibeUE/ # Must be installed
│ └── MyCustomTools/ # Your plugin
└── YourProject.uproject Step 2: Enable Plugin
- Open Unreal Editor
- Go to Edit → Plugins
- Search for your plugin name
- Check Enabled checkbox
- Restart the editor
Step 3: Use Your Tools
Open VibeUE AI Chat and use your tools:
# In natural language:
Create a new level called TestLevel in /Game/Maps
# Or using direct tool syntax:
create_new_level(LevelPath="/Game/Maps", LevelName="TestLevel", OpenWorld=false) ✨ Best Practices
Write detailed descriptions for your tools so the AI understands their purpose
Always validate inputs and return clear error messages on failure
Check for null pointers, valid worlds, and editor availability before performing operations
Group related tools in categories and use consistent naming conventions
Document your tools with clear parameter descriptions and usage examples
📚 References
Complete working example of a VibeUE plugin with custom tools
Documentation of all built-in VibeUE tools
Alternative way to extend VibeUE with external MCP servers