Begining refactor of BlueprintMCP

This commit is contained in:
2026-03-05 21:23:59 -05:00
parent 8367bd2221
commit 9b32de024a
24 changed files with 1016 additions and 1719 deletions

View File

@@ -254,18 +254,12 @@ bool FBlueprintMCPServer::LoadSnapshotFromDisk(const FString& SnapshotId, FGraph
// HandleSnapshotGraph
// ============================================================
FString FBlueprintMCPServer::HandleSnapshotGraph(const FString& Body)
void FBlueprintMCPServer::HandleSnapshotGraph(const FJsonObject* Json, FJsonObject* Result)
{
TSharedPtr<FJsonObject> Json = ParseBodyJson(Body);
if (!Json.IsValid())
{
return MakeErrorJson(TEXT("Invalid JSON body"));
}
FString BlueprintName = Json->GetStringField(TEXT("blueprint"));
if (BlueprintName.IsEmpty())
{
return MakeErrorJson(TEXT("Missing required field: blueprint"));
return MakeErrorJson(Result, TEXT("Missing required field: blueprint"));
}
FString GraphFilter;
@@ -276,7 +270,7 @@ FString FBlueprintMCPServer::HandleSnapshotGraph(const FString& Body)
UBlueprint* BP = LoadBlueprintByName(BlueprintName, LoadError);
if (!BP)
{
return MakeErrorJson(LoadError);
return MakeErrorJson(Result, LoadError);
}
UE_LOG(LogTemp, Display, TEXT("BlueprintMCP: Creating snapshot for blueprint '%s'"), *BlueprintName);
@@ -305,7 +299,7 @@ FString FBlueprintMCPServer::HandleSnapshotGraph(const FString& Body)
if (GraphsToCapture.Num() == 0 && !GraphFilter.IsEmpty())
{
return MakeErrorJson(FString::Printf(TEXT("Graph '%s' not found in blueprint '%s'"), *GraphFilter, *BlueprintName));
return MakeErrorJson(Result, FString::Printf(TEXT("Graph '%s' not found in blueprint '%s'"), *GraphFilter, *BlueprintName));
}
int32 TotalConnections = 0;
@@ -336,32 +330,24 @@ FString FBlueprintMCPServer::HandleSnapshotGraph(const FString& Body)
*Snapshot.SnapshotId, GraphsToCapture.Num(), TotalConnections);
// Build response
TSharedRef<FJsonObject> Result = MakeShared<FJsonObject>();
Result->SetStringField(TEXT("status"), TEXT("ok"));
Result->SetStringField(TEXT("snapshotId"), Snapshot.SnapshotId);
Result->SetStringField(TEXT("blueprint"), BP->GetName());
Result->SetArrayField(TEXT("graphs"), GraphSummaries);
Result->SetNumberField(TEXT("totalConnections"), TotalConnections);
return JsonToString(Result);
}
// ============================================================
// HandleDiffGraph
// ============================================================
FString FBlueprintMCPServer::HandleDiffGraph(const FString& Body)
void FBlueprintMCPServer::HandleDiffGraph(const FJsonObject* Json, FJsonObject* Result)
{
TSharedPtr<FJsonObject> Json = ParseBodyJson(Body);
if (!Json.IsValid())
{
return MakeErrorJson(TEXT("Invalid JSON body"));
}
FString BlueprintName = Json->GetStringField(TEXT("blueprint"));
FString SnapshotId = Json->GetStringField(TEXT("snapshotId"));
if (BlueprintName.IsEmpty() || SnapshotId.IsEmpty())
{
return MakeErrorJson(TEXT("Missing required fields: blueprint, snapshotId"));
return MakeErrorJson(Result, TEXT("Missing required fields: blueprint, snapshotId"));
}
FString GraphFilter;
@@ -374,7 +360,7 @@ FString FBlueprintMCPServer::HandleDiffGraph(const FString& Body)
{
if (!LoadSnapshotFromDisk(SnapshotId, LoadedSnapshot))
{
return MakeErrorJson(FString::Printf(TEXT("Snapshot '%s' not found in memory or on disk"), *SnapshotId));
return MakeErrorJson(Result, FString::Printf(TEXT("Snapshot '%s' not found in memory or on disk"), *SnapshotId));
}
SnapshotPtr = &LoadedSnapshot;
}
@@ -384,7 +370,7 @@ FString FBlueprintMCPServer::HandleDiffGraph(const FString& Body)
UBlueprint* BP = LoadBlueprintByName(BlueprintName, LoadError);
if (!BP)
{
return MakeErrorJson(LoadError);
return MakeErrorJson(Result, LoadError);
}
UE_LOG(LogTemp, Display, TEXT("BlueprintMCP: Diffing blueprint '%s' against snapshot '%s'"), *BlueprintName, *SnapshotId);
@@ -545,7 +531,6 @@ FString FBlueprintMCPServer::HandleDiffGraph(const FString& Body)
}
// Build result
TSharedRef<FJsonObject> Result = MakeShared<FJsonObject>();
Result->SetStringField(TEXT("status"), TEXT("ok"));
Result->SetStringField(TEXT("blueprint"), BP->GetName());
Result->SetStringField(TEXT("snapshotId"), SnapshotId);
@@ -563,27 +548,19 @@ FString FBlueprintMCPServer::HandleDiffGraph(const FString& Body)
UE_LOG(LogTemp, Display, TEXT("BlueprintMCP: Diff complete — %d severed, %d new, %d type changes, %d missing nodes"),
SeveredArr.Num(), NewConnsArr.Num(), TypeChangesArr.Num(), MissingNodesArr.Num());
return JsonToString(Result);
}
// ============================================================
// HandleRestoreGraph
// ============================================================
FString FBlueprintMCPServer::HandleRestoreGraph(const FString& Body)
void FBlueprintMCPServer::HandleRestoreGraph(const FJsonObject* Json, FJsonObject* Result)
{
TSharedPtr<FJsonObject> Json = ParseBodyJson(Body);
if (!Json.IsValid())
{
return MakeErrorJson(TEXT("Invalid JSON body"));
}
FString BlueprintName = Json->GetStringField(TEXT("blueprint"));
FString SnapshotId = Json->GetStringField(TEXT("snapshotId"));
if (BlueprintName.IsEmpty() || SnapshotId.IsEmpty())
{
return MakeErrorJson(TEXT("Missing required fields: blueprint, snapshotId"));
return MakeErrorJson(Result, TEXT("Missing required fields: blueprint, snapshotId"));
}
FString GraphFilter;
@@ -602,7 +579,7 @@ FString FBlueprintMCPServer::HandleRestoreGraph(const FString& Body)
{
if (!LoadSnapshotFromDisk(SnapshotId, LoadedSnapshot))
{
return MakeErrorJson(FString::Printf(TEXT("Snapshot '%s' not found in memory or on disk"), *SnapshotId));
return MakeErrorJson(Result, FString::Printf(TEXT("Snapshot '%s' not found in memory or on disk"), *SnapshotId));
}
SnapshotPtr = &LoadedSnapshot;
}
@@ -612,7 +589,7 @@ FString FBlueprintMCPServer::HandleRestoreGraph(const FString& Body)
UBlueprint* BP = LoadBlueprintByName(BlueprintName, LoadError);
if (!BP)
{
return MakeErrorJson(LoadError);
return MakeErrorJson(Result, LoadError);
}
UE_LOG(LogTemp, Display, TEXT("BlueprintMCP: Restoring connections from snapshot '%s' for blueprint '%s' (dryRun=%s)"),
@@ -775,28 +752,20 @@ FString FBlueprintMCPServer::HandleRestoreGraph(const FString& Body)
UE_LOG(LogTemp, Display, TEXT("BlueprintMCP: Restore complete — %d reconnected, %d failed, saved=%s"),
Reconnected, Failed, bSaved ? TEXT("true") : TEXT("false"));
TSharedRef<FJsonObject> Result = MakeShared<FJsonObject>();
Result->SetStringField(TEXT("status"), TEXT("ok"));
Result->SetNumberField(TEXT("reconnected"), Reconnected);
Result->SetNumberField(TEXT("failed"), Failed);
Result->SetArrayField(TEXT("details"), DetailsArr);
Result->SetBoolField(TEXT("saved"), bSaved);
Result->SetBoolField(TEXT("dryRun"), bDryRun);
return JsonToString(Result);
}
// ============================================================
// HandleFindDisconnectedPins
// ============================================================
FString FBlueprintMCPServer::HandleFindDisconnectedPins(const FString& Body)
void FBlueprintMCPServer::HandleFindDisconnectedPins(const FJsonObject* Json, FJsonObject* Result)
{
TSharedPtr<FJsonObject> Json = ParseBodyJson(Body);
if (!Json.IsValid())
{
return MakeErrorJson(TEXT("Invalid JSON body"));
}
FString BlueprintName;
Json->TryGetStringField(TEXT("blueprint"), BlueprintName);
@@ -808,7 +777,7 @@ FString FBlueprintMCPServer::HandleFindDisconnectedPins(const FString& Body)
if (BlueprintName.IsEmpty() && PathFilter.IsEmpty() && SnapshotId.IsEmpty())
{
return MakeErrorJson(TEXT("Provide at least one of: blueprint, filter, or snapshotId"));
return MakeErrorJson(Result, TEXT("Provide at least one of: blueprint, filter, or snapshotId"));
}
// Optionally load snapshot for definite-break detection
@@ -1086,7 +1055,6 @@ FString FBlueprintMCPServer::HandleFindDisconnectedPins(const FString& Body)
UE_LOG(LogTemp, Display, TEXT("BlueprintMCP: FindDisconnectedPins complete — %d HIGH, %d MEDIUM, %d total across %d blueprints"),
HighCount, MediumCount, ResultsArr.Num(), BlueprintsScanned);
TSharedRef<FJsonObject> Result = MakeShared<FJsonObject>();
Result->SetArrayField(TEXT("results"), ResultsArr);
TSharedRef<FJsonObject> Summary = MakeShared<FJsonObject>();
@@ -1095,26 +1063,18 @@ FString FBlueprintMCPServer::HandleFindDisconnectedPins(const FString& Body)
Summary->SetNumberField(TEXT("total"), ResultsArr.Num());
Summary->SetNumberField(TEXT("blueprintsScanned"), BlueprintsScanned);
Result->SetObjectField(TEXT("summary"), Summary);
return JsonToString(Result);
}
// ============================================================
// HandleAnalyzeRebuildImpact
// ============================================================
FString FBlueprintMCPServer::HandleAnalyzeRebuildImpact(const FString& Body)
void FBlueprintMCPServer::HandleAnalyzeRebuildImpact(const FJsonObject* Json, FJsonObject* Result)
{
TSharedPtr<FJsonObject> Json = ParseBodyJson(Body);
if (!Json.IsValid())
{
return MakeErrorJson(TEXT("Invalid JSON body"));
}
FString ModuleName = Json->GetStringField(TEXT("moduleName"));
if (ModuleName.IsEmpty())
{
return MakeErrorJson(TEXT("Missing required field: moduleName"));
return MakeErrorJson(Result, TEXT("Missing required field: moduleName"));
}
// Optional struct name filter
@@ -1359,7 +1319,6 @@ FString FBlueprintMCPServer::HandleAnalyzeRebuildImpact(const FString& Body)
AffectedBlueprints.Num(), TotalBreakMakeNodes, TotalConnectionsAtRisk);
// Build response
TSharedRef<FJsonObject> Result = MakeShared<FJsonObject>();
Result->SetStringField(TEXT("moduleName"), ModuleName);
Result->SetArrayField(TEXT("typesFound"), TypesFoundArr);
@@ -1384,6 +1343,4 @@ FString FBlueprintMCPServer::HandleAnalyzeRebuildImpact(const FString& Body)
Summary->SetNumberField(TEXT("totalBreakMakeNodes"), TotalBreakMakeNodes);
Summary->SetNumberField(TEXT("totalConnectionsAtRisk"), TotalConnectionsAtRisk);
Result->SetObjectField(TEXT("summary"), Summary);
return JsonToString(Result);
}