adding MCPPort in project settings
This commit is contained in:
1 parent
0e8cb5957a
commit
ed4c724b9f
8 files changed
+177
-10
No files matched your search
@@ -5,6 +5,7 @@ A simple MCP server for interacting with Unreal Engine.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
import json
|
||||
@@ -25,7 +26,7 @@ logger = logging.getLogger("UnrealMCP")
|
||||
|
||||
# Configuration
|
||||
UNREAL_HOST = "127.0.0.1"
|
||||
UNREAL_PORT = 55557
|
||||
UNREAL_PORT = int(os.environ.get("UNREAL_MCP_PORT", "55557"))
|
||||
|
||||
class UnrealConnection:
|
||||
"""Connection to an Unreal Engine instance."""
|
||||
|
||||
@@ -59,9 +59,9 @@
|
||||
#include "Commands/UnrealMCPCommonUtils.h"
|
||||
#include "Commands/UnrealMCPUMGCommands.h"
|
||||
|
||||
// Default settings
|
||||
#include "UnrealMCPSettings.h"
|
||||
|
||||
#define MCP_SERVER_HOST "127.0.0.1"
|
||||
#define MCP_SERVER_PORT 55557
|
||||
|
||||
UUnrealMCPBridge::UUnrealMCPBridge()
|
||||
{
|
||||
@@ -90,7 +90,7 @@ void UUnrealMCPBridge::Initialize(FSubsystemCollectionBase& Collection)
|
||||
ListenerSocket = nullptr;
|
||||
ConnectionSocket = nullptr;
|
||||
ServerThread = nullptr;
|
||||
Port = MCP_SERVER_PORT;
|
||||
Port = UUnrealMCPSettings::Get()->MCPPort;
|
||||
FIPv4Address::Parse(MCP_SERVER_HOST, ServerAddress);
|
||||
|
||||
// Start the server automatically
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "UnrealMCPSettings.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "UnrealEdMisc.h"
|
||||
#include "HAL/PlatformFileManager.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/MessageDialog.h"
|
||||
#include "Misc/Paths.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "UUnrealMCPSettings"
|
||||
|
||||
void UUnrealMCPSettings::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
if (PropertyChangedEvent.GetPropertyName() != GET_MEMBER_NAME_CHECKED(UUnrealMCPSettings, MCPPort))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Write to Config/DefaultGame.ini (the persistent project config, not Saved/).
|
||||
// SaveConfig() alone writes to Saved/Config/ which can be wiped between sessions.
|
||||
UpdateDefaultConfigFile();
|
||||
|
||||
const FString McpJsonPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()) / TEXT(".mcp.json");
|
||||
if (!FPaths::FileExists(McpJsonPath))
|
||||
{
|
||||
// Init not done yet — .mcp.json will be created with the right port when Init Claude Code is run
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateMcpJson();
|
||||
|
||||
const FText RestartMessage = FText::FromString(FString::Printf(
|
||||
TEXT("Le port MCP a été modifié → %d\n\n")
|
||||
TEXT("Le fichier .mcp.json a été mis à jour.\n")
|
||||
TEXT("Un redémarrage de l'éditeur est nécessaire pour que le bridge C++ écoute sur le nouveau port.\n")
|
||||
TEXT("Redémarrer maintenant ?"),
|
||||
MCPPort));
|
||||
const EAppReturnType::Type Answer = FMessageDialog::Open(EAppMsgType::YesNo, RestartMessage);
|
||||
if (Answer == EAppReturnType::Yes)
|
||||
{
|
||||
FUnrealEdMisc::Get().RestartEditor(false);
|
||||
}
|
||||
}
|
||||
|
||||
void UUnrealMCPSettings::UpdateMcpJson() const
|
||||
{
|
||||
const FString FilePath = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()) / TEXT(".mcp.json");
|
||||
const FString Content = FString::Printf(
|
||||
TEXT("{\n")
|
||||
TEXT(" \"mcpServers\": {\n")
|
||||
TEXT(" \"unrealMCP\": {\n")
|
||||
TEXT(" \"type\": \"stdio\",\n")
|
||||
TEXT(" \"command\": \"uv\",\n")
|
||||
TEXT(" \"args\": [\"--directory\", \".claude/mcp-server\", \"run\", \"unreal_mcp_server.py\"],\n")
|
||||
TEXT(" \"env\": {\n")
|
||||
TEXT(" \"UNREAL_MCP_PORT\": \"%d\"\n")
|
||||
TEXT(" }\n")
|
||||
TEXT(" }\n")
|
||||
TEXT(" }\n")
|
||||
TEXT("}\n"),
|
||||
MCPPort);
|
||||
|
||||
if (FFileHelper::SaveStringToFile(Content, *FilePath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM))
|
||||
{
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("[UUnrealMCPSettings] .mcp.json updated with port %d"), MCPPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("[UUnrealMCPSettings] Failed to write .mcp.json at %s"), *FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DeveloperSettings.h"
|
||||
#include "UnrealMCPSettings.generated.h"
|
||||
|
||||
UCLASS(Config=Game, meta=(DisplayName="Unreal MCP"))
|
||||
class UNREALMCP_API UUnrealMCPSettings : public UDeveloperSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual FName GetCategoryName() const override { return TEXT("Plugins"); }
|
||||
virtual FName GetSectionName() const override { return TEXT("UnrealMCP"); }
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, Category="Server",
|
||||
meta=(ClampMin=1024, ClampMax=65535,
|
||||
DisplayName="MCP Server Port",
|
||||
ToolTip="Port TCP sur lequel le bridge Unreal MCP écoute. Doit correspondre à UNREAL_MCP_PORT dans .mcp.json. Nécessite un redémarrage de l'éditeur pour être pris en compte."))
|
||||
int32 MCPPort = 55557;
|
||||
|
||||
static const UUnrealMCPSettings* Get() { return GetDefault<UUnrealMCPSettings>(); }
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
|
||||
private:
|
||||
void UpdateMcpJson() const;
|
||||
#endif
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "ClaudeCodeInitializer.h"
|
||||
#include "UnrealMCPSetupLog.h"
|
||||
#include "UnrealMCPSettings.h"
|
||||
#include "ClaudeCodeResultDialog.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "HAL/FileManager.h"
|
||||
@@ -10,6 +11,7 @@
|
||||
#include "Misc/MessageDialog.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Misc/ScopedSlowTask.h"
|
||||
#include "UnrealEdMisc.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include "Serialization/JsonReader.h"
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
@@ -88,6 +90,19 @@ void FClaudeCodeInitializer::Run()
|
||||
}
|
||||
|
||||
FClaudeCodeResultDialog::Show(Result);
|
||||
|
||||
if (Result.bOverallSuccess)
|
||||
{
|
||||
const EAppReturnType::Type RestartAnswer = FMessageDialog::Open(EAppMsgType::YesNo,
|
||||
LOCTEXT("RestartPrompt",
|
||||
"Initialisation réussie !\n\n"
|
||||
"Redémarrez l'éditeur pour que Claude Code détecte la configuration MCP.\n"
|
||||
"Redémarrer maintenant ?"));
|
||||
if (RestartAnswer == EAppReturnType::Yes)
|
||||
{
|
||||
FUnrealEdMisc::Get().RestartEditor(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FClaudeCodeInitializer::IsCppProject()
|
||||
@@ -143,14 +158,33 @@ bool FClaudeCodeInitializer::IsMcpJsonValid(const FString& ProjectDir)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bFoundScript = false;
|
||||
for (const TSharedPtr<FJsonValue>& Arg : *Args)
|
||||
{
|
||||
if (Arg->AsString() == TEXT("unreal_mcp_server.py"))
|
||||
{
|
||||
return true;
|
||||
bFoundScript = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (!bFoundScript)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate env.UNREAL_MCP_PORT matches the configured port
|
||||
const TSharedPtr<FJsonObject>* Env;
|
||||
if (!(*UnrealMCP)->TryGetObjectField(TEXT("env"), Env))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
FString PortStr;
|
||||
if (!(*Env)->TryGetStringField(TEXT("UNREAL_MCP_PORT"), PortStr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const int32 ConfiguredPort = UUnrealMCPSettings::Get()->MCPPort;
|
||||
return FCString::Atoi(*PortStr) == ConfiguredPort;
|
||||
}
|
||||
|
||||
bool FClaudeCodeInitializer::IsMcpServerFolderValid(const FString& ProjectDir)
|
||||
@@ -340,17 +374,22 @@ FInitStep FClaudeCodeInitializer::WriteMcpJson(const FString& ProjectDir)
|
||||
}
|
||||
|
||||
const FString FilePath = ProjectDir / TEXT(".mcp.json");
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[.mcp.json] Writing %s"), *FilePath);
|
||||
const FString Content =
|
||||
const int32 Port = UUnrealMCPSettings::Get()->MCPPort;
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[.mcp.json] Writing %s (port %d)"), *FilePath, Port);
|
||||
const FString Content = FString::Printf(
|
||||
TEXT("{\n")
|
||||
TEXT(" \"mcpServers\": {\n")
|
||||
TEXT(" \"unrealMCP\": {\n")
|
||||
TEXT(" \"type\": \"stdio\",\n")
|
||||
TEXT(" \"command\": \"uv\",\n")
|
||||
TEXT(" \"args\": [\"--directory\", \".claude/mcp-server\", \"run\", \"unreal_mcp_server.py\"]\n")
|
||||
TEXT(" \"args\": [\"--directory\", \".claude/mcp-server\", \"run\", \"unreal_mcp_server.py\"],\n")
|
||||
TEXT(" \"env\": {\n")
|
||||
TEXT(" \"UNREAL_MCP_PORT\": \"%d\"\n")
|
||||
TEXT(" }\n")
|
||||
TEXT(" }\n")
|
||||
TEXT(" }\n")
|
||||
TEXT("}\n");
|
||||
TEXT("}\n"),
|
||||
Port);
|
||||
|
||||
if (FFileHelper::SaveStringToFile(Content, *FilePath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM))
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "ToolMenus.h"
|
||||
#include "ToolMenu.h"
|
||||
#include "ToolMenuSection.h"
|
||||
#include "ISettingsModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FClaudeCodeMenuExtender"
|
||||
|
||||
@@ -37,6 +38,22 @@ void FClaudeCodeMenuExtender::BuildMenu(UToolMenu* Menu)
|
||||
FSlateIcon(),
|
||||
FUIAction(FExecuteAction::CreateStatic(&FClaudeCodeMenuExtender::OnInitClaudeCodeClicked))
|
||||
);
|
||||
Section.AddMenuEntry(
|
||||
"OpenMCPSettings",
|
||||
LOCTEXT("SettingsLabel", "Configuration du port MCP..."),
|
||||
LOCTEXT("SettingsTooltip", "Ouvrir les paramètres du port MCP dans les Project Settings"),
|
||||
FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Settings"),
|
||||
FUIAction(FExecuteAction::CreateStatic(&FClaudeCodeMenuExtender::OnOpenSettingsClicked))
|
||||
);
|
||||
}
|
||||
|
||||
void FClaudeCodeMenuExtender::OnOpenSettingsClicked()
|
||||
{
|
||||
ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
|
||||
if (SettingsModule)
|
||||
{
|
||||
SettingsModule->ShowViewer(TEXT("Project"), TEXT("Plugins"), TEXT("UnrealMCP"));
|
||||
}
|
||||
}
|
||||
|
||||
void FClaudeCodeMenuExtender::OnInitClaudeCodeClicked()
|
||||
|
||||
@@ -12,4 +12,5 @@ public:
|
||||
private:
|
||||
static void BuildMenu(UToolMenu* Menu);
|
||||
static void OnInitClaudeCodeClicked();
|
||||
static void OnOpenSettingsClicked();
|
||||
};
|
||||
@@ -18,6 +18,8 @@ public class UnrealMCPSetup : ModuleRules
|
||||
"ToolMenus",
|
||||
"Projects",
|
||||
"Json",
|
||||
"Settings", // ISettingsModule — open Project Settings programmatically
|
||||
"UnrealMCP", // UUnrealMCPSettings — read configured port
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user