flockbay 0.10.15 → 0.10.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/codex/flockbayMcpStdioBridge.cjs +339 -0
  2. package/dist/codex/flockbayMcpStdioBridge.mjs +339 -0
  3. package/dist/{index--o4BPz5o.cjs → index-BxBuBx7C.cjs} +2706 -609
  4. package/dist/{index-CUp3juDS.mjs → index-CHm9r89K.mjs} +2707 -611
  5. package/dist/index.cjs +3 -5
  6. package/dist/index.mjs +3 -5
  7. package/dist/lib.cjs +7 -9
  8. package/dist/lib.d.cts +219 -531
  9. package/dist/lib.d.mts +219 -531
  10. package/dist/lib.mjs +7 -9
  11. package/dist/{runCodex-D3eT-TvB.cjs → runCodex-DuCGwO2K.cjs} +264 -43
  12. package/dist/{runCodex-o6PCbHQ7.mjs → runCodex-DudVDqNh.mjs} +263 -42
  13. package/dist/{runGemini-CBxZp6I7.cjs → runGemini-B25LZ4Cw.cjs} +64 -29
  14. package/dist/{runGemini-Bt0oEj_g.mjs → runGemini-Ddu8UCOS.mjs} +63 -28
  15. package/dist/{types-C-jnUdn_.cjs → types-CGQhv7Z-.cjs} +470 -1146
  16. package/dist/{types-DGd6ea2Z.mjs → types-DuhcLxar.mjs} +469 -1142
  17. package/package.json +1 -1
  18. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintCommands.cpp +195 -6
  19. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintNodeCommands.cpp +376 -5
  20. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommandSchema.cpp +731 -0
  21. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommonUtils.cpp +476 -8
  22. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPEditorCommands.cpp +1518 -94
  23. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/MCPServerRunnable.cpp +7 -4
  24. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPBridge.cpp +150 -112
  25. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintCommands.h +2 -1
  26. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintNodeCommands.h +4 -1
  27. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPCommandSchema.h +42 -0
  28. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPEditorCommands.h +21 -0
  29. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/UnrealMCP.Build.cs +4 -1
  30. package/dist/flockbayScreenshotGate-DJX3Is5d.mjs +0 -136
  31. package/dist/flockbayScreenshotGate-DkxU24cR.cjs +0 -138
@@ -16,6 +16,8 @@
16
16
  #include "Camera/CameraActor.h"
17
17
  #include "Kismet/GameplayStatics.h"
18
18
  #include "EdGraphSchema_K2.h"
19
+ #include "UObject/UObjectIterator.h"
20
+ #include "Kismet/BlueprintFunctionLibrary.h"
19
21
 
20
22
  // Declare the log category
21
23
  DEFINE_LOG_CATEGORY_STATIC(LogUnrealMCP, Log, All);
@@ -34,6 +36,10 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleCommand(const FSt
34
36
  {
35
37
  return HandleAddBlueprintGetSelfComponentReference(Params);
36
38
  }
39
+ else if (CommandType == TEXT("add_blueprint_get_component_node"))
40
+ {
41
+ return HandleAddBlueprintGetComponentNode(Params);
42
+ }
37
43
  else if (CommandType == TEXT("add_blueprint_event_node"))
38
44
  {
39
45
  return HandleAddBlueprintEvent(Params);
@@ -58,10 +64,77 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleCommand(const FSt
58
64
  {
59
65
  return HandleFindBlueprintNodes(Params);
60
66
  }
67
+ else if (CommandType == TEXT("search_blueprint_functions"))
68
+ {
69
+ return HandleSearchBlueprintFunctions(Params);
70
+ }
71
+ else if (CommandType == TEXT("resolve_blueprint_function"))
72
+ {
73
+ return HandleResolveBlueprintFunction(Params);
74
+ }
61
75
 
62
76
  return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Unknown blueprint node command: %s"), *CommandType));
63
77
  }
64
78
 
79
+ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintGetComponentNode(const TSharedPtr<FJsonObject>& Params)
80
+ {
81
+ // This mirrors the editor UX of dragging a Blueprint component into the EventGraph,
82
+ // which creates a variable-get node referencing that component on Self.
83
+ FString BlueprintName;
84
+ if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
85
+ {
86
+ return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
87
+ }
88
+
89
+ FString ComponentName;
90
+ if (!Params->TryGetStringField(TEXT("component_name"), ComponentName))
91
+ {
92
+ return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'component_name' parameter"));
93
+ }
94
+
95
+ FVector2D NodePosition(0.0f, 0.0f);
96
+ if (Params->HasField(TEXT("node_position")))
97
+ {
98
+ NodePosition = FUnrealMCPCommonUtils::GetVector2DFromJson(Params, TEXT("node_position"));
99
+ }
100
+
101
+ UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
102
+ if (!Blueprint)
103
+ {
104
+ return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
105
+ }
106
+
107
+ UEdGraph* EventGraph = FUnrealMCPCommonUtils::FindOrCreateEventGraph(Blueprint);
108
+ if (!EventGraph)
109
+ {
110
+ return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to get event graph"));
111
+ }
112
+
113
+ UK2Node_VariableGet* GetComponentNode = NewObject<UK2Node_VariableGet>(EventGraph);
114
+ if (!GetComponentNode)
115
+ {
116
+ return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to create get component node"));
117
+ }
118
+
119
+ FMemberReference& VarRef = GetComponentNode->VariableReference;
120
+ VarRef.SetSelfMember(FName(*ComponentName));
121
+
122
+ GetComponentNode->NodePosX = NodePosition.X;
123
+ GetComponentNode->NodePosY = NodePosition.Y;
124
+
125
+ EventGraph->AddNode(GetComponentNode);
126
+ GetComponentNode->CreateNewGuid();
127
+ GetComponentNode->PostPlacedNewNode();
128
+ GetComponentNode->AllocateDefaultPins();
129
+ GetComponentNode->ReconstructNode();
130
+
131
+ FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
132
+
133
+ TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
134
+ ResultObj->SetStringField(TEXT("node_id"), GetComponentNode->NodeGuid.ToString());
135
+ return ResultObj;
136
+ }
137
+
65
138
  TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleConnectBlueprintNodes(const TSharedPtr<FJsonObject>& Params)
66
139
  {
67
140
  // Get required parameters
@@ -291,6 +364,11 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
291
364
  FString Target;
292
365
  Params->TryGetStringField(TEXT("target"), Target);
293
366
 
367
+ FString OwnerPath;
368
+ Params->TryGetStringField(TEXT("function_owner_path"), OwnerPath);
369
+ Params->TryGetStringField(TEXT("owner_class_path"), OwnerPath);
370
+ Params->TryGetStringField(TEXT("ownerPath"), OwnerPath);
371
+
294
372
  // Find the blueprint
295
373
  UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
296
374
  if (!Blueprint)
@@ -313,6 +391,21 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
313
391
  UE_LOG(LogTemp, Display, TEXT("Looking for function '%s' in target '%s'"),
314
392
  *FunctionName, Target.IsEmpty() ? TEXT("Blueprint") : *Target);
315
393
 
394
+ // If we have an explicit owner class path, resolve it first (most reliable across UE versions).
395
+ if (!OwnerPath.IsEmpty())
396
+ {
397
+ OwnerPath = OwnerPath.TrimStartAndEnd();
398
+ UClass* OwnerClass = LoadObject<UClass>(nullptr, *OwnerPath);
399
+ if (!OwnerClass && !OwnerPath.Contains(TEXT("'")))
400
+ {
401
+ OwnerClass = LoadObject<UClass>(nullptr, *FString::Printf(TEXT("Class'%s'"), *OwnerPath));
402
+ }
403
+ if (OwnerClass)
404
+ {
405
+ Function = OwnerClass->FindFunctionByName(*FunctionName);
406
+ }
407
+ }
408
+
316
409
  // Check if we have a target class specified
317
410
  if (!Target.IsEmpty())
318
411
  {
@@ -366,8 +459,8 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
366
459
  }
367
460
  }
368
461
 
369
- // If we found a target class, look for the function there
370
- if (TargetClass)
462
+ // If we found a target class, look for the function there (unless owner path already resolved).
463
+ if (TargetClass && !Function)
371
464
  {
372
465
  UE_LOG(LogTemp, Display, TEXT("Looking for function '%s' in class '%s'"),
373
466
  *FunctionName, *TargetClass->GetName());
@@ -390,8 +483,6 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
390
483
  for (TFieldIterator<UFunction> FuncIt(CurrentClass); FuncIt; ++FuncIt)
391
484
  {
392
485
  UFunction* AvailableFunc = *FuncIt;
393
- UE_LOG(LogTemp, Display, TEXT(" - Available function: %s"), *AvailableFunc->GetName());
394
-
395
486
  if (AvailableFunc->GetName().Equals(FunctionName, ESearchCase::IgnoreCase))
396
487
  {
397
488
  UE_LOG(LogTemp, Display, TEXT(" - Found case-insensitive match: %s"), *AvailableFunc->GetName());
@@ -670,6 +761,264 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
670
761
  return ResultObj;
671
762
  }
672
763
 
764
+ static bool IsBlueprintCallableFunction(UFunction* Function)
765
+ {
766
+ if (!Function) return false;
767
+ const bool bCallable = Function->HasAnyFunctionFlags(FUNC_BlueprintCallable | FUNC_BlueprintPure);
768
+ if (!bCallable) return false;
769
+ if (Function->HasAnyFunctionFlags(FUNC_Delegate)) return false;
770
+ if (Function->HasMetaData(FName(TEXT("DeprecatedFunction")))) return false;
771
+ return true;
772
+ }
773
+
774
+ static FString SafeDisplayName(UFunction* Function)
775
+ {
776
+ if (!Function) return TEXT("");
777
+ if (Function->HasMetaData(FName(TEXT("DisplayName"))))
778
+ {
779
+ return Function->GetMetaData(FName(TEXT("DisplayName")));
780
+ }
781
+ return Function->GetName();
782
+ }
783
+
784
+ static bool MatchesQuery(const FString& QueryLower, const FString& Candidate)
785
+ {
786
+ return Candidate.ToLower().Contains(QueryLower);
787
+ }
788
+
789
+ static UClass* ResolveClassBestEffort(const FString& Target)
790
+ {
791
+ FString T = Target.TrimStartAndEnd();
792
+ if (T.IsEmpty()) return nullptr;
793
+
794
+ if (T.StartsWith(TEXT("/Script/")))
795
+ {
796
+ return LoadObject<UClass>(nullptr, *T);
797
+ }
798
+
799
+ UClass* Found = FindObject<UClass>(ANY_PACKAGE, *T);
800
+ if (!Found && !T.StartsWith(TEXT("U")))
801
+ {
802
+ Found = FindObject<UClass>(ANY_PACKAGE, *(FString(TEXT("U")) + T));
803
+ }
804
+ if (!Found && !T.EndsWith(TEXT("Library")))
805
+ {
806
+ Found = FindObject<UClass>(ANY_PACKAGE, *(FString(TEXT("U")) + T + TEXT("Library")));
807
+ }
808
+ if (!Found && !T.EndsWith(TEXT("Component")))
809
+ {
810
+ Found = FindObject<UClass>(ANY_PACKAGE, *(FString(TEXT("U")) + T + TEXT("Component")));
811
+ }
812
+ return Found;
813
+ }
814
+
815
+ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleSearchBlueprintFunctions(const TSharedPtr<FJsonObject>& Params)
816
+ {
817
+ FString Query;
818
+ if (!Params->TryGetStringField(TEXT("query"), Query) && !Params->TryGetStringField(TEXT("name"), Query))
819
+ {
820
+ return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'query' parameter"));
821
+ }
822
+ Query = Query.TrimStartAndEnd();
823
+ if (Query.IsEmpty())
824
+ {
825
+ return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("'query' is empty"));
826
+ }
827
+
828
+ FString Target;
829
+ Params->TryGetStringField(TEXT("target"), Target);
830
+ Params->TryGetStringField(TEXT("class"), Target);
831
+
832
+ int32 Limit = 25;
833
+ if (Params->HasField(TEXT("limit")))
834
+ {
835
+ Limit = (int32)Params->GetNumberField(TEXT("limit"));
836
+ Limit = FMath::Clamp(Limit, 1, 200);
837
+ }
838
+
839
+ UClass* TargetClass = nullptr;
840
+ if (!Target.IsEmpty())
841
+ {
842
+ TargetClass = ResolveClassBestEffort(Target);
843
+ }
844
+
845
+ const FString QueryLower = Query.ToLower();
846
+ TArray<TSharedPtr<FJsonValue>> Matches;
847
+
848
+ auto MaybeAddFunction = [&](UFunction* Function, UClass* OwnerClass)
849
+ {
850
+ if ((int32)Matches.Num() >= Limit) return;
851
+ if (!IsBlueprintCallableFunction(Function)) return;
852
+
853
+ const FString Name = Function->GetName();
854
+ const FString Display = SafeDisplayName(Function);
855
+ if (!MatchesQuery(QueryLower, Name) && !MatchesQuery(QueryLower, Display)) return;
856
+
857
+ TSharedPtr<FJsonObject> Obj = MakeShared<FJsonObject>();
858
+ Obj->SetStringField(TEXT("functionName"), Name);
859
+ Obj->SetStringField(TEXT("displayName"), Display);
860
+ if (OwnerClass)
861
+ {
862
+ Obj->SetStringField(TEXT("ownerClass"), OwnerClass->GetName());
863
+ Obj->SetStringField(TEXT("ownerPath"), OwnerClass->GetPathName());
864
+ }
865
+ Obj->SetBoolField(TEXT("isStatic"), Function->HasAnyFunctionFlags(FUNC_Static));
866
+
867
+ // Minimal signature info.
868
+ TArray<TSharedPtr<FJsonValue>> Inputs;
869
+ TArray<TSharedPtr<FJsonValue>> Outputs;
870
+ for (TFieldIterator<FProperty> It(Function); It; ++It)
871
+ {
872
+ FProperty* Prop = *It;
873
+ if (!Prop) continue;
874
+ const bool bIsReturn = Prop->HasAnyPropertyFlags(CPF_ReturnParm);
875
+ const bool bIsOut = Prop->HasAnyPropertyFlags(CPF_OutParm) && !Prop->HasAnyPropertyFlags(CPF_ConstParm);
876
+
877
+ TSharedPtr<FJsonObject> P = MakeShared<FJsonObject>();
878
+ P->SetStringField(TEXT("name"), Prop->GetName());
879
+ P->SetStringField(TEXT("type"), Prop->GetCPPType());
880
+
881
+ if (bIsReturn || bIsOut)
882
+ {
883
+ Outputs.Add(MakeShared<FJsonValueObject>(P));
884
+ }
885
+ else
886
+ {
887
+ Inputs.Add(MakeShared<FJsonValueObject>(P));
888
+ }
889
+ }
890
+ Obj->SetArrayField(TEXT("inputs"), Inputs);
891
+ Obj->SetArrayField(TEXT("outputs"), Outputs);
892
+
893
+ Matches.Add(MakeShared<FJsonValueObject>(Obj));
894
+ };
895
+
896
+ if (TargetClass)
897
+ {
898
+ for (TFieldIterator<UFunction> FuncIt(TargetClass, EFieldIteratorFlags::IncludeSuper); FuncIt; ++FuncIt)
899
+ {
900
+ MaybeAddFunction(*FuncIt, TargetClass);
901
+ if ((int32)Matches.Num() >= Limit) break;
902
+ }
903
+ }
904
+ else
905
+ {
906
+ for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt)
907
+ {
908
+ UClass* Class = *ClassIt;
909
+ if (!Class) continue;
910
+ if (!Class->IsChildOf(UBlueprintFunctionLibrary::StaticClass())) continue;
911
+ if (Class->HasAnyClassFlags(CLASS_Deprecated)) continue;
912
+
913
+ for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt)
914
+ {
915
+ MaybeAddFunction(*FuncIt, Class);
916
+ if ((int32)Matches.Num() >= Limit) break;
917
+ }
918
+ if ((int32)Matches.Num() >= Limit) break;
919
+ }
920
+ }
921
+
922
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
923
+ Result->SetStringField(TEXT("query"), Query);
924
+ if (!Target.IsEmpty()) Result->SetStringField(TEXT("target"), Target);
925
+ Result->SetNumberField(TEXT("count"), Matches.Num());
926
+ Result->SetArrayField(TEXT("matches"), Matches);
927
+ return Result;
928
+ }
929
+
930
+ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleResolveBlueprintFunction(const TSharedPtr<FJsonObject>& Params)
931
+ {
932
+ FString FunctionName;
933
+ if (!Params->TryGetStringField(TEXT("function_name"), FunctionName) &&
934
+ !Params->TryGetStringField(TEXT("name"), FunctionName) &&
935
+ !Params->TryGetStringField(TEXT("query"), FunctionName))
936
+ {
937
+ return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'function_name' parameter"));
938
+ }
939
+ FunctionName = FunctionName.TrimStartAndEnd();
940
+ if (FunctionName.IsEmpty())
941
+ {
942
+ return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("'function_name' is empty"));
943
+ }
944
+
945
+ FString Target;
946
+ Params->TryGetStringField(TEXT("target"), Target);
947
+ Params->TryGetStringField(TEXT("class"), Target);
948
+
949
+ UClass* TargetClass = nullptr;
950
+ if (!Target.IsEmpty())
951
+ {
952
+ TargetClass = ResolveClassBestEffort(Target);
953
+ }
954
+
955
+ UFunction* Resolved = nullptr;
956
+ UClass* Owner = nullptr;
957
+
958
+ auto SearchClass = [&](UClass* Class)
959
+ {
960
+ if (!Class || Resolved) return;
961
+ for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::IncludeSuper); FuncIt; ++FuncIt)
962
+ {
963
+ UFunction* F = *FuncIt;
964
+ if (!IsBlueprintCallableFunction(F)) continue;
965
+ if (F->GetName().Equals(FunctionName, ESearchCase::IgnoreCase))
966
+ {
967
+ Resolved = F;
968
+ Owner = Class;
969
+ return;
970
+ }
971
+ }
972
+ };
973
+
974
+ if (TargetClass)
975
+ {
976
+ SearchClass(TargetClass);
977
+ }
978
+ else
979
+ {
980
+ // Prefer common Blueprint libraries first.
981
+ const TArray<FString> Preferred = { TEXT("KismetMathLibrary"), TEXT("KismetSystemLibrary"), TEXT("GameplayStatics") };
982
+ for (const FString& Name : Preferred)
983
+ {
984
+ if (Resolved) break;
985
+ SearchClass(ResolveClassBestEffort(Name));
986
+ }
987
+
988
+ if (!Resolved)
989
+ {
990
+ for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt)
991
+ {
992
+ UClass* Class = *ClassIt;
993
+ if (!Class) continue;
994
+ if (!Class->IsChildOf(UBlueprintFunctionLibrary::StaticClass())) continue;
995
+ SearchClass(Class);
996
+ if (Resolved) break;
997
+ }
998
+ }
999
+ }
1000
+
1001
+ if (!Resolved || !Owner)
1002
+ {
1003
+ return FUnrealMCPCommonUtils::CreateErrorResponse(
1004
+ FString::Printf(TEXT("Function not found or not Blueprint-callable: %s"), *FunctionName));
1005
+ }
1006
+
1007
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
1008
+ Result->SetStringField(TEXT("functionName"), Resolved->GetName());
1009
+ Result->SetStringField(TEXT("displayName"), SafeDisplayName(Resolved));
1010
+ Result->SetStringField(TEXT("ownerClass"), Owner->GetName());
1011
+ Result->SetStringField(TEXT("ownerPath"), Owner->GetPathName());
1012
+
1013
+ // Suggest params for add_blueprint_function_node (caller must add blueprint_name).
1014
+ TSharedPtr<FJsonObject> Suggested = MakeShared<FJsonObject>();
1015
+ Suggested->SetStringField(TEXT("function_name"), Resolved->GetName());
1016
+ Suggested->SetStringField(TEXT("function_owner_path"), Owner->GetPathName());
1017
+ Result->SetObjectField(TEXT("suggested"), Suggested);
1018
+
1019
+ return Result;
1020
+ }
1021
+
673
1022
  TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintVariable(const TSharedPtr<FJsonObject>& Params)
674
1023
  {
675
1024
  // Get required parameters
@@ -690,6 +1039,28 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintVaria
690
1039
  {
691
1040
  return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'variable_type' parameter"));
692
1041
  }
1042
+ VariableType = VariableType.TrimStartAndEnd();
1043
+ const FString VariableTypeLower = VariableType.ToLower();
1044
+ if (VariableTypeLower == TEXT("bool") || VariableTypeLower == TEXT("boolean"))
1045
+ {
1046
+ VariableType = TEXT("Boolean");
1047
+ }
1048
+ else if (VariableTypeLower == TEXT("int") || VariableTypeLower == TEXT("integer"))
1049
+ {
1050
+ VariableType = TEXT("Integer");
1051
+ }
1052
+ else if (VariableTypeLower == TEXT("float") || VariableTypeLower == TEXT("number") || VariableTypeLower == TEXT("double"))
1053
+ {
1054
+ VariableType = TEXT("Float");
1055
+ }
1056
+ else if (VariableTypeLower == TEXT("string") || VariableTypeLower == TEXT("str"))
1057
+ {
1058
+ VariableType = TEXT("String");
1059
+ }
1060
+ else if (VariableTypeLower == TEXT("vector") || VariableTypeLower == TEXT("vec3"))
1061
+ {
1062
+ VariableType = TEXT("Vector");
1063
+ }
693
1064
 
694
1065
  // Get optional parameters
695
1066
  bool IsExposed = false;
@@ -921,4 +1292,4 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleFindBlueprintNode
921
1292
  ResultObj->SetArrayField(TEXT("node_guids"), NodeGuidArray);
922
1293
 
923
1294
  return ResultObj;
924
- }
1295
+ }