Ferramentas personalizadas
Adicione suas ferramentas de IA, módulos RQL, prompts e recursos ao Unreal MCP de qualquer plugin C++ e exponha ferramentas de gameplay no jogo.
O Unreal MCP permite que qualquer plugin do Unreal, incluindo os plugins do seu próprio projeto de jogo, adicione capacidades para agentes de IA. Você não faz fork do Unreal MCP: você implementa uma pequena interface pública, registra-a como uma modular feature do Unreal e o plugin a detecta quando seu módulo é carregado.
Esta página é para desenvolvedores C++. Se você só quer mais cobertura do engine, confira primeiro as extensões prontas.
Escolha o tipo certo de contribuição
| Você quer que o agente… | Contribua com | Interface |
|---|---|---|
| Ler ou alterar dados do editor de um recurso do engine ou dos seus próprios tipos | Um módulo RQL (recomendado para trabalho no editor) | IUnrealMcpRqlModule |
| Executar uma ação que não seja acesso a dados, ou agir dentro de um jogo em execução | Ferramentas | IUnrealMcpToolProvider |
| Buscar um template de prompt reutilizável | Prompts | IUnrealMcpPromptProvider |
| Ler conteúdo fixo por URI | Recursos | IUnrealMcpResourceProvider |
Todas as extensões oficiais são módulos RQL, então o agente as acessa pelas mesmas ferramentas rql-query e rql-mutate usadas no resto do editor.
Opção 1: um módulo RQL
Dependa do módulo UnrealMcpRql no Build.cs do seu módulo de editor e declare o plugin UnrealMCP no array Plugins do seu .uplugin. Depois implemente o módulo:
#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)O que o contexto pode adicionar:
- Fontes (onde uma consulta começa):
AddObjectSource,AddObjectListSource,AddAssetSource,AddClassDefaultsSource. - Operações (chamadas com
call):AddApiClassouAddApiSourcetornam cadaUFUNCTIONde uma classe chamável. Declare-as comoUFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true")); o comentário de documentação acima de cada uma se torna a descrição que o agente lê. - Membros:
ExposePropertiespara propriedades que a reflexão oculta, e membros computados somente leitura comAddJsonMember,AddObjectMember,AddObjectListMember. - Guias:
AddGuideadiciona uma seção à skillunreal-rql.
Uma mutação é executada em uma única transação do editor, então crie objetos com RF_Transactional e chame Modify() no que você alterar. A seção Extensions do editor lista seu módulo e permite desativá-lo. A referência compilável é o plugin samples/UnrealAITemplate no repositório Unreal-MCP.
Opção 2: ferramentas personalizadas
Passo 1: adicione a dependência
No Build.cs do seu módulo:
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
});No seu .uplugin, adicione a dependência do plugin para que a ordem de carregamento seja resolvida:
{
"Plugins": [ { "Name": "UnrealMCP", "Enabled": true } ]
}Passo 2: implemente o provider
#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));
});
}
};O builder oferece .Title, .Description, os helpers de parâmetro .ParamString, .ParamInt, .ParamNumber, .ParamBool e .ParamVector (passe EUnrealMcpParamRequirement::Required para um obrigatório), as quatro dicas de MCP e .Handle. O handler é executado na game thread, então você pode chamar APIs do editor e de UObject diretamente.
Regras que importam:
- Os ids das ferramentas usam kebab-case: letras minúsculas e dígitos separados por hífens simples.
- Dê a cada ferramenta um título e as quatro dicas. Marque como destrutiva qualquer ferramenta que exclua ou sobrescreva dados.
- Não chame
.ExtensionId(...)por conta própria; seuGetExtensionId()é aplicado automaticamente.
Passo 3: registre-o como modular feature
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();
}
}Mantenha o provider vivo enquanto ele estiver registrado e sempre cancele o registro no shutdown.
Como o registro se comporta
- Descoberta e hot reload. Os providers são encontrados na inicialização do editor. Carregar ou descarregar seu módulo depois reconstrói o registro e os clientes de IA veem a mudança automaticamente.
- Ordem determinística. Os providers são mesclados em ordem crescente de extension-id; as ferramentas dentro de um provider mantêm a ordem de declaração.
- Isolamento. Uma ferramenta inválida (id ruim, schema quebrado, sem handler) ou um nome de ferramenta duplicado é descartada e registrada na entrada da sua extensão. Suas outras ferramentas e as outras extensões não são afetadas. Um crash dentro de um handler ainda é um crash do editor, então valide as entradas e retorne
FUnrealMcpToolResult::Error(...). - Visibilidade e toggles. Suas ferramentas recebem a mesma caixa Visible na janela MCP Tools que as nativas. Uma extensão desativada não contribui com nada.
Prompts e recursos
Prompts e resources seguem o mesmo padrão com IUnrealMcpPromptProvider mais FUnrealMcpPromptRegistry, e IUnrealMcpResourceProvider mais FUnrealMcpResourceRegistry. Um prompt declara parâmetros com os mesmos helpers Param* e retorna mensagens com marcação de papel. Um resource é identificado pela sua URI e retorna texto ou um blob base64 com um tipo MIME. Hoje só há suporte a URIs fixas, não a URIs com template. O prompt embutido level-design-brief e o resource unreal://project/levels são referências funcionais.
Gerar uma ferramenta com o agente
Com uma instalação do plugin a partir do código-fonte, a ferramenta de sistema unreal-skill-create grava um novo arquivo de ferramenta em C++ no módulo de editor do plugin. A ferramenta só passa a existir depois que você recompila o editor (Live Coding ou uma recompilação do projeto).
Ferramentas no jogo (runtime)
O Unreal MCP também pode se conectar a um jogo em execução (Play In Editor, Standalone ou uma build Development empacotada) para que um agente de IA possa controlá-lo. Uma conexão de runtime não oferece ferramentas da engine: apenas as ferramentas que o seu jogo registra.
- Faça seu módulo de jogo depender de
UnrealMcpRuntime(e não deUnrealMcpEditor) e escreva as ferramentas exatamente como acima. - Ative Project Settings, Plugins, Unreal MCP (Runtime). A opção vem desligada por padrão e fica armazenada em
DefaultGame.ini. - Conecte explicitamente. O jogo nunca se conecta sozinho.
Em C++:
#include "UnrealMcpRuntimeSubsystem.h"
if (UUnrealMcpRuntimeSubsystem* Mcp = UUnrealMcpRuntimeSubsystem::Get(this))
{
Mcp->RegisterToolProvider(MyToolProvider);
Mcp->Connect(TEXT("http://localhost:8080"), TEXT("my-token"));
}No Blueprint, use Get Unreal MCP Runtime Subsystem, depois Connect, Disconnect e Is Connected. No console:
UnrealMcp.Connect <host> [token]
UnrealMcp.DisconnectRegras de segurança embutidas em Connect():
- Builds Shipping se recusam a conectar, a menos que você compile com a flag
bUnrealMcpAllowShipping. - Somente hosts de loopback são permitidos, a menos que você passe
bAllowRemoteHost = true. - O modo runtime funciona apenas em plataformas desktop (Windows, macOS, Linux).
O plugin samples/UnrealAIRuntimeSample no repositório adiciona uma ferramenta game-time-dilation que lê e define a dilatação temporal do mundo em um jogo em execução. Se você não precisa de ferramentas de runtime, exclua o plugin das builds empacotadas conforme descrito em Installation.