// Exposes K2 graph mutation to Python. // // In Python these are reachable as: // unreal.MCPGraphLibrary.spawn_call_function_node(bp, graph, owner_class, fn_name, pos) // unreal.MCPGraphLibrary.connect_pins(graph, from_id, "Then", to_id, "Exec") // etc. // // Every spawn returns the node's NodeGuid as a string. Python keeps a local // id -> NodeGuid map and passes the guid into connect_pins / set_pin_default. #pragma once #include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "MCPGraphLibrary.generated.h" class UBlueprint; class UWidgetBlueprint; class UWidget; class UEdGraph; class UEdGraphNode; class UEdGraphPin; class UScriptStruct; class UEnum; UCLASS() class UEBLUEPRINTMCPEDITOR_API UMCPGraphLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() public: // ==================================================================== // Graph lookup // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|Graph") static UEdGraph* FindEventGraph(UBlueprint* Blueprint); UFUNCTION(BlueprintCallable, Category = "MCP|Graph") static UEdGraph* FindFunctionGraph(UBlueprint* Blueprint, FName FunctionName); UFUNCTION(BlueprintCallable, Category = "MCP|Graph") static TArray ListNodeIds(UEdGraph* Graph); UFUNCTION(BlueprintCallable, Category = "MCP|Graph") static TArray ListPinsOnNode(UEdGraph* Graph, const FString& NodeId); UFUNCTION(BlueprintCallable, Category = "MCP|Graph") static int32 ClearGraph(UEdGraph* Graph); UFUNCTION(BlueprintCallable, Category = "MCP|Graph") static bool DeleteNode(UEdGraph* Graph, const FString& NodeId); // ==================================================================== // Spawners — basic // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnCallFunctionNode(UBlueprint* Blueprint, UEdGraph* Graph, UClass* FunctionOwnerClass, FName FunctionName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnEventNode(UBlueprint* Blueprint, UEdGraph* Graph, UClass* OwnerClass, FName EventName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnCustomEventNode(UBlueprint* Blueprint, UEdGraph* Graph, FName EventName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Network") static bool SetCustomEventNetworkFlags(UBlueprint* Blueprint, UEdGraph* Graph, const FString& NodeIdOrEventName, FName Mode, bool bReliable); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnComponentBoundEvent(UBlueprint* Blueprint, UEdGraph* Graph, FName ComponentName, FName DelegateName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnBranchNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnSequenceNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position, int32 OutputCount); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnVariableGetNode(UBlueprint* Blueprint, UEdGraph* Graph, FName VariableName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnVariableSetNode(UBlueprint* Blueprint, UEdGraph* Graph, FName VariableName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnSelfNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnCastNode(UBlueprint* Blueprint, UEdGraph* Graph, UClass* TargetClass, FVector2D Position); // ==================================================================== // Spawners — flow / collections // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnSwitchOnIntNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnSwitchOnStringNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnSwitchOnEnumNode(UBlueprint* Blueprint, UEdGraph* Graph, UEnum* EnumType, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnMakeArrayNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnMakeStructNode(UBlueprint* Blueprint, UEdGraph* Graph, UScriptStruct* StructType, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnBreakStructNode(UBlueprint* Blueprint, UEdGraph* Graph, UScriptStruct* StructType, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnSetFieldsInStructNode(UBlueprint* Blueprint, UEdGraph* Graph, UScriptStruct* StructType, FVector2D Position); /** Spawn a UK2Node_MacroInstance bound to one of the StandardMacros (ForLoop, * ForEachLoop, WhileLoop, DoOnce, Gate, FlipFlop, MultiGate, IsValid, DoN). */ UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnStandardMacroNode(UBlueprint* Blueprint, UEdGraph* Graph, FName MacroName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnSpawnActorFromClassNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnFormatTextNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnGetSubsystemNode(UBlueprint* Blueprint, UEdGraph* Graph, UClass* SubsystemClass, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnLoadAssetNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); // ==================================================================== // Spawners — Tier 2 (knot/comment/enum literal/class defaults/return/arrays) // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnKnotNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnCommentNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position, FVector2D Size, const FString& Comment); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnEnumLiteralNode(UBlueprint* Blueprint, UEdGraph* Graph, UEnum* EnumType, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnGetClassDefaultsNode(UBlueprint* Blueprint, UEdGraph* Graph, UClass* TargetClass, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnFunctionResultNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnGetArrayItemNode(UBlueprint* Blueprint, UEdGraph* Graph, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Spawn") static FString SpawnPromotableOperatorNode(UBlueprint* Blueprint, UEdGraph* Graph, FName OperatorName, FVector2D Position); /** Add a new case pin to a SwitchInt/SwitchString/SwitchEnum node. */ UFUNCTION(BlueprintCallable, Category = "MCP|Edit") static bool AddCasePinToSwitch(UEdGraph* Graph, const FString& NodeId); /** Set FormatText template AND reconstruct so {arg} pins appear. */ UFUNCTION(BlueprintCallable, Category = "MCP|Edit") static bool FormatTextSetFormat(UEdGraph* Graph, const FString& NodeId, const FString& Format); /** Force a node to ReconstructNode() (e.g. after toggling pure/latent). */ UFUNCTION(BlueprintCallable, Category = "MCP|Edit") static bool ReconstructNode(UEdGraph* Graph, const FString& NodeId); // ==================================================================== // Delegates // ==================================================================== /** Bind an existing event to a component's multicast delegate. * target = "ComponentName.DelegateName". */ UFUNCTION(BlueprintCallable, Category = "MCP|Delegate") static FString SpawnBindDelegateNode(UBlueprint* Blueprint, UEdGraph* Graph, FName ComponentName, FName DelegateName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Delegate") static FString SpawnUnbindDelegateNode(UBlueprint* Blueprint, UEdGraph* Graph, FName ComponentName, FName DelegateName, FVector2D Position); UFUNCTION(BlueprintCallable, Category = "MCP|Delegate") static FString SpawnCallDelegateNode(UBlueprint* Blueprint, UEdGraph* Graph, FName DispatcherName, FVector2D Position); /** AssignDelegate = AddDelegate + CustomEvent — a sugar combo node. */ UFUNCTION(BlueprintCallable, Category = "MCP|Delegate") static FString SpawnAssignDelegateNode(UBlueprint* Blueprint, UEdGraph* Graph, FName ComponentName, FName DelegateName, FVector2D Position); /** Add an Event Dispatcher (multicast delegate variable) with no params. */ UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool AddEventDispatcher(UBlueprint* Blueprint, FName DispatcherName); // ==================================================================== // Edges & defaults // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|Edges") static bool ConnectPins(UEdGraph* Graph, const FString& FromNodeId, FName FromPin, const FString& ToNodeId, FName ToPin); UFUNCTION(BlueprintCallable, Category = "MCP|Edges") static bool BreakLink(UEdGraph* Graph, const FString& FromNodeId, FName FromPin, const FString& ToNodeId, FName ToPin); UFUNCTION(BlueprintCallable, Category = "MCP|Edges") static bool BreakAllNodeLinks(UEdGraph* Graph, const FString& NodeId); UFUNCTION(BlueprintCallable, Category = "MCP|Edges") static bool SetPinDefault(UEdGraph* Graph, const FString& NodeId, FName PinName, const FString& Value); // ==================================================================== // BP-level authoring // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static UEdGraph* AddFunctionGraph(UBlueprint* Blueprint, FName FunctionName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static UEdGraph* AddMacroGraph(UBlueprint* Blueprint, FName MacroName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool AddInterface(UBlueprint* Blueprint, const FString& InterfacePath); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool SetVariableDefaultValue(UBlueprint* Blueprint, FName VariableName, const FString& Value); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool SetVariableMetadata(UBlueprint* Blueprint, FName VariableName, bool bInstanceEditable, bool bExposeOnSpawn, const FString& Category, const FString& Tooltip); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool AddLocalVariable(UBlueprint* Blueprint, FName FunctionName, FName VariableName, const FString& TypeSpec, const FString& DefaultValue); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static FString AddComponentToBlueprint(UBlueprint* Blueprint, UClass* ComponentClass, FName ComponentName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool AddMemberVariable(UBlueprint* Blueprint, FName VariableName, const FString& TypeSpec); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool RemoveComponent(UBlueprint* Blueprint, FName ComponentName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool AttachComponent(UBlueprint* Blueprint, FName ChildName, FName ParentName, FName SocketName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool SetRootComponent(UBlueprint* Blueprint, FName ComponentName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool SetComponentProperty(UBlueprint* Blueprint, FName ComponentName, FName PropertyName, const FString& Value); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool SetComponentTransform(UBlueprint* Blueprint, FName ComponentName, FVector Location, FRotator Rotation, FVector Scale); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool ConfigureBoxComponent(UBlueprint* Blueprint, FName ComponentName, FVector Extent, FName CollisionProfile); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool RenameVariable(UBlueprint* Blueprint, FName OldName, FName NewName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool DeleteVariable(UBlueprint* Blueprint, FName VariableName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool RenameFunction(UBlueprint* Blueprint, FName OldName, FName NewName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool RemoveFunctionGraph(UBlueprint* Blueprint, FName FunctionName); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool RemoveMacroGraph(UBlueprint* Blueprint, FName MacroName); /** Add an input/output parameter to a user function. Direction: "input"/"output". */ UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool AddFunctionParameter(UBlueprint* Blueprint, FName FunctionName, FName ParamName, const FString& TypeSpec, const FString& Direction); UFUNCTION(BlueprintCallable, Category = "MCP|Authoring") static bool RemoveFunctionParameter(UBlueprint* Blueprint, FName FunctionName, FName ParamName); // ==================================================================== // UMG Designer / WidgetTree // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static FString DescribeWidgetTreeJson(UWidgetBlueprint* Blueprint); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static FString GetWidgetPropertiesJson(UWidgetBlueprint* Blueprint, FName WidgetName); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static FString GetWidgetSlotPropertiesJson(UWidgetBlueprint* Blueprint, FName WidgetName); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static FString AddWidgetToTree(UWidgetBlueprint* Blueprint, UClass* WidgetClass, FName WidgetName, FName ParentName, int32 Index, bool bIsVariable); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool RemoveWidgetFromTree(UWidgetBlueprint* Blueprint, FName WidgetName); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool RenameWidgetInTree(UWidgetBlueprint* Blueprint, FName OldName, FName NewName); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool MoveWidgetInTree(UWidgetBlueprint* Blueprint, FName WidgetName, FName NewParentName, int32 Index); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool SetRootWidget(UWidgetBlueprint* Blueprint, FName WidgetName); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool SetWidgetIsVariable(UWidgetBlueprint* Blueprint, FName WidgetName, bool bIsVariable); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool SetWidgetProperty(UWidgetBlueprint* Blueprint, FName WidgetName, FName PropertyName, const FString& Value); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool SetWidgetSlotProperty(UWidgetBlueprint* Blueprint, FName WidgetName, FName PropertyName, const FString& Value); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool SetCanvasSlotLayout(UWidgetBlueprint* Blueprint, FName WidgetName, FVector2D Position, FVector2D Size, FVector2D AnchorsMinimum, FVector2D AnchorsMaximum, FVector2D Alignment, bool bAutoSize, int32 ZOrder); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool SetNamedSlotContent(UWidgetBlueprint* Blueprint, FName HostWidgetName, FName SlotName, FName ContentWidgetName); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool ClearNamedSlotContent(UWidgetBlueprint* Blueprint, FName HostWidgetName, FName SlotName); UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool SetDesiredFocusWidget(UWidgetBlueprint* Blueprint, FName WidgetName); /** Create a UMG WidgetAnimation that keys a single float property (e.g. RenderOpacity) * on WidgetName. Times (seconds) and Values are parallel arrays — each pair is one * linear key. The animation is added to the WidgetBlueprint's Animations array; loop * is controlled at PlayAnimation time (NumLoopsToPlay=0). Returns false on bad input * or if an animation with AnimName already exists. */ UFUNCTION(BlueprintCallable, Category = "MCP|WidgetTree") static bool CreateWidgetFloatAnimation(UWidgetBlueprint* Blueprint, FName AnimName, FName WidgetName, FName PropertyName, const TArray& Times, const TArray& Values); // ==================================================================== // Compile / introspect // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|Asset") static bool CompileAndSaveBlueprint(UBlueprint* Blueprint); UFUNCTION(BlueprintCallable, Category = "MCP|Asset") static TArray GetCompileErrors(UBlueprint* Blueprint); /** Compile + capture FCompilerResultsLog. Returns "SEV|NodeName|Message" per entry. */ UFUNCTION(BlueprintCallable, Category = "MCP|Asset") static TArray CompileWithMessages(UBlueprint* Blueprint); /** Dump entire graph as JSON string round-trippable into apply_graph NodeSpec. */ UFUNCTION(BlueprintCallable, Category = "MCP|Asset") static FString DumpGraphToJson(UEdGraph* Graph); // ==================================================================== // Discovery — Pipeline v0.3 // ==================================================================== /** List all graphs on a Blueprint. Returns JSON: {event:[], functions:[], macros:[], delegates:[]}. */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static FString ListGraphsJson(UBlueprint* Blueprint); /** Full BP overview: parent, interfaces, vars, components (SCS tree), functions, dispatchers. JSON. */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static FString DescribeBlueprintJson(UBlueprint* Blueprint); /** Currently selected nodes in the open BP editor for `Blueprint`. JSON list of NodeGuid strings + per-node info. */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static FString GetSelectedNodesJson(UBlueprint* Blueprint); /** All currently-open Blueprint editors (paths). */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static TArray ListOpenBlueprints(); /** For a UK2Node_CallFunction by guid, return {owner_class, function, source_bp_path?, native?} JSON. */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static FString ResolveFunctionSourceJson(UEdGraph* Graph, const FString& NodeId); /** All node guids in this BP that reference variable `Name`. JSON list grouped by graph. */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static FString FindVariableReferencesJson(UBlueprint* Blueprint, FName VariableName); /** All call sites of `FunctionName` (defined on Blueprint or external) within this BP. JSON. */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static FString FindFunctionReferencesJson(UBlueprint* Blueprint, FName FunctionName); /** AssetRegistry-driven BP search by parent class path. Returns list of BP paths. */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static TArray FindBlueprintsByParent(const FString& ParentClassPath); /** Hard-referenced assets of this BP (asset registry). */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static TArray GetReferencedAssets(const FString& AssetPath); /** Reverse: assets that reference this BP. */ UFUNCTION(BlueprintCallable, Category = "MCP|Discover") static TArray GetReferencersOfAsset(const FString& AssetPath); // ==================================================================== // Editing — single-node operations // ==================================================================== /** Move nodes by guid to new positions. positions: array of {guid,x,y} encoded as parallel arrays. */ UFUNCTION(BlueprintCallable, Category = "MCP|Edit") static int32 MoveNodes(UEdGraph* Graph, const TArray& NodeIds, const TArray& Positions); UFUNCTION(BlueprintCallable, Category = "MCP|Edit") static bool ResizeCommentNode(UEdGraph* Graph, const FString& NodeId, FVector2D Size); UFUNCTION(BlueprintCallable, Category = "MCP|Edit") static bool SetNodeComment(UEdGraph* Graph, const FString& NodeId, const FString& Comment, bool bCommentBubbleVisible); // ==================================================================== // Navigation — open editors, focus nodes // ==================================================================== UFUNCTION(BlueprintCallable, Category = "MCP|Navigate") static bool OpenBlueprintEditor(UBlueprint* Blueprint); UFUNCTION(BlueprintCallable, Category = "MCP|Navigate") static bool OpenGraphInEditor(UBlueprint* Blueprint, UEdGraph* Graph); UFUNCTION(BlueprintCallable, Category = "MCP|Navigate") static bool JumpToNodeInEditor(UBlueprint* Blueprint, UEdGraph* Graph, const FString& NodeId); UFUNCTION(BlueprintCallable, Category = "MCP|Introspect") static TArray ListFunctionsOnClass(UClass* Class); UFUNCTION(BlueprintCallable, Category = "MCP|Introspect") static TArray ListPropertiesOnClass(UClass* Class); UFUNCTION(BlueprintCallable, Category = "MCP|Introspect") static TArray ListDelegatesOnClass(UClass* Class); UFUNCTION(BlueprintCallable, Category = "MCP|Introspect") static FString GetPinType(UClass* OwnerClass, FName FunctionName, FName PinName); private: static UEdGraphNode* FindNodeByGuid(UEdGraph* Graph, const FString& NodeId); static UEdGraphPin* FindPinByName(UEdGraphNode* Node, const FName& PinName); static class USCS_Node* FindSCSNode(UBlueprint* Blueprint, FName ComponentName); template static TNode* PlaceNode(UEdGraph* Graph, FVector2D Position); };