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.
- package/dist/codex/flockbayMcpStdioBridge.cjs +339 -0
- package/dist/codex/flockbayMcpStdioBridge.mjs +339 -0
- package/dist/{index--o4BPz5o.cjs → index-BxBuBx7C.cjs} +2706 -609
- package/dist/{index-CUp3juDS.mjs → index-CHm9r89K.mjs} +2707 -611
- package/dist/index.cjs +3 -5
- package/dist/index.mjs +3 -5
- package/dist/lib.cjs +7 -9
- package/dist/lib.d.cts +219 -531
- package/dist/lib.d.mts +219 -531
- package/dist/lib.mjs +7 -9
- package/dist/{runCodex-D3eT-TvB.cjs → runCodex-DuCGwO2K.cjs} +264 -43
- package/dist/{runCodex-o6PCbHQ7.mjs → runCodex-DudVDqNh.mjs} +263 -42
- package/dist/{runGemini-CBxZp6I7.cjs → runGemini-B25LZ4Cw.cjs} +64 -29
- package/dist/{runGemini-Bt0oEj_g.mjs → runGemini-Ddu8UCOS.mjs} +63 -28
- package/dist/{types-C-jnUdn_.cjs → types-CGQhv7Z-.cjs} +470 -1146
- package/dist/{types-DGd6ea2Z.mjs → types-DuhcLxar.mjs} +469 -1142
- package/package.json +1 -1
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintCommands.cpp +195 -6
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintNodeCommands.cpp +376 -5
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommandSchema.cpp +731 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommonUtils.cpp +476 -8
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPEditorCommands.cpp +1518 -94
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/MCPServerRunnable.cpp +7 -4
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPBridge.cpp +150 -112
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintCommands.h +2 -1
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintNodeCommands.h +4 -1
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPCommandSchema.h +42 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPEditorCommands.h +21 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/UnrealMCP.Build.cs +4 -1
- package/dist/flockbayScreenshotGate-DJX3Is5d.mjs +0 -136
- package/dist/flockbayScreenshotGate-DkxU24cR.cjs +0 -138
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
#include "Commands/UnrealMCPCommandSchema.h"
|
|
2
|
+
#include "Commands/UnrealMCPCommonUtils.h"
|
|
3
|
+
#include "Interfaces/IPluginManager.h"
|
|
4
|
+
|
|
5
|
+
static constexpr int32 kUnrealMcpSchemaVersion = 2;
|
|
6
|
+
|
|
7
|
+
TSharedPtr<FJsonObject> FUnrealMCPParamSchema::ToJson() const
|
|
8
|
+
{
|
|
9
|
+
TSharedPtr<FJsonObject> Obj = MakeShared<FJsonObject>();
|
|
10
|
+
Obj->SetStringField(TEXT("name"), Name);
|
|
11
|
+
Obj->SetStringField(TEXT("type"), Type);
|
|
12
|
+
Obj->SetBoolField(TEXT("required"), bRequired);
|
|
13
|
+
if (!Description.IsEmpty()) Obj->SetStringField(TEXT("description"), Description);
|
|
14
|
+
if (Aliases.Num() > 0)
|
|
15
|
+
{
|
|
16
|
+
TArray<TSharedPtr<FJsonValue>> Arr;
|
|
17
|
+
for (const FString& A : Aliases) Arr.Add(MakeShared<FJsonValueString>(A));
|
|
18
|
+
Obj->SetArrayField(TEXT("aliases"), Arr);
|
|
19
|
+
}
|
|
20
|
+
if (EnumValues.Num() > 0)
|
|
21
|
+
{
|
|
22
|
+
TArray<TSharedPtr<FJsonValue>> Arr;
|
|
23
|
+
for (const FString& V : EnumValues) Arr.Add(MakeShared<FJsonValueString>(V));
|
|
24
|
+
Obj->SetArrayField(TEXT("enum"), Arr);
|
|
25
|
+
}
|
|
26
|
+
if (ValueAliases.Num() > 0)
|
|
27
|
+
{
|
|
28
|
+
TSharedPtr<FJsonObject> MapObj = MakeShared<FJsonObject>();
|
|
29
|
+
for (const TPair<FString, FString>& Pair : ValueAliases)
|
|
30
|
+
{
|
|
31
|
+
MapObj->SetStringField(Pair.Key, Pair.Value);
|
|
32
|
+
}
|
|
33
|
+
Obj->SetObjectField(TEXT("valueAliases"), MapObj);
|
|
34
|
+
}
|
|
35
|
+
return Obj;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
TSharedPtr<FJsonObject> FUnrealMCPCommandSchema::ToJson() const
|
|
39
|
+
{
|
|
40
|
+
TSharedPtr<FJsonObject> Obj = MakeShared<FJsonObject>();
|
|
41
|
+
Obj->SetStringField(TEXT("command"), Command);
|
|
42
|
+
if (!Title.IsEmpty()) Obj->SetStringField(TEXT("title"), Title);
|
|
43
|
+
if (!Description.IsEmpty()) Obj->SetStringField(TEXT("description"), Description);
|
|
44
|
+
|
|
45
|
+
TArray<TSharedPtr<FJsonValue>> ParamsArr;
|
|
46
|
+
for (const FUnrealMCPParamSchema& P : Params)
|
|
47
|
+
{
|
|
48
|
+
ParamsArr.Add(MakeShared<FJsonValueObject>(P.ToJson()));
|
|
49
|
+
}
|
|
50
|
+
Obj->SetArrayField(TEXT("params"), ParamsArr);
|
|
51
|
+
|
|
52
|
+
if (ExampleParams.IsValid())
|
|
53
|
+
{
|
|
54
|
+
Obj->SetObjectField(TEXT("exampleParams"), ExampleParams);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Obj->SetNumberField(TEXT("schemaVersion"), kUnrealMcpSchemaVersion);
|
|
58
|
+
return Obj;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static void AddStringParam(TArray<FUnrealMCPParamSchema>& Out, const FString& Name, bool bRequired, const FString& Desc, const TArray<FString>& Aliases = {})
|
|
62
|
+
{
|
|
63
|
+
FUnrealMCPParamSchema P;
|
|
64
|
+
P.Name = Name;
|
|
65
|
+
P.Type = TEXT("string");
|
|
66
|
+
P.bRequired = bRequired;
|
|
67
|
+
P.Description = Desc;
|
|
68
|
+
P.Aliases = Aliases;
|
|
69
|
+
Out.Add(MoveTemp(P));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static void AddNumberParam(TArray<FUnrealMCPParamSchema>& Out, const FString& Name, bool bRequired, const FString& Desc, const TArray<FString>& Aliases = {})
|
|
73
|
+
{
|
|
74
|
+
FUnrealMCPParamSchema P;
|
|
75
|
+
P.Name = Name;
|
|
76
|
+
P.Type = TEXT("number");
|
|
77
|
+
P.bRequired = bRequired;
|
|
78
|
+
P.Description = Desc;
|
|
79
|
+
P.Aliases = Aliases;
|
|
80
|
+
Out.Add(MoveTemp(P));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static void AddBoolParam(TArray<FUnrealMCPParamSchema>& Out, const FString& Name, bool bRequired, const FString& Desc, const TArray<FString>& Aliases = {})
|
|
84
|
+
{
|
|
85
|
+
FUnrealMCPParamSchema P;
|
|
86
|
+
P.Name = Name;
|
|
87
|
+
P.Type = TEXT("boolean");
|
|
88
|
+
P.bRequired = bRequired;
|
|
89
|
+
P.Description = Desc;
|
|
90
|
+
P.Aliases = Aliases;
|
|
91
|
+
Out.Add(MoveTemp(P));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static void AddAnyParam(TArray<FUnrealMCPParamSchema>& Out, const FString& Name, bool bRequired, const FString& Desc, const TArray<FString>& Aliases = {})
|
|
95
|
+
{
|
|
96
|
+
FUnrealMCPParamSchema P;
|
|
97
|
+
P.Name = Name;
|
|
98
|
+
P.Type = TEXT("any");
|
|
99
|
+
P.bRequired = bRequired;
|
|
100
|
+
P.Description = Desc;
|
|
101
|
+
P.Aliases = Aliases;
|
|
102
|
+
Out.Add(MoveTemp(P));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static void AddVectorParam(TArray<FUnrealMCPParamSchema>& Out, const FString& Name, bool bRequired, const FString& Desc, const TArray<FString>& Aliases = {})
|
|
106
|
+
{
|
|
107
|
+
FUnrealMCPParamSchema P;
|
|
108
|
+
P.Name = Name;
|
|
109
|
+
P.Type = TEXT("vector");
|
|
110
|
+
P.bRequired = bRequired;
|
|
111
|
+
P.Description = Desc + TEXT(" Accepts either [x,y,z] or {x,y,z}.");
|
|
112
|
+
P.Aliases = Aliases;
|
|
113
|
+
Out.Add(MoveTemp(P));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static void AddRotatorParam(TArray<FUnrealMCPParamSchema>& Out, const FString& Name, bool bRequired, const FString& Desc, const TArray<FString>& Aliases = {})
|
|
117
|
+
{
|
|
118
|
+
FUnrealMCPParamSchema P;
|
|
119
|
+
P.Name = Name;
|
|
120
|
+
P.Type = TEXT("rotator");
|
|
121
|
+
P.bRequired = bRequired;
|
|
122
|
+
P.Description = Desc + TEXT(" Accepts either [pitch,yaw,roll] or {pitch,yaw,roll}.");
|
|
123
|
+
P.Aliases = Aliases;
|
|
124
|
+
Out.Add(MoveTemp(P));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static void AddEnumParam(
|
|
128
|
+
TArray<FUnrealMCPParamSchema>& Out,
|
|
129
|
+
const FString& Name,
|
|
130
|
+
bool bRequired,
|
|
131
|
+
const FString& Desc,
|
|
132
|
+
const TArray<FString>& EnumValues,
|
|
133
|
+
const TArray<FString>& Aliases = {},
|
|
134
|
+
const TMap<FString, FString>& ValueAliases = {})
|
|
135
|
+
{
|
|
136
|
+
FUnrealMCPParamSchema P;
|
|
137
|
+
P.Name = Name;
|
|
138
|
+
P.Type = TEXT("string");
|
|
139
|
+
P.bRequired = bRequired;
|
|
140
|
+
P.Description = Desc;
|
|
141
|
+
P.Aliases = Aliases;
|
|
142
|
+
P.EnumValues = EnumValues;
|
|
143
|
+
P.ValueAliases = ValueAliases;
|
|
144
|
+
Out.Add(MoveTemp(P));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
static TSharedPtr<FJsonObject> Example(std::initializer_list<TPair<FString, TSharedPtr<FJsonValue>>> Fields)
|
|
148
|
+
{
|
|
149
|
+
TSharedPtr<FJsonObject> Obj = MakeShared<FJsonObject>();
|
|
150
|
+
for (const auto& Pair : Fields)
|
|
151
|
+
{
|
|
152
|
+
Obj->SetField(Pair.Key, Pair.Value);
|
|
153
|
+
}
|
|
154
|
+
return Obj;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static TMap<FString, FUnrealMCPCommandSchema> BuildSchemas()
|
|
158
|
+
{
|
|
159
|
+
TMap<FString, FUnrealMCPCommandSchema> Schemas;
|
|
160
|
+
|
|
161
|
+
{
|
|
162
|
+
FUnrealMCPCommandSchema S;
|
|
163
|
+
S.Command = TEXT("create_blueprint");
|
|
164
|
+
S.Title = TEXT("Create Blueprint");
|
|
165
|
+
S.Description = TEXT("Create a new Blueprint asset.");
|
|
166
|
+
AddStringParam(S.Params, TEXT("name"), true, TEXT("Blueprint asset name."), {TEXT("blueprint_name"), TEXT("assetName"), TEXT("asset_name")});
|
|
167
|
+
AddStringParam(S.Params, TEXT("path"), false, TEXT("Package path (e.g. /Game/Blueprints/). Defaults to /Game/Blueprints/."), {TEXT("packagePath"), TEXT("package_path"), TEXT("blueprint_path")});
|
|
168
|
+
AddStringParam(S.Params, TEXT("parent_class"), false, TEXT("Parent class name (e.g. Actor, Pawn)."), {TEXT("parentClass"), TEXT("parent")});
|
|
169
|
+
S.ExampleParams = Example({
|
|
170
|
+
{TEXT("name"), MakeShared<FJsonValueString>(TEXT("BP_TwoStoryBuilding"))},
|
|
171
|
+
{TEXT("path"), MakeShared<FJsonValueString>(TEXT("/Game/Blueprints/"))},
|
|
172
|
+
{TEXT("parent_class"), MakeShared<FJsonValueString>(TEXT("Actor"))},
|
|
173
|
+
});
|
|
174
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
{
|
|
178
|
+
FUnrealMCPCommandSchema S;
|
|
179
|
+
S.Command = TEXT("create_landscape");
|
|
180
|
+
S.Title = TEXT("Create Landscape");
|
|
181
|
+
S.Description = TEXT("Create a new Landscape actor in the current editor level. Fails if PIE is running.");
|
|
182
|
+
AddStringParam(S.Params, TEXT("name"), true, TEXT("Landscape actor name (must be unique)."));
|
|
183
|
+
AddNumberParam(S.Params, TEXT("componentCountX"), false, TEXT("Number of components in X (default 8)."));
|
|
184
|
+
AddNumberParam(S.Params, TEXT("componentCountY"), false, TEXT("Number of components in Y (default 8)."));
|
|
185
|
+
AddNumberParam(S.Params, TEXT("sectionsPerComponent"), false, TEXT("Sections per component (1 or 2, default 1)."));
|
|
186
|
+
AddNumberParam(S.Params, TEXT("quadsPerSection"), false, TEXT("Quads per section (default 63)."));
|
|
187
|
+
AddVectorParam(S.Params, TEXT("location"), false, TEXT("Center location in cm."));
|
|
188
|
+
AddRotatorParam(S.Params, TEXT("rotation"), false, TEXT("Rotation in degrees."));
|
|
189
|
+
AddVectorParam(S.Params, TEXT("scale"), false, TEXT("Actor scale (default [100,100,100])."));
|
|
190
|
+
AddStringParam(S.Params, TEXT("materialPath"), false, TEXT("Optional landscape material object path."), {TEXT("material"), TEXT("landscapeMaterial")});
|
|
191
|
+
S.ExampleParams = Example({
|
|
192
|
+
{TEXT("name"), MakeShared<FJsonValueString>(TEXT("Landscape_01"))},
|
|
193
|
+
{TEXT("componentCountX"), MakeShared<FJsonValueNumber>(8)},
|
|
194
|
+
{TEXT("componentCountY"), MakeShared<FJsonValueNumber>(8)},
|
|
195
|
+
{TEXT("sectionsPerComponent"), MakeShared<FJsonValueNumber>(1)},
|
|
196
|
+
{TEXT("quadsPerSection"), MakeShared<FJsonValueNumber>(63)},
|
|
197
|
+
{TEXT("location"), MakeShared<FJsonValueArray>(TArray<TSharedPtr<FJsonValue>>{
|
|
198
|
+
MakeShared<FJsonValueNumber>(0), MakeShared<FJsonValueNumber>(0), MakeShared<FJsonValueNumber>(0),
|
|
199
|
+
})},
|
|
200
|
+
});
|
|
201
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
{
|
|
205
|
+
FUnrealMCPCommandSchema S;
|
|
206
|
+
S.Command = TEXT("save_all");
|
|
207
|
+
S.Title = TEXT("Save All");
|
|
208
|
+
S.Description = TEXT("Save all dirty packages (maps + content) without prompting. Fails if PIE is running.");
|
|
209
|
+
S.ExampleParams = Example({});
|
|
210
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
{
|
|
214
|
+
FUnrealMCPCommandSchema S;
|
|
215
|
+
S.Command = TEXT("add_component_to_blueprint");
|
|
216
|
+
S.Title = TEXT("Add Component To Blueprint");
|
|
217
|
+
S.Description = TEXT("Add a component to a Blueprint's SimpleConstructionScript.");
|
|
218
|
+
AddStringParam(S.Params, TEXT("blueprint_name"), true, TEXT("Blueprint asset name."), {TEXT("name"), TEXT("blueprint"), TEXT("blueprintName")});
|
|
219
|
+
AddStringParam(S.Params, TEXT("component_type"), true, TEXT("Component type/class (e.g. StaticMesh, StaticMeshComponent, PointLightComponent)."), {TEXT("type"), TEXT("component_class"), TEXT("componentClass")});
|
|
220
|
+
AddStringParam(S.Params, TEXT("component_name"), true, TEXT("New component name."), {TEXT("name"), TEXT("componentName")});
|
|
221
|
+
AddStringParam(S.Params, TEXT("parent_component_name"), false, TEXT("Optional parent component name."), {TEXT("parentComponentName"), TEXT("parent_component")});
|
|
222
|
+
AddVectorParam(S.Params, TEXT("location"), false, TEXT("Relative location."), {TEXT("relative_location"), TEXT("RelativeLocation")});
|
|
223
|
+
AddRotatorParam(S.Params, TEXT("rotation"), false, TEXT("Relative rotation."), {TEXT("relative_rotation"), TEXT("RelativeRotation")});
|
|
224
|
+
AddVectorParam(S.Params, TEXT("scale"), false, TEXT("Relative scale."), {TEXT("relative_scale"), TEXT("RelativeScale3D")});
|
|
225
|
+
S.ExampleParams = Example({
|
|
226
|
+
{TEXT("blueprint_name"), MakeShared<FJsonValueString>(TEXT("BP_TwoStoryBuilding"))},
|
|
227
|
+
{TEXT("component_type"), MakeShared<FJsonValueString>(TEXT("StaticMeshComponent"))},
|
|
228
|
+
{TEXT("component_name"), MakeShared<FJsonValueString>(TEXT("Wall_01"))},
|
|
229
|
+
{TEXT("location"), MakeShared<FJsonValueArray>(TArray<TSharedPtr<FJsonValue>>{
|
|
230
|
+
MakeShared<FJsonValueNumber>(0), MakeShared<FJsonValueNumber>(0), MakeShared<FJsonValueNumber>(0),
|
|
231
|
+
})},
|
|
232
|
+
});
|
|
233
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
{
|
|
237
|
+
FUnrealMCPCommandSchema S;
|
|
238
|
+
S.Command = TEXT("set_component_property");
|
|
239
|
+
S.Title = TEXT("Set Component Property (Blueprint)");
|
|
240
|
+
S.Description = TEXT("Set a property on a Blueprint's component template (SCS).");
|
|
241
|
+
AddStringParam(S.Params, TEXT("blueprint_name"), true, TEXT("Blueprint asset name or path."), {TEXT("blueprint"), TEXT("name"), TEXT("blueprintPath")});
|
|
242
|
+
AddStringParam(S.Params, TEXT("component_name"), true, TEXT("Component name in the blueprint."), {TEXT("component"), TEXT("name"), TEXT("componentName")});
|
|
243
|
+
AddStringParam(S.Params, TEXT("property_name"), true, TEXT("Property name to set."), {TEXT("property"), TEXT("prop"), TEXT("field"), TEXT("propertyName")});
|
|
244
|
+
AddAnyParam(S.Params, TEXT("property_value"), true, TEXT("JSON value for the property."), {TEXT("value"), TEXT("propertyValue")});
|
|
245
|
+
S.ExampleParams = Example({
|
|
246
|
+
{TEXT("blueprint_name"), MakeShared<FJsonValueString>(TEXT("BP_TwoStoryBuilding"))},
|
|
247
|
+
{TEXT("component_name"), MakeShared<FJsonValueString>(TEXT("Wall_01"))},
|
|
248
|
+
{TEXT("property_name"), MakeShared<FJsonValueString>(TEXT("RelativeScale3D"))},
|
|
249
|
+
{TEXT("property_value"), MakeShared<FJsonValueArray>(TArray<TSharedPtr<FJsonValue>>{
|
|
250
|
+
MakeShared<FJsonValueNumber>(35), MakeShared<FJsonValueNumber>(25), MakeShared<FJsonValueNumber>(0.2),
|
|
251
|
+
})},
|
|
252
|
+
});
|
|
253
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
{
|
|
257
|
+
FUnrealMCPCommandSchema S;
|
|
258
|
+
S.Command = TEXT("compile_blueprint");
|
|
259
|
+
S.Title = TEXT("Compile Blueprint");
|
|
260
|
+
S.Description = TEXT("Compile a single Blueprint.");
|
|
261
|
+
AddStringParam(S.Params, TEXT("blueprint_name"), true, TEXT("Blueprint asset name or path."), {TEXT("blueprint"), TEXT("name"), TEXT("blueprintPath")});
|
|
262
|
+
S.ExampleParams = Example({
|
|
263
|
+
{TEXT("blueprint_name"), MakeShared<FJsonValueString>(TEXT("BP_TwoStoryBuilding"))},
|
|
264
|
+
});
|
|
265
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
{
|
|
269
|
+
FUnrealMCPCommandSchema S;
|
|
270
|
+
S.Command = TEXT("compile_blueprints_all");
|
|
271
|
+
S.Title = TEXT("Compile Blueprints (All)");
|
|
272
|
+
S.Description = TEXT("Compile all Blueprints in the project (bounded).");
|
|
273
|
+
AddNumberParam(S.Params, TEXT("limit"), false, TEXT("Optional max number of blueprints to compile."));
|
|
274
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
{
|
|
278
|
+
FUnrealMCPCommandSchema S;
|
|
279
|
+
S.Command = TEXT("add_blueprint_variable");
|
|
280
|
+
S.Title = TEXT("Add Blueprint Variable");
|
|
281
|
+
S.Description = TEXT("Add a variable to a Blueprint.");
|
|
282
|
+
AddStringParam(S.Params, TEXT("blueprint_name"), true, TEXT("Blueprint asset name."), {TEXT("name"), TEXT("blueprint"), TEXT("blueprintName"), TEXT("blueprintPath")});
|
|
283
|
+
AddStringParam(S.Params, TEXT("variable_name"), true, TEXT("Variable name."), {TEXT("name"), TEXT("var_name"), TEXT("varName")});
|
|
284
|
+
AddStringParam(S.Params, TEXT("variable_type"), true, TEXT("Variable type (e.g. float, int, bool, vector, string)."), {TEXT("type"), TEXT("var_type"), TEXT("varType")});
|
|
285
|
+
AddStringParam(S.Params, TEXT("default_value"), false, TEXT("Optional default value (string form)."), {TEXT("defaultValue"), TEXT("default")});
|
|
286
|
+
S.ExampleParams = Example({
|
|
287
|
+
{TEXT("blueprint_name"), MakeShared<FJsonValueString>(TEXT("BP_TwoStoryBuilding"))},
|
|
288
|
+
{TEXT("variable_name"), MakeShared<FJsonValueString>(TEXT("WidthCm"))},
|
|
289
|
+
{TEXT("variable_type"), MakeShared<FJsonValueString>(TEXT("float"))},
|
|
290
|
+
{TEXT("default_value"), MakeShared<FJsonValueString>(TEXT("500"))},
|
|
291
|
+
});
|
|
292
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
{
|
|
296
|
+
FUnrealMCPCommandSchema S;
|
|
297
|
+
S.Command = TEXT("spawn_blueprint_actor");
|
|
298
|
+
S.Title = TEXT("Spawn Blueprint Actor");
|
|
299
|
+
S.Description = TEXT("Spawn an actor from a Blueprint/Class into the editor world.");
|
|
300
|
+
AddStringParam(S.Params, TEXT("blueprint_name"), true, TEXT("Blueprint name or object path."), {TEXT("blueprint"), TEXT("blueprint_path"), TEXT("objectPath"), TEXT("object_path"), TEXT("objectPath")});
|
|
301
|
+
AddStringParam(S.Params, TEXT("actor_name"), true, TEXT("Desired actor name base."), {TEXT("name")});
|
|
302
|
+
AddVectorParam(S.Params, TEXT("location"), false, TEXT("World location."));
|
|
303
|
+
AddRotatorParam(S.Params, TEXT("rotation"), false, TEXT("World rotation."));
|
|
304
|
+
AddVectorParam(S.Params, TEXT("scale"), false, TEXT("World scale."));
|
|
305
|
+
AddBoolParam(S.Params, TEXT("include_details"), false, TEXT("If true, include detailed component/property info (larger response)."), {TEXT("detailed"), TEXT("includeProperties")});
|
|
306
|
+
S.ExampleParams = Example({
|
|
307
|
+
{TEXT("blueprint_name"), MakeShared<FJsonValueString>(TEXT("/Game/Blueprints/BP_TwoStoryBuilding.BP_TwoStoryBuilding"))},
|
|
308
|
+
{TEXT("actor_name"), MakeShared<FJsonValueString>(TEXT("TwoStoryBuilding_01"))},
|
|
309
|
+
{TEXT("location"), MakeShared<FJsonValueArray>(TArray<TSharedPtr<FJsonValue>>{
|
|
310
|
+
MakeShared<FJsonValueNumber>(0), MakeShared<FJsonValueNumber>(0), MakeShared<FJsonValueNumber>(0),
|
|
311
|
+
})},
|
|
312
|
+
{TEXT("include_details"), MakeShared<FJsonValueBoolean>(false)},
|
|
313
|
+
});
|
|
314
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// NOTE: Schemas for other commands are intentionally minimal; they still help with required keys & common aliases.
|
|
318
|
+
const auto AddSimpleCommand = [&](const FString& Command, const FString& Title, const FString& Desc, const TArray<FUnrealMCPParamSchema>& Params, const TSharedPtr<FJsonObject>& ExampleParams) {
|
|
319
|
+
FUnrealMCPCommandSchema S;
|
|
320
|
+
S.Command = Command;
|
|
321
|
+
S.Title = Title;
|
|
322
|
+
S.Description = Desc;
|
|
323
|
+
S.Params = Params;
|
|
324
|
+
S.ExampleParams = ExampleParams;
|
|
325
|
+
Schemas.Add(S.Command, MoveTemp(S));
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
{
|
|
329
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
330
|
+
AddStringParam(P, TEXT("pattern"), true, TEXT("Fuzzy name/pattern to match."), {TEXT("name"), TEXT("query")});
|
|
331
|
+
AddNumberParam(P, TEXT("limit"), false, TEXT("Max results (default 25)."));
|
|
332
|
+
AddSimpleCommand(TEXT("find_actors_by_name"), TEXT("Find Actors By Name"), TEXT("Find actors by name substring."), P, Example({
|
|
333
|
+
{TEXT("pattern"), MakeShared<FJsonValueString>(TEXT("BP_"))},
|
|
334
|
+
{TEXT("limit"), MakeShared<FJsonValueNumber>(25)},
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
{
|
|
339
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
340
|
+
AddStringParam(P, TEXT("type"), true, TEXT("Actor type/class name (e.g. StaticMeshActor, PointLight)."), {TEXT("class"), TEXT("actor_type"), TEXT("actorType")});
|
|
341
|
+
AddStringParam(P, TEXT("name"), true, TEXT("Actor name base."), {TEXT("actor_name"), TEXT("actorName")});
|
|
342
|
+
AddVectorParam(P, TEXT("location"), false, TEXT("World location."));
|
|
343
|
+
AddRotatorParam(P, TEXT("rotation"), false, TEXT("World rotation."));
|
|
344
|
+
AddVectorParam(P, TEXT("scale"), false, TEXT("World scale."));
|
|
345
|
+
AddStringParam(P, TEXT("static_mesh_path"), false, TEXT("Static mesh object path (for StaticMeshActor)."), {TEXT("staticMeshPath"), TEXT("static_mesh")});
|
|
346
|
+
AddSimpleCommand(TEXT("spawn_actor"), TEXT("Spawn Actor"), TEXT("Spawn an actor in the editor world."), P, Example({
|
|
347
|
+
{TEXT("type"), MakeShared<FJsonValueString>(TEXT("StaticMeshActor"))},
|
|
348
|
+
{TEXT("name"), MakeShared<FJsonValueString>(TEXT("MCP_Cube_01"))},
|
|
349
|
+
{TEXT("static_mesh_path"), MakeShared<FJsonValueString>(TEXT("/Engine/BasicShapes/Cube.Cube"))},
|
|
350
|
+
}));
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
{
|
|
354
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
355
|
+
AddStringParam(P, TEXT("actor_name"), true, TEXT("Actor name to modify."), {TEXT("name"), TEXT("actor")});
|
|
356
|
+
AddStringParam(P, TEXT("property_name"), true, TEXT("Property name or property path (best-effort)."), {TEXT("property"), TEXT("prop"), TEXT("field")});
|
|
357
|
+
AddAnyParam(P, TEXT("property_value"), true, TEXT("Property value (JSON; type depends on property)."), {TEXT("value"), TEXT("propertyValue")});
|
|
358
|
+
AddSimpleCommand(TEXT("set_actor_property"), TEXT("Set Actor Property"), TEXT("Set an editable property on an actor."), P, nullptr);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
{
|
|
362
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
363
|
+
AddStringParam(P, TEXT("filepath"), false, TEXT("Output path. If omitted, defaults to <Project>/Saved/Screenshots/Flockbay/."), {TEXT("path"), TEXT("file_path")});
|
|
364
|
+
AddStringParam(P, TEXT("filename"), false, TEXT("Optional file name (auto-generated if omitted)."));
|
|
365
|
+
AddSimpleCommand(TEXT("take_screenshot"), TEXT("Take Screenshot"), TEXT("Capture a screenshot from the editor or PIE."), P, nullptr);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
{
|
|
369
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
370
|
+
AddStringParam(P, TEXT("query"), false, TEXT("Fuzzy search string."));
|
|
371
|
+
AddStringParam(P, TEXT("root"), false, TEXT("Root path (default /Game/)."));
|
|
372
|
+
AddNumberParam(P, TEXT("limit"), false, TEXT("Max results."));
|
|
373
|
+
AddSimpleCommand(TEXT("search_assets"), TEXT("Search Assets"), TEXT("Search assets via AssetRegistry."), P, nullptr);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
{
|
|
377
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
378
|
+
AddStringParam(P, TEXT("object_path"), true, TEXT("Asset object path."), {TEXT("objectPath"), TEXT("asset_path"), TEXT("assetPath")});
|
|
379
|
+
AddSimpleCommand(TEXT("get_asset_info"), TEXT("Get Asset Info"), TEXT("Get basic info for an asset."), P, nullptr);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
{
|
|
383
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
384
|
+
AddStringParam(P, TEXT("object_path"), true, TEXT("Asset object path to place (e.g. /Game/.../BP_X.BP_X)."), {TEXT("objectPath"), TEXT("asset_path"), TEXT("assetPath")});
|
|
385
|
+
AddVectorParam(P, TEXT("location"), false, TEXT("World location (default 0,0,0)."));
|
|
386
|
+
AddRotatorParam(P, TEXT("rotation"), false, TEXT("World rotation (default 0,0,0)."));
|
|
387
|
+
AddVectorParam(P, TEXT("scale"), false, TEXT("World scale (default 1,1,1)."));
|
|
388
|
+
AddStringParam(P, TEXT("actor_name"), false, TEXT("Optional actor name base."), {TEXT("name")});
|
|
389
|
+
AddSimpleCommand(TEXT("place_asset"), TEXT("Place Asset"), TEXT("Place an asset (Blueprint, StaticMesh, etc.) into the level."), P, nullptr);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
{
|
|
393
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
394
|
+
AddStringParam(P, TEXT("blueprint_name"), true, TEXT("Blueprint asset name."), {TEXT("name"), TEXT("blueprint")});
|
|
395
|
+
AddStringParam(P, TEXT("component_name"), true, TEXT("Component name in blueprint."), {TEXT("name"), TEXT("component")});
|
|
396
|
+
AddStringParam(P, TEXT("mesh_path"), true, TEXT("Static mesh object path."), {TEXT("static_mesh_path"), TEXT("staticMeshPath"), TEXT("static_mesh")});
|
|
397
|
+
AddSimpleCommand(TEXT("set_static_mesh_properties"), TEXT("Set Static Mesh Properties"), TEXT("Assign a static mesh to a StaticMeshComponent in a Blueprint."), P, Example({
|
|
398
|
+
{TEXT("blueprint_name"), MakeShared<FJsonValueString>(TEXT("BP_TwoStoryBuilding"))},
|
|
399
|
+
{TEXT("component_name"), MakeShared<FJsonValueString>(TEXT("Wall_01"))},
|
|
400
|
+
{TEXT("mesh_path"), MakeShared<FJsonValueString>(TEXT("/Engine/BasicShapes/Cube.Cube"))},
|
|
401
|
+
}));
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
{
|
|
405
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
406
|
+
AddStringParam(P, TEXT("blueprint_name"), true, TEXT("Blueprint asset name."), {TEXT("name"), TEXT("blueprint")});
|
|
407
|
+
AddStringParam(P, TEXT("event_name"), true, TEXT("Event function name (e.g. UserConstructionScript)."), {TEXT("name"), TEXT("event")});
|
|
408
|
+
AddVectorParam(P, TEXT("node_position"), false, TEXT("Node position in the graph."));
|
|
409
|
+
AddSimpleCommand(TEXT("add_blueprint_event_node"), TEXT("Add Blueprint Event Node"), TEXT("Add or reuse an event node in the EventGraph."), P, Example({
|
|
410
|
+
{TEXT("blueprint_name"), MakeShared<FJsonValueString>(TEXT("BP_TwoStoryBuilding"))},
|
|
411
|
+
{TEXT("event_name"), MakeShared<FJsonValueString>(TEXT("UserConstructionScript"))},
|
|
412
|
+
}));
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
{
|
|
416
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
417
|
+
AddStringParam(P, TEXT("blueprint_name"), true, TEXT("Blueprint asset name."), {TEXT("name"), TEXT("blueprint")});
|
|
418
|
+
AddStringParam(P, TEXT("function_name"), true, TEXT("Function name (e.g. MakeVector)."), {TEXT("name"), TEXT("function")});
|
|
419
|
+
AddStringParam(P, TEXT("target"), false, TEXT("Target class name for the function (e.g. KismetMathLibrary, SceneComponent)."));
|
|
420
|
+
AddStringParam(P, TEXT("function_owner_path"), false, TEXT("Optional explicit class path (/Script/Engine.KismetMathLibrary). Overrides target."), {TEXT("owner_path"), TEXT("ownerClassPath"), TEXT("owner_class_path")});
|
|
421
|
+
AddVectorParam(P, TEXT("node_position"), false, TEXT("Node position in the graph."));
|
|
422
|
+
AddSimpleCommand(TEXT("add_blueprint_function_node"), TEXT("Add Blueprint Function Node"), TEXT("Add a function call node to the EventGraph."), P, nullptr);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
{
|
|
426
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
427
|
+
AddStringParam(P, TEXT("query"), true, TEXT("Substring to search for (function name/display name)."), {TEXT("q"), TEXT("name")});
|
|
428
|
+
AddStringParam(P, TEXT("target"), false, TEXT("Optional target class name (limits the search)."), {TEXT("class"), TEXT("owner")});
|
|
429
|
+
AddNumberParam(P, TEXT("limit"), false, TEXT("Max results (default 25)."));
|
|
430
|
+
AddSimpleCommand(TEXT("search_blueprint_functions"), TEXT("Search Blueprint Functions"), TEXT("Search for Blueprint-callable functions and return candidates."), P, Example({
|
|
431
|
+
{TEXT("query"), MakeShared<FJsonValueString>(TEXT("MakeVector"))},
|
|
432
|
+
{TEXT("target"), MakeShared<FJsonValueString>(TEXT("KismetMathLibrary"))},
|
|
433
|
+
}));
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
{
|
|
437
|
+
TArray<FUnrealMCPParamSchema> P;
|
|
438
|
+
AddStringParam(P, TEXT("function_name"), true, TEXT("Function name to resolve."), {TEXT("name"), TEXT("query")});
|
|
439
|
+
AddStringParam(P, TEXT("target"), false, TEXT("Optional target class constraint."), {TEXT("class"), TEXT("owner")});
|
|
440
|
+
AddSimpleCommand(TEXT("resolve_blueprint_function"), TEXT("Resolve Blueprint Function"), TEXT("Resolve a function to an explicit owner class path usable for add_blueprint_function_node."), P, Example({
|
|
441
|
+
{TEXT("function_name"), MakeShared<FJsonValueString>(TEXT("MakeVector"))},
|
|
442
|
+
{TEXT("target"), MakeShared<FJsonValueString>(TEXT("KismetMathLibrary"))},
|
|
443
|
+
}));
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return Schemas;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
static const TMap<FString, FUnrealMCPCommandSchema>& SchemaMap()
|
|
450
|
+
{
|
|
451
|
+
static const TMap<FString, FUnrealMCPCommandSchema> Schemas = BuildSchemas();
|
|
452
|
+
return Schemas;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
int32 FUnrealMCPCommandSchemaRegistry::SchemaVersion()
|
|
456
|
+
{
|
|
457
|
+
return kUnrealMcpSchemaVersion;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const FUnrealMCPCommandSchema* FUnrealMCPCommandSchemaRegistry::FindSchema(const FString& CommandType)
|
|
461
|
+
{
|
|
462
|
+
const auto& Map = SchemaMap();
|
|
463
|
+
if (const FUnrealMCPCommandSchema* Found = Map.Find(CommandType))
|
|
464
|
+
{
|
|
465
|
+
return Found;
|
|
466
|
+
}
|
|
467
|
+
return nullptr;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
TArray<FString> FUnrealMCPCommandSchemaRegistry::GetSupportedCommands()
|
|
471
|
+
{
|
|
472
|
+
// Keep explicit + stable ordering.
|
|
473
|
+
TArray<FString> Commands;
|
|
474
|
+
Commands.Add(TEXT("ping"));
|
|
475
|
+
Commands.Add(TEXT("get_plugin_info"));
|
|
476
|
+
Commands.Add(TEXT("list_capabilities"));
|
|
477
|
+
Commands.Add(TEXT("get_command_schema"));
|
|
478
|
+
|
|
479
|
+
// Editor
|
|
480
|
+
Commands.Add(TEXT("get_actors_in_level"));
|
|
481
|
+
Commands.Add(TEXT("find_actors_by_name"));
|
|
482
|
+
Commands.Add(TEXT("spawn_actor"));
|
|
483
|
+
Commands.Add(TEXT("create_actor"));
|
|
484
|
+
Commands.Add(TEXT("create_landscape"));
|
|
485
|
+
Commands.Add(TEXT("delete_actor"));
|
|
486
|
+
Commands.Add(TEXT("set_actor_transform"));
|
|
487
|
+
Commands.Add(TEXT("get_actor_properties"));
|
|
488
|
+
Commands.Add(TEXT("set_actor_property"));
|
|
489
|
+
Commands.Add(TEXT("spawn_blueprint_actor"));
|
|
490
|
+
Commands.Add(TEXT("focus_viewport"));
|
|
491
|
+
Commands.Add(TEXT("take_screenshot"));
|
|
492
|
+
Commands.Add(TEXT("save_all"));
|
|
493
|
+
Commands.Add(TEXT("get_play_in_editor_status"));
|
|
494
|
+
Commands.Add(TEXT("play_in_editor"));
|
|
495
|
+
Commands.Add(TEXT("play_in_editor_windowed"));
|
|
496
|
+
Commands.Add(TEXT("stop_play_in_editor"));
|
|
497
|
+
Commands.Add(TEXT("search_assets"));
|
|
498
|
+
Commands.Add(TEXT("get_asset_info"));
|
|
499
|
+
Commands.Add(TEXT("list_asset_packs"));
|
|
500
|
+
Commands.Add(TEXT("place_asset"));
|
|
501
|
+
Commands.Add(TEXT("map_check"));
|
|
502
|
+
Commands.Add(TEXT("get_editor_context"));
|
|
503
|
+
Commands.Add(TEXT("get_player_context"));
|
|
504
|
+
Commands.Add(TEXT("raycast_from_camera"));
|
|
505
|
+
Commands.Add(TEXT("raycast_down"));
|
|
506
|
+
Commands.Add(TEXT("get_actor_transform"));
|
|
507
|
+
Commands.Add(TEXT("get_actor_bounds"));
|
|
508
|
+
|
|
509
|
+
// Blueprint asset + SCS edits
|
|
510
|
+
Commands.Add(TEXT("create_blueprint"));
|
|
511
|
+
Commands.Add(TEXT("add_component_to_blueprint"));
|
|
512
|
+
Commands.Add(TEXT("set_component_property"));
|
|
513
|
+
Commands.Add(TEXT("set_physics_properties"));
|
|
514
|
+
Commands.Add(TEXT("compile_blueprint"));
|
|
515
|
+
Commands.Add(TEXT("compile_blueprints_all"));
|
|
516
|
+
Commands.Add(TEXT("set_blueprint_property"));
|
|
517
|
+
Commands.Add(TEXT("set_static_mesh_properties"));
|
|
518
|
+
Commands.Add(TEXT("set_pawn_properties"));
|
|
519
|
+
|
|
520
|
+
// Blueprint graph/node edits
|
|
521
|
+
Commands.Add(TEXT("connect_blueprint_nodes"));
|
|
522
|
+
Commands.Add(TEXT("add_blueprint_get_self_component_reference"));
|
|
523
|
+
Commands.Add(TEXT("add_blueprint_self_reference"));
|
|
524
|
+
Commands.Add(TEXT("find_blueprint_nodes"));
|
|
525
|
+
Commands.Add(TEXT("add_blueprint_event_node"));
|
|
526
|
+
Commands.Add(TEXT("add_blueprint_input_action_node"));
|
|
527
|
+
Commands.Add(TEXT("add_blueprint_function_node"));
|
|
528
|
+
Commands.Add(TEXT("add_blueprint_get_component_node"));
|
|
529
|
+
Commands.Add(TEXT("add_blueprint_variable"));
|
|
530
|
+
|
|
531
|
+
// Function discovery helpers
|
|
532
|
+
Commands.Add(TEXT("search_blueprint_functions"));
|
|
533
|
+
Commands.Add(TEXT("resolve_blueprint_function"));
|
|
534
|
+
|
|
535
|
+
// Project
|
|
536
|
+
Commands.Add(TEXT("create_input_mapping"));
|
|
537
|
+
|
|
538
|
+
// UMG
|
|
539
|
+
Commands.Add(TEXT("create_umg_widget_blueprint"));
|
|
540
|
+
Commands.Add(TEXT("add_text_block_to_widget"));
|
|
541
|
+
Commands.Add(TEXT("add_button_to_widget"));
|
|
542
|
+
Commands.Add(TEXT("bind_widget_event"));
|
|
543
|
+
Commands.Add(TEXT("set_text_block_binding"));
|
|
544
|
+
Commands.Add(TEXT("add_widget_to_viewport"));
|
|
545
|
+
|
|
546
|
+
return Commands;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
static bool HasKey(const TSharedPtr<FJsonObject>& Obj, const FString& Key)
|
|
550
|
+
{
|
|
551
|
+
return Obj.IsValid() && Obj->HasField(Key);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
static FString JsonTypeName(const TSharedPtr<FJsonValue>& V)
|
|
555
|
+
{
|
|
556
|
+
if (!V.IsValid()) return TEXT("null");
|
|
557
|
+
switch (V->Type)
|
|
558
|
+
{
|
|
559
|
+
case EJson::None: return TEXT("null");
|
|
560
|
+
case EJson::Null: return TEXT("null");
|
|
561
|
+
case EJson::String: return TEXT("string");
|
|
562
|
+
case EJson::Number: return TEXT("number");
|
|
563
|
+
case EJson::Boolean: return TEXT("boolean");
|
|
564
|
+
case EJson::Array: return TEXT("array");
|
|
565
|
+
case EJson::Object: return TEXT("object");
|
|
566
|
+
default: return TEXT("unknown");
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
static bool TryGetWithAliases(const TSharedPtr<FJsonObject>& In, const FString& Canonical, const TArray<FString>& Aliases, TSharedPtr<FJsonValue>& OutValue, FString& OutUsedKey)
|
|
571
|
+
{
|
|
572
|
+
if (!In.IsValid()) return false;
|
|
573
|
+
OutValue = In->TryGetField(Canonical);
|
|
574
|
+
if (OutValue.IsValid())
|
|
575
|
+
{
|
|
576
|
+
OutUsedKey = Canonical;
|
|
577
|
+
return true;
|
|
578
|
+
}
|
|
579
|
+
for (const FString& A : Aliases)
|
|
580
|
+
{
|
|
581
|
+
if (A.IsEmpty()) continue;
|
|
582
|
+
OutValue = In->TryGetField(A);
|
|
583
|
+
if (OutValue.IsValid())
|
|
584
|
+
{
|
|
585
|
+
OutUsedKey = A;
|
|
586
|
+
return true;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
bool FUnrealMCPCommandSchemaRegistry::NormalizeParams(
|
|
593
|
+
const FString& CommandType,
|
|
594
|
+
const TSharedPtr<FJsonObject>& InParams,
|
|
595
|
+
TSharedPtr<FJsonObject>& OutParams,
|
|
596
|
+
TSharedPtr<FJsonObject>& OutError)
|
|
597
|
+
{
|
|
598
|
+
OutError.Reset();
|
|
599
|
+
OutParams = InParams.IsValid() ? MakeShared<FJsonObject>(*InParams) : MakeShared<FJsonObject>();
|
|
600
|
+
|
|
601
|
+
const FUnrealMCPCommandSchema* Schema = FindSchema(CommandType);
|
|
602
|
+
if (!Schema)
|
|
603
|
+
{
|
|
604
|
+
return true;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
TArray<FString> Missing;
|
|
608
|
+
TSharedPtr<FJsonObject> Normalized = MakeShared<FJsonObject>(*OutParams);
|
|
609
|
+
|
|
610
|
+
for (const FUnrealMCPParamSchema& P : Schema->Params)
|
|
611
|
+
{
|
|
612
|
+
TSharedPtr<FJsonValue> Value;
|
|
613
|
+
FString UsedKey;
|
|
614
|
+
const bool bFound = TryGetWithAliases(OutParams, P.Name, P.Aliases, Value, UsedKey);
|
|
615
|
+
if (!bFound)
|
|
616
|
+
{
|
|
617
|
+
if (P.bRequired) Missing.Add(P.Name);
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Apply value aliases for enums (e.g. anchor="player" -> "player_camera").
|
|
622
|
+
if (P.ValueAliases.Num() > 0 && Value.IsValid() && Value->Type == EJson::String)
|
|
623
|
+
{
|
|
624
|
+
const FString InValue = Value->AsString();
|
|
625
|
+
if (const FString* Mapped = P.ValueAliases.Find(InValue))
|
|
626
|
+
{
|
|
627
|
+
Value = MakeShared<FJsonValueString>(*Mapped);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
Normalized->SetField(P.Name, Value);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
OutParams = Normalized;
|
|
635
|
+
|
|
636
|
+
if (Missing.Num() > 0)
|
|
637
|
+
{
|
|
638
|
+
TSharedPtr<FJsonObject> Details = MakeShared<FJsonObject>();
|
|
639
|
+
Details->SetStringField(TEXT("kind"), TEXT("missing_params"));
|
|
640
|
+
Details->SetStringField(TEXT("command"), CommandType);
|
|
641
|
+
Details->SetNumberField(TEXT("schemaVersion"), kUnrealMcpSchemaVersion);
|
|
642
|
+
|
|
643
|
+
TArray<TSharedPtr<FJsonValue>> MissingArr;
|
|
644
|
+
for (const FString& M : Missing) MissingArr.Add(MakeShared<FJsonValueString>(M));
|
|
645
|
+
Details->SetArrayField(TEXT("missing"), MissingArr);
|
|
646
|
+
|
|
647
|
+
TArray<TSharedPtr<FJsonValue>> RequiredArr;
|
|
648
|
+
for (const FUnrealMCPParamSchema& P : Schema->Params)
|
|
649
|
+
{
|
|
650
|
+
if (P.bRequired) RequiredArr.Add(MakeShared<FJsonValueString>(P.Name));
|
|
651
|
+
}
|
|
652
|
+
Details->SetArrayField(TEXT("required"), RequiredArr);
|
|
653
|
+
|
|
654
|
+
TArray<TSharedPtr<FJsonValue>> ProvidedArr;
|
|
655
|
+
for (const auto& Pair : OutParams->Values) ProvidedArr.Add(MakeShared<FJsonValueString>(Pair.Key));
|
|
656
|
+
Details->SetArrayField(TEXT("provided"), ProvidedArr);
|
|
657
|
+
|
|
658
|
+
if (Schema->ExampleParams.IsValid())
|
|
659
|
+
{
|
|
660
|
+
TSharedPtr<FJsonObject> ExampleCall = MakeShared<FJsonObject>();
|
|
661
|
+
ExampleCall->SetStringField(TEXT("type"), CommandType);
|
|
662
|
+
ExampleCall->SetObjectField(TEXT("params"), Schema->ExampleParams);
|
|
663
|
+
Details->SetObjectField(TEXT("exampleCall"), ExampleCall);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
OutError = FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Missing required parameter(s): %s"), *FString::Join(Missing, TEXT(", "))));
|
|
667
|
+
OutError->SetObjectField(TEXT("details"), Details);
|
|
668
|
+
return false;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
return true;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
TSharedPtr<FJsonObject> FUnrealMCPCommandSchemaRegistry::GetSchemaResponse(const FString& CommandTypeOrEmpty)
|
|
675
|
+
{
|
|
676
|
+
TSharedPtr<FJsonObject> Out = MakeShared<FJsonObject>();
|
|
677
|
+
Out->SetNumberField(TEXT("schemaVersion"), kUnrealMcpSchemaVersion);
|
|
678
|
+
|
|
679
|
+
if (!CommandTypeOrEmpty.IsEmpty())
|
|
680
|
+
{
|
|
681
|
+
const FUnrealMCPCommandSchema* Schema = FindSchema(CommandTypeOrEmpty);
|
|
682
|
+
if (!Schema)
|
|
683
|
+
{
|
|
684
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("No schema found for command: %s"), *CommandTypeOrEmpty));
|
|
685
|
+
}
|
|
686
|
+
Out->SetObjectField(TEXT("schema"), Schema->ToJson());
|
|
687
|
+
return Out;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
TArray<TSharedPtr<FJsonValue>> SchemasArr;
|
|
691
|
+
for (const auto& Pair : SchemaMap())
|
|
692
|
+
{
|
|
693
|
+
SchemasArr.Add(MakeShared<FJsonValueObject>(Pair.Value.ToJson()));
|
|
694
|
+
}
|
|
695
|
+
Out->SetArrayField(TEXT("schemas"), SchemasArr);
|
|
696
|
+
return Out;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
TSharedPtr<FJsonObject> FUnrealMCPCommandSchemaRegistry::GetCapabilitiesResponse()
|
|
700
|
+
{
|
|
701
|
+
TSharedPtr<FJsonObject> Out = MakeShared<FJsonObject>();
|
|
702
|
+
Out->SetNumberField(TEXT("schemaVersion"), kUnrealMcpSchemaVersion);
|
|
703
|
+
|
|
704
|
+
// Plugin descriptor (best-effort).
|
|
705
|
+
if (TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin(TEXT("UnrealMCP")))
|
|
706
|
+
{
|
|
707
|
+
const FPluginDescriptor& Descriptor = Plugin->GetDescriptor();
|
|
708
|
+
Out->SetStringField(TEXT("pluginName"), Plugin->GetName());
|
|
709
|
+
Out->SetStringField(TEXT("baseDir"), Plugin->GetBaseDir());
|
|
710
|
+
Out->SetStringField(TEXT("versionName"), Descriptor.VersionName);
|
|
711
|
+
Out->SetNumberField(TEXT("version"), Descriptor.Version);
|
|
712
|
+
Out->SetBoolField(TEXT("installed"), Descriptor.bInstalled);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
TArray<TSharedPtr<FJsonValue>> Commands;
|
|
716
|
+
for (const FString& Cmd : GetSupportedCommands())
|
|
717
|
+
{
|
|
718
|
+
Commands.Add(MakeShared<FJsonValueString>(Cmd));
|
|
719
|
+
}
|
|
720
|
+
Out->SetArrayField(TEXT("commands"), Commands);
|
|
721
|
+
|
|
722
|
+
TSharedPtr<FJsonObject> Caps = MakeShared<FJsonObject>();
|
|
723
|
+
Caps->SetBoolField(TEXT("paramAliases"), true);
|
|
724
|
+
Caps->SetBoolField(TEXT("schemaDiscovery"), true);
|
|
725
|
+
Caps->SetBoolField(TEXT("vectorObjectInput"), true);
|
|
726
|
+
Caps->SetBoolField(TEXT("rotatorObjectInput"), true);
|
|
727
|
+
Caps->SetBoolField(TEXT("functionDiscovery"), true);
|
|
728
|
+
Out->SetObjectField(TEXT("capabilities"), Caps);
|
|
729
|
+
|
|
730
|
+
return Out;
|
|
731
|
+
}
|