ue-mcp 1.2.1 → 1.2.2

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 (54) hide show
  1. package/dist/context-cli.js +16 -16
  2. package/dist/engine-observer.js +68 -68
  3. package/dist/flow/guard.d.ts +26 -37
  4. package/dist/flow/guard.js +40 -25
  5. package/dist/flow/guard.js.map +1 -1
  6. package/dist/flow/guarded-bridge.d.ts +0 -10
  7. package/dist/flow/guarded-bridge.js +18 -23
  8. package/dist/flow/guarded-bridge.js.map +1 -1
  9. package/dist/flow/schema.d.ts +276 -16
  10. package/dist/flow/task-guards.d.ts +1 -1
  11. package/dist/flow/task-guards.js +44 -68
  12. package/dist/flow/task-guards.js.map +1 -1
  13. package/dist/instructions.js +130 -130
  14. package/dist/plugin-cli.js +299 -299
  15. package/dist/tool-counts.json +2 -2
  16. package/package.json +2 -2
  17. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.cpp +76 -76
  18. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.h +27 -27
  19. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.cpp +128 -128
  20. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.h +63 -63
  21. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +230 -230
  22. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +323 -323
  23. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +20 -20
  24. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers_Nested.cpp +537 -537
  25. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.h +77 -77
  26. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +353 -353
  27. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +18 -18
  28. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_InputRuntime.cpp +246 -246
  29. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +597 -597
  30. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +51 -51
  31. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +878 -878
  32. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +449 -449
  33. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Function.cpp +275 -275
  34. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Graph.cpp +551 -551
  35. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +531 -531
  36. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.h +28 -28
  37. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +677 -677
  38. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +822 -822
  39. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +22 -22
  40. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +218 -218
  41. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.h +17 -17
  42. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.cpp +46 -46
  43. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.h +23 -23
  44. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/MCPExternalRegistry.cpp +83 -83
  45. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/UE_MCP_BridgeModule.h +14 -14
  46. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/UE_MCP_BridgeStatusModule.cpp +37 -37
  47. package/dist/manifest-signature.d.ts +0 -1
  48. package/dist/manifest-signature.js +0 -53
  49. package/dist/manifest-signature.js.map +0 -1
  50. package/dist/pie/schema.d.ts +0 -791
  51. package/dist/pie/schema.js +0 -151
  52. package/dist/pie/schema.js.map +0 -1
  53. package/dist/watch-cli.js.map +0 -1
  54. /package/plugin/ue_mcp_bridge/{ue_mcp_bridge.uplugin → UE_MCP_Bridge.uplugin} +0 -0
@@ -1,76 +1,76 @@
1
- #include "EngineStatusHooks.h"
2
- #include "MCPEngineStatus.h"
3
- #include "UE_MCP_BridgeModule.h"
4
- #include "GameThreadExecutor.h"
5
- #include "Handlers/DialogHandlers.h"
6
-
7
- #include "Framework/Application/SlateApplication.h"
8
-
9
- #include "AssetCompilingManager.h"
10
- #include "ShaderCompiler.h"
11
-
12
- namespace
13
- {
14
- FDelegateHandle GPreTickHandle;
15
- FDelegateHandle GModalLoopHandle;
16
- }
17
-
18
- void FMCPEngineStatusHooks::Install()
19
- {
20
- FMCPEngineStatus& Status = FMCPEngineStatus::Get();
21
-
22
- Status.SetModalProvider([](FString& OutTitle, FString& OutMessage, TArray<FString>& OutButtons)
23
- {
24
- return FDialogHandlers::DescribeActiveModal(OutTitle, OutMessage, OutButtons);
25
- });
26
-
27
- Status.SetCompileProvider([](int32& OutShaderJobs, int32& OutAssetCompiles)
28
- {
29
- OutShaderJobs = GShaderCompilingManager ? GShaderCompilingManager->GetNumRemainingJobs() : 0;
30
- OutAssetCompiles = FAssetCompilingManager::Get().GetNumRemainingAssets();
31
- });
32
-
33
- if (!FSlateApplication::IsInitialized())
34
- {
35
- UE_LOG(LogMCPBridge, Warning, TEXT("[UE-MCP] Slate not initialized at bridge startup - engine status keeps its core-only hooks"));
36
- return;
37
- }
38
-
39
- // Slate's pre-tick keeps firing while a long operation pumps the UI to draw
40
- // its progress bar, which is exactly the window where the core ticker is
41
- // suspended and every bridge request times out.
42
- GPreTickHandle = FSlateApplication::Get().OnPreTick().AddLambda([](float)
43
- {
44
- FMCPEngineStatus::Get().CaptureNow();
45
- });
46
-
47
- GModalLoopHandle = FSlateApplication::Get().GetOnModalLoopTickEvent().AddLambda([](float)
48
- {
49
- FMCPEngineStatus::Get().CaptureNow();
50
- // Seeing the dialog is only half of it: the call that could answer it
51
- // is queued behind the same blocked game thread. Modal-safe handlers
52
- // run here so a dialog can be cleared from the outside.
53
- FMCPGameThreadExecutor::DrainModalSafeQueue();
54
- });
55
- }
56
-
57
- void FMCPEngineStatusHooks::Remove()
58
- {
59
- FMCPEngineStatus& Status = FMCPEngineStatus::Get();
60
- Status.SetModalProvider(nullptr);
61
- Status.SetCompileProvider(nullptr);
62
-
63
- if (FSlateApplication::IsInitialized())
64
- {
65
- if (GPreTickHandle.IsValid())
66
- {
67
- FSlateApplication::Get().OnPreTick().Remove(GPreTickHandle);
68
- GPreTickHandle.Reset();
69
- }
70
- if (GModalLoopHandle.IsValid())
71
- {
72
- FSlateApplication::Get().GetOnModalLoopTickEvent().Remove(GModalLoopHandle);
73
- GModalLoopHandle.Reset();
74
- }
75
- }
76
- }
1
+ #include "EngineStatusHooks.h"
2
+ #include "MCPEngineStatus.h"
3
+ #include "UE_MCP_BridgeModule.h"
4
+ #include "GameThreadExecutor.h"
5
+ #include "Handlers/DialogHandlers.h"
6
+
7
+ #include "Framework/Application/SlateApplication.h"
8
+
9
+ #include "AssetCompilingManager.h"
10
+ #include "ShaderCompiler.h"
11
+
12
+ namespace
13
+ {
14
+ FDelegateHandle GPreTickHandle;
15
+ FDelegateHandle GModalLoopHandle;
16
+ }
17
+
18
+ void FMCPEngineStatusHooks::Install()
19
+ {
20
+ FMCPEngineStatus& Status = FMCPEngineStatus::Get();
21
+
22
+ Status.SetModalProvider([](FString& OutTitle, FString& OutMessage, TArray<FString>& OutButtons)
23
+ {
24
+ return FDialogHandlers::DescribeActiveModal(OutTitle, OutMessage, OutButtons);
25
+ });
26
+
27
+ Status.SetCompileProvider([](int32& OutShaderJobs, int32& OutAssetCompiles)
28
+ {
29
+ OutShaderJobs = GShaderCompilingManager ? GShaderCompilingManager->GetNumRemainingJobs() : 0;
30
+ OutAssetCompiles = FAssetCompilingManager::Get().GetNumRemainingAssets();
31
+ });
32
+
33
+ if (!FSlateApplication::IsInitialized())
34
+ {
35
+ UE_LOG(LogMCPBridge, Warning, TEXT("[UE-MCP] Slate not initialized at bridge startup - engine status keeps its core-only hooks"));
36
+ return;
37
+ }
38
+
39
+ // Slate's pre-tick keeps firing while a long operation pumps the UI to draw
40
+ // its progress bar, which is exactly the window where the core ticker is
41
+ // suspended and every bridge request times out.
42
+ GPreTickHandle = FSlateApplication::Get().OnPreTick().AddLambda([](float)
43
+ {
44
+ FMCPEngineStatus::Get().CaptureNow();
45
+ });
46
+
47
+ GModalLoopHandle = FSlateApplication::Get().GetOnModalLoopTickEvent().AddLambda([](float)
48
+ {
49
+ FMCPEngineStatus::Get().CaptureNow();
50
+ // Seeing the dialog is only half of it: the call that could answer it
51
+ // is queued behind the same blocked game thread. Modal-safe handlers
52
+ // run here so a dialog can be cleared from the outside.
53
+ FMCPGameThreadExecutor::DrainModalSafeQueue();
54
+ });
55
+ }
56
+
57
+ void FMCPEngineStatusHooks::Remove()
58
+ {
59
+ FMCPEngineStatus& Status = FMCPEngineStatus::Get();
60
+ Status.SetModalProvider(nullptr);
61
+ Status.SetCompileProvider(nullptr);
62
+
63
+ if (FSlateApplication::IsInitialized())
64
+ {
65
+ if (GPreTickHandle.IsValid())
66
+ {
67
+ FSlateApplication::Get().OnPreTick().Remove(GPreTickHandle);
68
+ GPreTickHandle.Reset();
69
+ }
70
+ if (GModalLoopHandle.IsValid())
71
+ {
72
+ FSlateApplication::Get().GetOnModalLoopTickEvent().Remove(GModalLoopHandle);
73
+ GModalLoopHandle.Reset();
74
+ }
75
+ }
76
+ }
@@ -1,27 +1,27 @@
1
- #pragma once
2
-
3
- #include "CoreMinimal.h"
4
-
5
- /**
6
- * Wires the editor-only sensors into FMCPEngineStatus, which lives in the
7
- * UE_MCP_BridgeStatus module and has been publishing since PostConfigInit on
8
- * Core-only hooks.
9
- *
10
- * Split this way because the snapshot has to exist long before Slate, the
11
- * asset compiler or the shader compiler do. Once the bridge module loads, the
12
- * same snapshot gains:
13
- *
14
- * - Slate's pre-tick, which keeps firing while a long operation pumps the UI;
15
- * - the modal loop tick, which fires while a dialog owns the main loop (and
16
- * is also where modal-safe handlers get their chance to run);
17
- * - a description of the active modal dialog, from the Slate widget walk;
18
- * - remaining shader jobs and asset compiles.
19
- */
20
- namespace FMCPEngineStatusHooks
21
- {
22
- /** Register the Slate hooks and the Slate/Engine-backed providers. */
23
- void Install();
24
-
25
- /** Unregister everything registered by Install. Safe to call twice. */
26
- void Remove();
27
- }
1
+ #pragma once
2
+
3
+ #include "CoreMinimal.h"
4
+
5
+ /**
6
+ * Wires the editor-only sensors into FMCPEngineStatus, which lives in the
7
+ * UE_MCP_BridgeStatus module and has been publishing since PostConfigInit on
8
+ * Core-only hooks.
9
+ *
10
+ * Split this way because the snapshot has to exist long before Slate, the
11
+ * asset compiler or the shader compiler do. Once the bridge module loads, the
12
+ * same snapshot gains:
13
+ *
14
+ * - Slate's pre-tick, which keeps firing while a long operation pumps the UI;
15
+ * - the modal loop tick, which fires while a dialog owns the main loop (and
16
+ * is also where modal-safe handlers get their chance to run);
17
+ * - a description of the active modal dialog, from the Slate widget walk;
18
+ * - remaining shader jobs and asset compiles.
19
+ */
20
+ namespace FMCPEngineStatusHooks
21
+ {
22
+ /** Register the Slate hooks and the Slate/Engine-backed providers. */
23
+ void Install();
24
+
25
+ /** Unregister everything registered by Install. Safe to call twice. */
26
+ void Remove();
27
+ }
@@ -1,128 +1,128 @@
1
- #include "HandlerRegistry.h"
2
- #include "HAL/PlatformFileManager.h"
3
- #include "Misc/FileHelper.h"
4
- #include "Misc/Paths.h"
5
- #include "HandlerUtils.h"
6
- #include "MCPHandlerRegistration.h"
7
-
8
- FMCPHandlerRegistry::FMCPHandlerRegistry()
9
- {
10
- }
11
-
12
- FMCPHandlerRegistry::~FMCPHandlerRegistry()
13
- {
14
- Clear();
15
- }
16
-
17
- void FMCPHandlerRegistry::RegisterHandler(const FString& MethodName, FHandlerFunction Handler)
18
- {
19
- CppHandlers.Add(MethodName, Handler);
20
- }
21
-
22
- void FMCPHandlerRegistry::RegisterHandlerWithTimeout(const FString& MethodName, FHandlerFunction Handler, float TimeoutSeconds)
23
- {
24
- CppHandlers.Add(MethodName, Handler);
25
- if (TimeoutSeconds > 0.0f)
26
- {
27
- HandlerTimeouts.Add(MethodName, TimeoutSeconds);
28
- }
29
- }
30
-
31
- float FMCPHandlerRegistry::GetHandlerTimeout(const FString& MethodName) const
32
- {
33
- if (const float* V = HandlerTimeouts.Find(MethodName))
34
- {
35
- return *V;
36
- }
37
- // External (plugin-contributed) handlers may register their own timeout.
38
- UEMCP::FExternalHandlerFn Unused;
39
- float ExternalTimeout = 0.0f;
40
- if (UEMCP::LookupExternalHandler(MethodName, Unused, ExternalTimeout) && ExternalTimeout > 0.0f)
41
- {
42
- return ExternalTimeout;
43
- }
44
- return 0.0f;
45
- }
46
-
47
- void FMCPHandlerRegistry::RegisterPythonHandler(const FString& MethodName, const FString& PythonScriptPath)
48
- {
49
- FPythonHandlerInfo Info;
50
- Info.ScriptPath = PythonScriptPath;
51
- Info.HandlerName = MethodName;
52
- PythonHandlers.Add(MethodName, Info);
53
- }
54
-
55
- TSharedPtr<FJsonValue> FMCPHandlerRegistry::ExecuteHandler(const FString& MethodName, const TSharedPtr<FJsonObject>& Params)
56
- {
57
- // Try C++ handler first
58
- if (CppHandlers.Contains(MethodName))
59
- {
60
- return CppHandlers[MethodName](Params);
61
- }
62
-
63
- // Try Python handler
64
- if (PythonHandlers.Contains(MethodName))
65
- {
66
- return ExecutePythonHandler(MethodName, Params);
67
- }
68
-
69
- // Plugin-contributed external handler (registered via UEMCP::RegisterExternalHandler).
70
- {
71
- UEMCP::FExternalHandlerFn External;
72
- float Unused = 0.0f;
73
- if (UEMCP::LookupExternalHandler(MethodName, External, Unused))
74
- {
75
- return External(Params);
76
- }
77
- }
78
-
79
- // Handler not found - return nullptr so BridgeServer sends "Unknown method" error
80
- return nullptr;
81
- }
82
-
83
- bool FMCPHandlerRegistry::HasHandler(const FString& MethodName) const
84
- {
85
- if (CppHandlers.Contains(MethodName) || PythonHandlers.Contains(MethodName))
86
- {
87
- return true;
88
- }
89
- UEMCP::FExternalHandlerFn Unused;
90
- float UnusedTimeout = 0.0f;
91
- return UEMCP::LookupExternalHandler(MethodName, Unused, UnusedTimeout);
92
- }
93
-
94
- TArray<FString> FMCPHandlerRegistry::GetHandlerNames() const
95
- {
96
- TArray<FString> Names;
97
- CppHandlers.GetKeys(Names);
98
-
99
- TArray<FString> PythonNames;
100
- PythonHandlers.GetKeys(PythonNames);
101
- Names.Append(PythonNames);
102
-
103
- Names.Append(UEMCP::GetExternalHandlerNames());
104
-
105
- return Names;
106
- }
107
-
108
- void FMCPHandlerRegistry::Clear()
109
- {
110
- CppHandlers.Empty();
111
- PythonHandlers.Empty();
112
- HandlerTimeouts.Empty();
113
- }
114
-
115
- TSharedPtr<FJsonValue> FMCPHandlerRegistry::ExecutePythonHandler(const FString& MethodName, const TSharedPtr<FJsonObject>& /*Params*/)
116
- {
117
- // Python handler dispatch is not implemented. Prior behaviour returned an
118
- // empty JSON object, which callers could not distinguish from a real
119
- // empty-success result. Return a typed error instead so callers see the
120
- // gap clearly; use `execute_python` for ad-hoc Python until the dispatch
121
- // pipeline lands.
122
- TSharedPtr<FJsonObject> Err = MakeShared<FJsonObject>();
123
- Err->SetBoolField(TEXT("success"), false);
124
- Err->SetStringField(TEXT("error"), FString::Printf(
125
- TEXT("Python handler '%s' is registered but Python dispatch is not implemented. Use the 'execute_python' action instead."),
126
- *MethodName));
127
- return MakeShared<FJsonValueObject>(Err);
128
- }
1
+ #include "HandlerRegistry.h"
2
+ #include "HAL/PlatformFileManager.h"
3
+ #include "Misc/FileHelper.h"
4
+ #include "Misc/Paths.h"
5
+ #include "HandlerUtils.h"
6
+ #include "MCPHandlerRegistration.h"
7
+
8
+ FMCPHandlerRegistry::FMCPHandlerRegistry()
9
+ {
10
+ }
11
+
12
+ FMCPHandlerRegistry::~FMCPHandlerRegistry()
13
+ {
14
+ Clear();
15
+ }
16
+
17
+ void FMCPHandlerRegistry::RegisterHandler(const FString& MethodName, FHandlerFunction Handler)
18
+ {
19
+ CppHandlers.Add(MethodName, Handler);
20
+ }
21
+
22
+ void FMCPHandlerRegistry::RegisterHandlerWithTimeout(const FString& MethodName, FHandlerFunction Handler, float TimeoutSeconds)
23
+ {
24
+ CppHandlers.Add(MethodName, Handler);
25
+ if (TimeoutSeconds > 0.0f)
26
+ {
27
+ HandlerTimeouts.Add(MethodName, TimeoutSeconds);
28
+ }
29
+ }
30
+
31
+ float FMCPHandlerRegistry::GetHandlerTimeout(const FString& MethodName) const
32
+ {
33
+ if (const float* V = HandlerTimeouts.Find(MethodName))
34
+ {
35
+ return *V;
36
+ }
37
+ // External (plugin-contributed) handlers may register their own timeout.
38
+ UEMCP::FExternalHandlerFn Unused;
39
+ float ExternalTimeout = 0.0f;
40
+ if (UEMCP::LookupExternalHandler(MethodName, Unused, ExternalTimeout) && ExternalTimeout > 0.0f)
41
+ {
42
+ return ExternalTimeout;
43
+ }
44
+ return 0.0f;
45
+ }
46
+
47
+ void FMCPHandlerRegistry::RegisterPythonHandler(const FString& MethodName, const FString& PythonScriptPath)
48
+ {
49
+ FPythonHandlerInfo Info;
50
+ Info.ScriptPath = PythonScriptPath;
51
+ Info.HandlerName = MethodName;
52
+ PythonHandlers.Add(MethodName, Info);
53
+ }
54
+
55
+ TSharedPtr<FJsonValue> FMCPHandlerRegistry::ExecuteHandler(const FString& MethodName, const TSharedPtr<FJsonObject>& Params)
56
+ {
57
+ // Try C++ handler first
58
+ if (CppHandlers.Contains(MethodName))
59
+ {
60
+ return CppHandlers[MethodName](Params);
61
+ }
62
+
63
+ // Try Python handler
64
+ if (PythonHandlers.Contains(MethodName))
65
+ {
66
+ return ExecutePythonHandler(MethodName, Params);
67
+ }
68
+
69
+ // Plugin-contributed external handler (registered via UEMCP::RegisterExternalHandler).
70
+ {
71
+ UEMCP::FExternalHandlerFn External;
72
+ float Unused = 0.0f;
73
+ if (UEMCP::LookupExternalHandler(MethodName, External, Unused))
74
+ {
75
+ return External(Params);
76
+ }
77
+ }
78
+
79
+ // Handler not found - return nullptr so BridgeServer sends "Unknown method" error
80
+ return nullptr;
81
+ }
82
+
83
+ bool FMCPHandlerRegistry::HasHandler(const FString& MethodName) const
84
+ {
85
+ if (CppHandlers.Contains(MethodName) || PythonHandlers.Contains(MethodName))
86
+ {
87
+ return true;
88
+ }
89
+ UEMCP::FExternalHandlerFn Unused;
90
+ float UnusedTimeout = 0.0f;
91
+ return UEMCP::LookupExternalHandler(MethodName, Unused, UnusedTimeout);
92
+ }
93
+
94
+ TArray<FString> FMCPHandlerRegistry::GetHandlerNames() const
95
+ {
96
+ TArray<FString> Names;
97
+ CppHandlers.GetKeys(Names);
98
+
99
+ TArray<FString> PythonNames;
100
+ PythonHandlers.GetKeys(PythonNames);
101
+ Names.Append(PythonNames);
102
+
103
+ Names.Append(UEMCP::GetExternalHandlerNames());
104
+
105
+ return Names;
106
+ }
107
+
108
+ void FMCPHandlerRegistry::Clear()
109
+ {
110
+ CppHandlers.Empty();
111
+ PythonHandlers.Empty();
112
+ HandlerTimeouts.Empty();
113
+ }
114
+
115
+ TSharedPtr<FJsonValue> FMCPHandlerRegistry::ExecutePythonHandler(const FString& MethodName, const TSharedPtr<FJsonObject>& /*Params*/)
116
+ {
117
+ // Python handler dispatch is not implemented. Prior behaviour returned an
118
+ // empty JSON object, which callers could not distinguish from a real
119
+ // empty-success result. Return a typed error instead so callers see the
120
+ // gap clearly; use `execute_python` for ad-hoc Python until the dispatch
121
+ // pipeline lands.
122
+ TSharedPtr<FJsonObject> Err = MakeShared<FJsonObject>();
123
+ Err->SetBoolField(TEXT("success"), false);
124
+ Err->SetStringField(TEXT("error"), FString::Printf(
125
+ TEXT("Python handler '%s' is registered but Python dispatch is not implemented. Use the 'execute_python' action instead."),
126
+ *MethodName));
127
+ return MakeShared<FJsonValueObject>(Err);
128
+ }
@@ -1,63 +1,63 @@
1
- #pragma once
2
-
3
- #include "CoreMinimal.h"
4
- #include "Dom/JsonValue.h"
5
- #include "Dom/JsonObject.h"
6
-
7
- class FMCPHandlerRegistry
8
- {
9
- public:
10
- // Handler function signature: takes params JSON object, returns result JSON value
11
- using FHandlerFunction = TFunction<TSharedPtr<FJsonValue>(const TSharedPtr<FJsonObject>& Params)>;
12
-
13
- // Python handler info
14
- struct FPythonHandlerInfo
15
- {
16
- FString ScriptPath;
17
- FString HandlerName;
18
- };
19
-
20
- FMCPHandlerRegistry();
21
- ~FMCPHandlerRegistry();
22
-
23
- // Register a C++ handler
24
- void RegisterHandler(const FString& MethodName, FHandlerFunction Handler);
25
-
26
- // Register a C++ handler with a non-default game-thread execution timeout.
27
- // Most handlers finish in milliseconds, but a few (create_cpp_class
28
- // regenerates IDE project files; build-related ops) legitimately need
29
- // minutes. Pass TimeoutSeconds explicitly for those.
30
- void RegisterHandlerWithTimeout(const FString& MethodName, FHandlerFunction Handler, float TimeoutSeconds);
31
-
32
- // Look up a per-handler timeout. Returns 0 if no override registered,
33
- // in which case the caller should use its default.
34
- float GetHandlerTimeout(const FString& MethodName) const;
35
-
36
- // Register a Python handler
37
- void RegisterPythonHandler(const FString& MethodName, const FString& PythonScriptPath);
38
-
39
- // Execute a handler
40
- TSharedPtr<FJsonValue> ExecuteHandler(const FString& MethodName, const TSharedPtr<FJsonObject>& Params);
41
-
42
- // Check if handler exists
43
- bool HasHandler(const FString& MethodName) const;
44
-
45
- // Get all registered handler names
46
- TArray<FString> GetHandlerNames() const;
47
-
48
- // Clear all handlers
49
- void Clear();
50
-
51
- private:
52
- // C++ handlers
53
- TMap<FString, FHandlerFunction> CppHandlers;
54
-
55
- // Python handlers
56
- TMap<FString, FPythonHandlerInfo> PythonHandlers;
57
-
58
- // Per-handler game-thread timeouts (seconds). Absent = use default.
59
- TMap<FString, float> HandlerTimeouts;
60
-
61
- // Execute Python handler
62
- TSharedPtr<FJsonValue> ExecutePythonHandler(const FString& MethodName, const TSharedPtr<FJsonObject>& Params);
63
- };
1
+ #pragma once
2
+
3
+ #include "CoreMinimal.h"
4
+ #include "Dom/JsonValue.h"
5
+ #include "Dom/JsonObject.h"
6
+
7
+ class FMCPHandlerRegistry
8
+ {
9
+ public:
10
+ // Handler function signature: takes params JSON object, returns result JSON value
11
+ using FHandlerFunction = TFunction<TSharedPtr<FJsonValue>(const TSharedPtr<FJsonObject>& Params)>;
12
+
13
+ // Python handler info
14
+ struct FPythonHandlerInfo
15
+ {
16
+ FString ScriptPath;
17
+ FString HandlerName;
18
+ };
19
+
20
+ FMCPHandlerRegistry();
21
+ ~FMCPHandlerRegistry();
22
+
23
+ // Register a C++ handler
24
+ void RegisterHandler(const FString& MethodName, FHandlerFunction Handler);
25
+
26
+ // Register a C++ handler with a non-default game-thread execution timeout.
27
+ // Most handlers finish in milliseconds, but a few (create_cpp_class
28
+ // regenerates IDE project files; build-related ops) legitimately need
29
+ // minutes. Pass TimeoutSeconds explicitly for those.
30
+ void RegisterHandlerWithTimeout(const FString& MethodName, FHandlerFunction Handler, float TimeoutSeconds);
31
+
32
+ // Look up a per-handler timeout. Returns 0 if no override registered,
33
+ // in which case the caller should use its default.
34
+ float GetHandlerTimeout(const FString& MethodName) const;
35
+
36
+ // Register a Python handler
37
+ void RegisterPythonHandler(const FString& MethodName, const FString& PythonScriptPath);
38
+
39
+ // Execute a handler
40
+ TSharedPtr<FJsonValue> ExecuteHandler(const FString& MethodName, const TSharedPtr<FJsonObject>& Params);
41
+
42
+ // Check if handler exists
43
+ bool HasHandler(const FString& MethodName) const;
44
+
45
+ // Get all registered handler names
46
+ TArray<FString> GetHandlerNames() const;
47
+
48
+ // Clear all handlers
49
+ void Clear();
50
+
51
+ private:
52
+ // C++ handlers
53
+ TMap<FString, FHandlerFunction> CppHandlers;
54
+
55
+ // Python handlers
56
+ TMap<FString, FPythonHandlerInfo> PythonHandlers;
57
+
58
+ // Per-handler game-thread timeouts (seconds). Absent = use default.
59
+ TMap<FString, float> HandlerTimeouts;
60
+
61
+ // Execute Python handler
62
+ TSharedPtr<FJsonValue> ExecutePythonHandler(const FString& MethodName, const TSharedPtr<FJsonObject>& Params);
63
+ };