How-To: Add MCP Tools to a Plugin

Goal: expose your plugin's editor operations to AI agents over Model Context Protocol (MCP), the way CrimsonEditorUtilities does. CrimsonCommonEditor gives you the master switch every Crimson plugin honors; you author the tools themselves on a UToolsetDefinition in your own editor module. This is an editor-only, C++ task.

Prerequisites
An editor module in your plugin. It depends on CrimsonCommonEditor, and its .uplugin declares CrimsonCommon, ModelContextProtocol, and ToolsetRegistry in the Plugins array. CrimsonEditorUtilities is a complete working example.
Always gate on the master switch
Every registration path below must be guarded by UCrimsonMCPSettings::IsEnabled() (from MCP/CrimsonMCPSettings.h). That single Project Settings toggle - Crimson -> Crimson MCP - is what lets users turn the whole suite's MCP surface off. Skipping the gate breaks that guarantee.

1. Recommended: a UToolsetDefinition

UE 5.8's Toolset Registry is the modern, discoverable path: tools authored here show up in an agent's list_toolsets. Declare a UToolsetDefinition subclass with static UFUNCTION(meta = (AICallable)) functions - the class name becomes the toolset name and each function is one tool. Report failures with UKismetSystemLibrary::RaiseScriptError. Add ToolsetRegistry and Kismet to the editor module's .Build.cs.

cpp
// MyPluginToolset.h
#include "ToolsetRegistry/ToolsetDefinition.h"
#include "MyPluginToolset.generated.h"
/** Tools for my plugin. */
UCLASS(BlueprintType, Hidden)
class UMyPluginToolset : public UToolsetDefinition
{
GENERATED_BODY()
public:
/**
* One-line description the agent sees.
* @param Name What this parameter means.
*/
UFUNCTION(meta = (AICallable), Category = "MyPlugin")
static FString DoThing(const FString& Name);
};

Register the toolset in the editor module's StartupModule (gated), and unregister on shutdown:

cpp
#include "ToolsetRegistry/UToolsetRegistry.h"
#include "MCP/CrimsonMCPSettings.h"
void FMyPluginEditorModule::StartupModule()
{
if (UCrimsonMCPSettings::IsEnabled())
{
UToolsetRegistry::RegisterToolsetClass(UMyPluginToolset::StaticClass());
}
}
void FMyPluginEditorModule::ShutdownModule()
{
if (UToolsetRegistry::IsAvailable())
{
UToolsetRegistry::UnregisterToolsetClass(UMyPluginToolset::StaticClass());
}
}
Verify
Enable Crimson MCP, restart, start the server, and confirm your toolset appears in the agent's list_toolsets. Run ModelContextProtocol.RefreshTools after live-coding a tool method.

2. Advanced results (images, audio, async)

For results richer than a string or struct - screenshots, audio, or operations that span multiple frames - return the engine's native ToolsetRegistry async result types (UToolCallAsyncResultImage, the ToolCallAsyncResult* family, ToolsetImage.h) from your AICallable function. The old Crimson low-level tool base (TCrimsonMCPTool / FCrimsonMCPToolRegistrar) was retired on 2026-07-17; every tool now goes through UToolsetDefinition.

See also

  • CrimsonEditorUtilities -> Quick Start - enable Crimson MCP and connect an agent
  • CrimsonEditorUtilities -> Concept: How Crimson MCP Works - toolsets, tool search, and the master-switch cascade