unreal-engine-mcp-server 0.5.4 → 0.5.5
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/automation/bridge.d.ts.map +1 -0
- package/dist/automation/bridge.js.map +1 -0
- package/dist/automation/connection-manager.d.ts.map +1 -0
- package/dist/automation/connection-manager.js.map +1 -0
- package/dist/automation/handshake.d.ts.map +1 -0
- package/dist/automation/handshake.js.map +1 -0
- package/dist/automation/index.d.ts.map +1 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/message-handler.d.ts.map +1 -0
- package/dist/automation/message-handler.js.map +1 -0
- package/dist/automation/request-tracker.d.ts.map +1 -0
- package/dist/automation/request-tracker.js.map +1 -0
- package/dist/automation/types.d.ts.map +1 -0
- package/dist/automation/types.js.map +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +4 -3
- package/dist/cli.js.map +1 -0
- package/dist/config/class-aliases.d.ts.map +1 -0
- package/dist/config/class-aliases.js.map +1 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js.map +1 -0
- package/dist/graphql/loaders.d.ts.map +1 -0
- package/dist/graphql/loaders.js.map +1 -0
- package/dist/graphql/resolvers.d.ts.map +1 -0
- package/dist/graphql/resolvers.js +29 -29
- package/dist/graphql/resolvers.js.map +1 -0
- package/dist/graphql/schema.d.ts.map +1 -0
- package/dist/graphql/schema.js.map +1 -0
- package/dist/graphql/server.d.ts.map +1 -0
- package/dist/graphql/server.js.map +1 -0
- package/dist/graphql/types.d.ts.map +1 -0
- package/dist/graphql/types.js.map +1 -0
- package/dist/handlers/resource-handlers.d.ts.map +1 -0
- package/dist/handlers/resource-handlers.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -7
- package/dist/index.js.map +1 -0
- package/dist/resources/actors.d.ts.map +1 -0
- package/dist/resources/actors.js.map +1 -0
- package/dist/resources/assets.d.ts.map +1 -0
- package/dist/resources/assets.js +6 -4
- package/dist/resources/assets.js.map +1 -0
- package/dist/resources/levels.d.ts.map +1 -0
- package/dist/resources/levels.js.map +1 -0
- package/dist/server/resource-registry.d.ts.map +1 -0
- package/dist/server/resource-registry.js.map +1 -0
- package/dist/server/tool-registry.d.ts.map +1 -0
- package/dist/server/tool-registry.js.map +1 -0
- package/dist/server-setup.d.ts.map +1 -0
- package/dist/server-setup.js.map +1 -0
- package/dist/services/health-monitor.d.ts.map +1 -0
- package/dist/services/health-monitor.js.map +1 -0
- package/dist/services/metrics-server.d.ts.map +1 -0
- package/dist/services/metrics-server.js.map +1 -0
- package/dist/tools/actors.d.ts.map +1 -0
- package/dist/tools/actors.js +3 -1
- package/dist/tools/actors.js.map +1 -0
- package/dist/tools/animation.d.ts.map +1 -0
- package/dist/tools/animation.js +2 -2
- package/dist/tools/animation.js.map +1 -0
- package/dist/tools/assets.d.ts.map +1 -0
- package/dist/tools/assets.js.map +1 -0
- package/dist/tools/audio.d.ts.map +1 -0
- package/dist/tools/audio.js.map +1 -0
- package/dist/tools/base-tool.d.ts.map +1 -0
- package/dist/tools/base-tool.js.map +1 -0
- package/dist/tools/behavior-tree.d.ts.map +1 -0
- package/dist/tools/behavior-tree.js.map +1 -0
- package/dist/tools/blueprint.d.ts.map +1 -0
- package/dist/tools/blueprint.js +4 -2
- package/dist/tools/blueprint.js.map +1 -0
- package/dist/tools/consolidated-tool-definitions.d.ts.map +1 -0
- package/dist/tools/consolidated-tool-definitions.js.map +1 -0
- package/dist/tools/consolidated-tool-handlers.d.ts.map +1 -0
- package/dist/tools/consolidated-tool-handlers.js.map +1 -0
- package/dist/tools/debug.d.ts.map +1 -0
- package/dist/tools/debug.js +3 -1
- package/dist/tools/debug.js.map +1 -0
- package/dist/tools/dynamic-handler-registry.d.ts.map +1 -0
- package/dist/tools/dynamic-handler-registry.js +3 -1
- package/dist/tools/dynamic-handler-registry.js.map +1 -0
- package/dist/tools/editor.d.ts.map +1 -0
- package/dist/tools/editor.js +1 -1
- package/dist/tools/editor.js.map +1 -0
- package/dist/tools/engine.d.ts.map +1 -0
- package/dist/tools/engine.js.map +1 -0
- package/dist/tools/environment.d.ts.map +1 -0
- package/dist/tools/environment.js +2 -2
- package/dist/tools/environment.js.map +1 -0
- package/dist/tools/foliage.d.ts.map +1 -0
- package/dist/tools/foliage.js.map +1 -0
- package/dist/tools/handlers/actor-handlers.d.ts +1 -1
- package/dist/tools/handlers/actor-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/actor-handlers.js +6 -5
- package/dist/tools/handlers/actor-handlers.js.map +1 -0
- package/dist/tools/handlers/animation-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/animation-handlers.js.map +1 -0
- package/dist/tools/handlers/argument-helper.d.ts.map +1 -0
- package/dist/tools/handlers/argument-helper.js.map +1 -0
- package/dist/tools/handlers/asset-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/asset-handlers.js +5 -1
- package/dist/tools/handlers/asset-handlers.js.map +1 -0
- package/dist/tools/handlers/audio-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/audio-handlers.js.map +1 -0
- package/dist/tools/handlers/blueprint-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/blueprint-handlers.js +2 -1
- package/dist/tools/handlers/blueprint-handlers.js.map +1 -0
- package/dist/tools/handlers/common-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/common-handlers.js.map +1 -0
- package/dist/tools/handlers/editor-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/editor-handlers.js +12 -2
- package/dist/tools/handlers/editor-handlers.js.map +1 -0
- package/dist/tools/handlers/effect-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/effect-handlers.js.map +1 -0
- package/dist/tools/handlers/environment-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/environment-handlers.js.map +1 -0
- package/dist/tools/handlers/graph-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/graph-handlers.js +61 -1
- package/dist/tools/handlers/graph-handlers.js.map +1 -0
- package/dist/tools/handlers/input-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/input-handlers.js.map +1 -0
- package/dist/tools/handlers/inspect-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/inspect-handlers.js.map +1 -0
- package/dist/tools/handlers/level-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/level-handlers.js.map +1 -0
- package/dist/tools/handlers/lighting-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/lighting-handlers.js +23 -1
- package/dist/tools/handlers/lighting-handlers.js.map +1 -0
- package/dist/tools/handlers/performance-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/performance-handlers.js +15 -2
- package/dist/tools/handlers/performance-handlers.js.map +1 -0
- package/dist/tools/handlers/pipeline-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/pipeline-handlers.js.map +1 -0
- package/dist/tools/handlers/sequence-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/sequence-handlers.js.map +1 -0
- package/dist/tools/handlers/system-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/system-handlers.js +16 -1
- package/dist/tools/handlers/system-handlers.js.map +1 -0
- package/dist/tools/input.d.ts.map +1 -0
- package/dist/tools/input.js +3 -1
- package/dist/tools/input.js.map +1 -0
- package/dist/tools/introspection.d.ts.map +1 -0
- package/dist/tools/introspection.js.map +1 -0
- package/dist/tools/landscape.d.ts.map +1 -0
- package/dist/tools/landscape.js +3 -1
- package/dist/tools/landscape.js.map +1 -0
- package/dist/tools/level.d.ts.map +1 -0
- package/dist/tools/level.js.map +1 -0
- package/dist/tools/lighting.d.ts.map +1 -0
- package/dist/tools/lighting.js +3 -1
- package/dist/tools/lighting.js.map +1 -0
- package/dist/tools/logs.d.ts.map +1 -0
- package/dist/tools/logs.js.map +1 -0
- package/dist/tools/materials.d.ts.map +1 -0
- package/dist/tools/materials.js +3 -1
- package/dist/tools/materials.js.map +1 -0
- package/dist/tools/niagara.d.ts.map +1 -0
- package/dist/tools/niagara.js +7 -5
- package/dist/tools/niagara.js.map +1 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/tools/physics.d.ts.map +1 -0
- package/dist/tools/physics.js +9 -7
- package/dist/tools/physics.js.map +1 -0
- package/dist/tools/property-dictionary.d.ts.map +1 -0
- package/dist/tools/property-dictionary.js.map +1 -0
- package/dist/tools/sequence.d.ts.map +1 -0
- package/dist/tools/sequence.js +3 -1
- package/dist/tools/sequence.js.map +1 -0
- package/dist/tools/tool-definition-utils.d.ts.map +1 -0
- package/dist/tools/tool-definition-utils.js.map +1 -0
- package/dist/tools/ui.d.ts.map +1 -0
- package/dist/tools/ui.js +3 -1
- package/dist/tools/ui.js.map +1 -0
- package/dist/types/automation-responses.d.ts.map +1 -0
- package/dist/types/automation-responses.js.map +1 -0
- package/dist/types/env.d.ts.map +1 -0
- package/dist/types/env.js.map +1 -0
- package/dist/types/handler-types.d.ts.map +1 -0
- package/dist/types/handler-types.js.map +1 -0
- package/dist/types/tool-interfaces.d.ts.map +1 -0
- package/dist/types/tool-interfaces.js.map +1 -0
- package/dist/types/tool-types.d.ts.map +1 -0
- package/dist/types/tool-types.js.map +1 -0
- package/dist/unreal-bridge.d.ts +1 -0
- package/dist/unreal-bridge.d.ts.map +1 -0
- package/dist/unreal-bridge.js +8 -0
- package/dist/unreal-bridge.js.map +1 -0
- package/dist/utils/command-validator.d.ts.map +1 -0
- package/dist/utils/command-validator.js.map +1 -0
- package/dist/utils/elicitation.d.ts.map +1 -0
- package/dist/utils/elicitation.js.map +1 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/ini-reader.d.ts.map +1 -0
- package/dist/utils/ini-reader.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/normalize.d.ts.map +1 -0
- package/dist/utils/normalize.js.map +1 -0
- package/dist/utils/path-security.d.ts.map +1 -0
- package/dist/utils/path-security.js.map +1 -0
- package/dist/utils/response-factory.d.ts.map +1 -0
- package/dist/utils/response-factory.js +3 -1
- package/dist/utils/response-factory.js.map +1 -0
- package/dist/utils/response-validator.d.ts.map +1 -0
- package/dist/utils/response-validator.js.map +1 -0
- package/dist/utils/result-helpers.d.ts.map +1 -0
- package/dist/utils/result-helpers.js.map +1 -0
- package/dist/utils/safe-json.d.ts.map +1 -0
- package/dist/utils/safe-json.js.map +1 -0
- package/dist/utils/unreal-command-queue.d.ts.map +1 -0
- package/dist/utils/unreal-command-queue.js.map +1 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/wasm/index.d.ts.map +1 -0
- package/dist/wasm/index.js.map +1 -0
- package/package.json +12 -34
- package/server.json +2 -2
- package/.dockerignore +0 -57
- package/.env.example +0 -26
- package/.env.production +0 -61
- package/.eslintrc.json +0 -0
- package/.eslintrc.override.json +0 -8
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -94
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -56
- package/.github/copilot-instructions.md +0 -478
- package/.github/dependabot.yml +0 -19
- package/.github/labeler.yml +0 -24
- package/.github/labels.yml +0 -70
- package/.github/pull_request_template.md +0 -42
- package/.github/release-drafter-config.yml +0 -51
- package/.github/workflows/auto-merge.yml +0 -38
- package/.github/workflows/ci.yml +0 -38
- package/.github/workflows/dependency-review.yml +0 -17
- package/.github/workflows/gemini-issue-triage.yml +0 -172
- package/.github/workflows/greetings.yml +0 -27
- package/.github/workflows/labeler.yml +0 -17
- package/.github/workflows/links.yml +0 -80
- package/.github/workflows/pr-size-labeler.yml +0 -137
- package/.github/workflows/publish-mcp.yml +0 -79
- package/.github/workflows/release-drafter.yml +0 -24
- package/.github/workflows/release.yml +0 -112
- package/.github/workflows/semantic-pull-request.yml +0 -35
- package/.github/workflows/smoke-test.yml +0 -36
- package/.github/workflows/stale.yml +0 -28
- package/CONTRIBUTING.md +0 -140
- package/Dockerfile +0 -37
- package/GEMINI.md +0 -115
- package/Public/Plugin_setup_guide.mp4 +0 -0
- package/Public/icon.png +0 -0
- package/claude_desktop_config_example.json +0 -15
- package/dist/types/responses.d.ts +0 -249
- package/dist/types/responses.js +0 -2
- package/docs/GraphQL-API.md +0 -888
- package/docs/Migration-Guide-v0.5.0.md +0 -684
- package/docs/Roadmap.md +0 -53
- package/docs/WebAssembly-Integration.md +0 -628
- package/docs/editor-plugin-extension.md +0 -370
- package/docs/handler-mapping.md +0 -249
- package/docs/native-automation-progress.md +0 -128
- package/docs/testing-guide.md +0 -423
- package/eslint.config.mjs +0 -68
- package/mcp-config-example.json +0 -14
- package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +0 -8
- package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +0 -64
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +0 -189
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +0 -22
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +0 -30
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +0 -1983
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +0 -72
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +0 -46
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +0 -846
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +0 -2393
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +0 -300
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +0 -2807
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +0 -1087
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +0 -488
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +0 -643
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +0 -31
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +0 -1094
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +0 -5750
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +0 -152
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +0 -2614
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +0 -42
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +0 -1237
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +0 -1725
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +0 -2265
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +0 -954
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +0 -209
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +0 -41
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +0 -1164
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +0 -762
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +0 -663
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +0 -136
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +0 -494
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +0 -278
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +0 -625
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +0 -401
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +0 -67
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +0 -472
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +0 -2634
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +0 -189
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +0 -917
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +0 -39
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +0 -2706
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +0 -519
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +0 -38
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +0 -668
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +0 -346
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +0 -1345
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +0 -149
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +0 -782
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +0 -115
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +0 -796
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +0 -117
- package/scripts/check-unreal-connection.mjs +0 -19
- package/scripts/clean-tmp.js +0 -23
- package/scripts/patch-wasm.js +0 -26
- package/scripts/run-all-tests.mjs +0 -136
- package/scripts/smoke-test.ts +0 -94
- package/scripts/sync-mcp-plugin.js +0 -143
- package/scripts/test-no-plugin-alternates.mjs +0 -113
- package/scripts/validate-server.js +0 -46
- package/scripts/verify-automation-bridge.js +0 -200
- package/src/automation/bridge.ts +0 -630
- package/src/automation/connection-manager.ts +0 -148
- package/src/automation/handshake.ts +0 -99
- package/src/automation/index.ts +0 -2
- package/src/automation/message-handler.ts +0 -192
- package/src/automation/request-tracker.ts +0 -155
- package/src/automation/types.ts +0 -108
- package/src/cli.ts +0 -34
- package/src/config/class-aliases.ts +0 -65
- package/src/config.ts +0 -73
- package/src/constants.ts +0 -29
- package/src/graphql/loaders.ts +0 -244
- package/src/graphql/resolvers.ts +0 -1008
- package/src/graphql/schema.ts +0 -452
- package/src/graphql/server.ts +0 -156
- package/src/graphql/types.ts +0 -10
- package/src/handlers/resource-handlers.ts +0 -186
- package/src/index.ts +0 -243
- package/src/resources/actors.ts +0 -127
- package/src/resources/assets.ts +0 -286
- package/src/resources/levels.ts +0 -68
- package/src/server/resource-registry.ts +0 -47
- package/src/server/tool-registry.ts +0 -354
- package/src/server-setup.ts +0 -114
- package/src/services/health-monitor.ts +0 -132
- package/src/services/metrics-server.ts +0 -176
- package/src/tools/actors.ts +0 -564
- package/src/tools/animation.ts +0 -941
- package/src/tools/assets.ts +0 -394
- package/src/tools/audio.ts +0 -499
- package/src/tools/base-tool.ts +0 -52
- package/src/tools/behavior-tree.ts +0 -45
- package/src/tools/blueprint.ts +0 -940
- package/src/tools/consolidated-tool-definitions.ts +0 -1256
- package/src/tools/consolidated-tool-handlers.ts +0 -302
- package/src/tools/debug.ts +0 -622
- package/src/tools/dynamic-handler-registry.ts +0 -33
- package/src/tools/editor.ts +0 -435
- package/src/tools/engine.ts +0 -43
- package/src/tools/environment.ts +0 -281
- package/src/tools/foliage.ts +0 -596
- package/src/tools/handlers/actor-handlers.ts +0 -244
- package/src/tools/handlers/animation-handlers.ts +0 -237
- package/src/tools/handlers/argument-helper.ts +0 -142
- package/src/tools/handlers/asset-handlers.ts +0 -550
- package/src/tools/handlers/audio-handlers.ts +0 -194
- package/src/tools/handlers/blueprint-handlers.ts +0 -380
- package/src/tools/handlers/common-handlers.ts +0 -108
- package/src/tools/handlers/editor-handlers.ts +0 -124
- package/src/tools/handlers/effect-handlers.ts +0 -224
- package/src/tools/handlers/environment-handlers.ts +0 -183
- package/src/tools/handlers/graph-handlers.ts +0 -117
- package/src/tools/handlers/input-handlers.ts +0 -28
- package/src/tools/handlers/inspect-handlers.ts +0 -450
- package/src/tools/handlers/level-handlers.ts +0 -253
- package/src/tools/handlers/lighting-handlers.ts +0 -151
- package/src/tools/handlers/performance-handlers.ts +0 -132
- package/src/tools/handlers/pipeline-handlers.ts +0 -194
- package/src/tools/handlers/sequence-handlers.ts +0 -438
- package/src/tools/handlers/system-handlers.ts +0 -564
- package/src/tools/input.ts +0 -160
- package/src/tools/introspection.ts +0 -689
- package/src/tools/landscape.ts +0 -649
- package/src/tools/level.ts +0 -989
- package/src/tools/lighting.ts +0 -1052
- package/src/tools/logs.ts +0 -219
- package/src/tools/materials.ts +0 -295
- package/src/tools/niagara.ts +0 -485
- package/src/tools/performance.ts +0 -661
- package/src/tools/physics.ts +0 -679
- package/src/tools/property-dictionary.ts +0 -98
- package/src/tools/sequence.ts +0 -385
- package/src/tools/tool-definition-utils.ts +0 -35
- package/src/tools/ui.ts +0 -452
- package/src/types/automation-responses.ts +0 -119
- package/src/types/env.ts +0 -17
- package/src/types/handler-types.ts +0 -442
- package/src/types/responses.ts +0 -355
- package/src/types/tool-interfaces.ts +0 -250
- package/src/types/tool-types.ts +0 -575
- package/src/unreal-bridge.ts +0 -693
- package/src/utils/command-validator.ts +0 -139
- package/src/utils/elicitation.ts +0 -132
- package/src/utils/error-handler.ts +0 -287
- package/src/utils/ini-reader.ts +0 -86
- package/src/utils/logger.ts +0 -35
- package/src/utils/normalize.test.ts +0 -162
- package/src/utils/normalize.ts +0 -146
- package/src/utils/path-security.ts +0 -43
- package/src/utils/response-factory.ts +0 -44
- package/src/utils/response-validator.ts +0 -395
- package/src/utils/result-helpers.ts +0 -195
- package/src/utils/safe-json.test.ts +0 -90
- package/src/utils/safe-json.ts +0 -70
- package/src/utils/unreal-command-queue.ts +0 -166
- package/src/utils/validation.test.ts +0 -184
- package/src/utils/validation.ts +0 -312
- package/src/wasm/index.ts +0 -838
- package/test-server.mjs +0 -100
- package/tests/test-animation.mjs +0 -369
- package/tests/test-asset-advanced.mjs +0 -82
- package/tests/test-asset-graph.mjs +0 -311
- package/tests/test-audio.mjs +0 -417
- package/tests/test-automation-timeouts.mjs +0 -98
- package/tests/test-behavior-tree.mjs +0 -444
- package/tests/test-blueprint-graph.mjs +0 -410
- package/tests/test-blueprint.mjs +0 -577
- package/tests/test-client-mode.mjs +0 -86
- package/tests/test-console-command.mjs +0 -56
- package/tests/test-control-actor.mjs +0 -425
- package/tests/test-control-editor.mjs +0 -112
- package/tests/test-graphql.mjs +0 -372
- package/tests/test-input.mjs +0 -349
- package/tests/test-inspect.mjs +0 -302
- package/tests/test-landscape.mjs +0 -316
- package/tests/test-lighting.mjs +0 -428
- package/tests/test-manage-asset.mjs +0 -438
- package/tests/test-manage-level.mjs +0 -89
- package/tests/test-materials.mjs +0 -356
- package/tests/test-niagara.mjs +0 -185
- package/tests/test-no-inline-python.mjs +0 -122
- package/tests/test-performance.mjs +0 -539
- package/tests/test-plugin-handshake.mjs +0 -82
- package/tests/test-runner.mjs +0 -993
- package/tests/test-sequence.mjs +0 -104
- package/tests/test-system.mjs +0 -96
- package/tests/test-wasm.mjs +0 -283
- package/tests/test-world-partition.mjs +0 -215
- package/tsconfig.json +0 -56
- package/vitest.config.ts +0 -35
- package/wasm/Cargo.lock +0 -363
- package/wasm/Cargo.toml +0 -42
- package/wasm/LICENSE +0 -21
- package/wasm/README.md +0 -253
- package/wasm/src/dependency_resolver.rs +0 -377
- package/wasm/src/lib.rs +0 -153
- package/wasm/src/property_parser.rs +0 -271
- package/wasm/src/transform_math.rs +0 -396
- package/wasm/tests/integration.rs +0 -109
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validates console commands before execution to prevent dangerous operations.
|
|
3
|
-
* Blocks crash-inducing commands, shell injection, and Python execution.
|
|
4
|
-
*/
|
|
5
|
-
export class CommandValidator {
|
|
6
|
-
/**
|
|
7
|
-
* Commands that can crash the engine or cause severe instability.
|
|
8
|
-
* These are blocked unconditionally.
|
|
9
|
-
*/
|
|
10
|
-
private static readonly DANGEROUS_COMMANDS = [
|
|
11
|
-
// Engine termination commands
|
|
12
|
-
'quit', 'exit', 'kill', 'crash',
|
|
13
|
-
// Crash-inducing commands
|
|
14
|
-
'r.gpucrash', 'r.crash', 'debug crash', 'forcecrash', 'debug break',
|
|
15
|
-
'assert false', 'check(false)',
|
|
16
|
-
// View buffer commands that can crash on some hardware
|
|
17
|
-
'viewmode visualizebuffer basecolor',
|
|
18
|
-
'viewmode visualizebuffer worldnormal',
|
|
19
|
-
// Heavy operations that can cause access violations if systems not initialized
|
|
20
|
-
'buildpaths', 'rebuildnavigation',
|
|
21
|
-
// Heavy debug commands that can stall or crash
|
|
22
|
-
'obj garbage', 'obj list', 'memreport',
|
|
23
|
-
// Potentially destructive without proper setup
|
|
24
|
-
'delete', 'destroy'
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Tokens that indicate shell injection or external system access attempts.
|
|
29
|
-
* Any command containing these is blocked.
|
|
30
|
-
*/
|
|
31
|
-
private static readonly FORBIDDEN_TOKENS = [
|
|
32
|
-
// Shell commands (Windows/Unix)
|
|
33
|
-
'rm ', 'rm-', 'del ', 'format ', 'shutdown', 'reboot',
|
|
34
|
-
'rmdir', 'mklink', 'copy ', 'move ', 'start "', 'system(',
|
|
35
|
-
// Python injection attempts
|
|
36
|
-
'import os', 'import subprocess', 'subprocess.', 'os.system',
|
|
37
|
-
'exec(', 'eval(', '__import__', 'import sys', 'import importlib',
|
|
38
|
-
'with open', 'open(', 'write(', 'read('
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Patterns that indicate obviously invalid commands.
|
|
43
|
-
* Used to warn about likely typos or invalid input.
|
|
44
|
-
*/
|
|
45
|
-
private static readonly INVALID_PATTERNS = [
|
|
46
|
-
/^\d+$/, // Just numbers
|
|
47
|
-
/^invalid_command/i,
|
|
48
|
-
/^this_is_not_a_valid/i,
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Pre-compiled patterns for dangerous commands using word boundaries.
|
|
53
|
-
* This prevents false positives like 'show exit menu' matching 'exit'.
|
|
54
|
-
*/
|
|
55
|
-
private static readonly DANGEROUS_PATTERNS = CommandValidator.DANGEROUS_COMMANDS.map(
|
|
56
|
-
cmd => new RegExp(`(?:^|\\s)${cmd.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:\\s|$)`, 'i')
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Validates a console command for safety before execution.
|
|
61
|
-
* @param command - The console command string to validate
|
|
62
|
-
* @throws Error if the command is dangerous, contains forbidden tokens, or is invalid
|
|
63
|
-
*/
|
|
64
|
-
static validate(command: string): void {
|
|
65
|
-
if (!command || typeof command !== 'string') {
|
|
66
|
-
throw new Error('Invalid command: must be a non-empty string');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const cmdTrimmed = command.trim();
|
|
70
|
-
if (cmdTrimmed.length === 0) {
|
|
71
|
-
return; // Empty commands are technically valid (no-op)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (cmdTrimmed.includes('\n') || cmdTrimmed.includes('\r')) {
|
|
75
|
-
throw new Error('Multi-line console commands are not allowed. Send one command per call.');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const cmdLower = cmdTrimmed.toLowerCase();
|
|
79
|
-
|
|
80
|
-
if (cmdLower === 'py' || cmdLower.startsWith('py ')) {
|
|
81
|
-
throw new Error('Python console commands are blocked from external calls for safety.');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Use word-boundary matching to avoid false positives like 'show exit menu'
|
|
85
|
-
if (this.DANGEROUS_PATTERNS.some(pattern => pattern.test(cmdLower))) {
|
|
86
|
-
throw new Error(`Dangerous command blocked: ${command}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (cmdLower.includes('&&') || cmdLower.includes('||')) {
|
|
90
|
-
throw new Error('Command chaining with && or || is blocked for safety.');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Block semicolon and pipe which can also be used for command chaining/injection
|
|
94
|
-
if (cmdTrimmed.includes(';')) {
|
|
95
|
-
throw new Error('Command chaining with ; (semicolon) is blocked for safety.');
|
|
96
|
-
}
|
|
97
|
-
if (cmdTrimmed.includes('|')) {
|
|
98
|
-
throw new Error('Command piping with | is blocked for safety.');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (this.FORBIDDEN_TOKENS.some(token => cmdLower.includes(token))) {
|
|
102
|
-
throw new Error(`Command contains unsafe token and was blocked: ${command}`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Block backticks which can be used for shell execution
|
|
106
|
-
if (cmdTrimmed.includes('`')) {
|
|
107
|
-
throw new Error('Backtick characters are blocked for safety.');
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Check if a command looks like an obviously invalid or mistyped command.
|
|
113
|
-
* @param command - The command to check
|
|
114
|
-
* @returns true if the command matches known invalid patterns
|
|
115
|
-
*/
|
|
116
|
-
static isLikelyInvalid(command: string): boolean {
|
|
117
|
-
const cmdTrimmed = command.trim();
|
|
118
|
-
return this.INVALID_PATTERNS.some(pattern => pattern.test(cmdTrimmed));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Get the priority level of a command for throttling purposes.
|
|
123
|
-
* Lower numbers indicate heavier operations that need more throttling.
|
|
124
|
-
* @param command - The command to evaluate
|
|
125
|
-
* @returns Priority level (1=heavy, 5=medium, 7=default, 8-9=light)
|
|
126
|
-
*/
|
|
127
|
-
static getPriority(command: string): number {
|
|
128
|
-
if (command.includes('BuildLighting') || command.includes('BuildPaths')) {
|
|
129
|
-
return 1; // Heavy operation
|
|
130
|
-
} else if (command.includes('summon') || command.includes('spawn')) {
|
|
131
|
-
return 5; // Medium operation
|
|
132
|
-
} else if (command.startsWith('stat')) {
|
|
133
|
-
return 8; // Dedicated throttling for stat commands
|
|
134
|
-
} else if (command.startsWith('show')) {
|
|
135
|
-
return 9; // Light operation
|
|
136
|
-
}
|
|
137
|
-
return 7; // Default priority
|
|
138
|
-
}
|
|
139
|
-
}
|
package/src/utils/elicitation.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
-
import { Logger } from './logger.js';
|
|
3
|
-
|
|
4
|
-
// Minimal helper to opportunistically use MCP Elicitation when available.
|
|
5
|
-
// Safe across clients: validates schema shape and handles timeouts and -32601 errors.
|
|
6
|
-
export type PrimitiveSchema =
|
|
7
|
-
| { type: 'string'; title?: string; description?: string; minLength?: number; maxLength?: number; pattern?: string; format?: 'email'|'uri'|'date'|'date-time'; default?: string }
|
|
8
|
-
| { type: 'number'|'integer'; title?: string; description?: string; minimum?: number; maximum?: number; default?: number }
|
|
9
|
-
| { type: 'boolean'; title?: string; description?: string; default?: boolean }
|
|
10
|
-
| { type: 'string'; enum: string[]; enumNames?: string[]; title?: string; description?: string; default?: string };
|
|
11
|
-
|
|
12
|
-
export interface ElicitSchema {
|
|
13
|
-
type: 'object';
|
|
14
|
-
properties: Record<string, PrimitiveSchema>;
|
|
15
|
-
required?: string[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ElicitOptions {
|
|
19
|
-
timeoutMs?: number;
|
|
20
|
-
// Handler invoked when elicitation cannot be performed; previously named
|
|
21
|
-
// Handler invoked when elicitation cannot be performed.
|
|
22
|
-
alternate?: () => Promise<{ ok: boolean; value?: any; error?: string }>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function createElicitationHelper(server: Server, log: Logger) {
|
|
26
|
-
// We do not require explicit capability detection: we optimistically try once
|
|
27
|
-
// and disable on a Method-not-found (-32601) error for the session.
|
|
28
|
-
let supported = true; // optimistic; will be set false on first failure
|
|
29
|
-
|
|
30
|
-
const MIN_TIMEOUT_MS = 30_000;
|
|
31
|
-
const MAX_TIMEOUT_MS = 10 * 60 * 1000;
|
|
32
|
-
const DEFAULT_TIMEOUT_MS = 3 * 60 * 1000;
|
|
33
|
-
|
|
34
|
-
const timeoutEnvRaw = process.env.MCP_ELICITATION_TIMEOUT_MS ?? process.env.ELICITATION_TIMEOUT_MS ?? '';
|
|
35
|
-
const parsedEnvTimeout = Number.parseInt(timeoutEnvRaw, 10);
|
|
36
|
-
const defaultTimeoutMs = Number.isFinite(parsedEnvTimeout) && parsedEnvTimeout > 0
|
|
37
|
-
? Math.min(Math.max(parsedEnvTimeout, MIN_TIMEOUT_MS), MAX_TIMEOUT_MS)
|
|
38
|
-
: DEFAULT_TIMEOUT_MS;
|
|
39
|
-
|
|
40
|
-
if (timeoutEnvRaw) {
|
|
41
|
-
log.debug('Configured elicitation timeout override detected', {
|
|
42
|
-
defaultTimeoutMs,
|
|
43
|
-
fromEnv: timeoutEnvRaw
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function isSafeSchema(schema: ElicitSchema): boolean {
|
|
48
|
-
if (!schema || schema.type !== 'object' || typeof schema.properties !== 'object') return false;
|
|
49
|
-
|
|
50
|
-
const propertyEntries = Object.entries(schema.properties ?? {});
|
|
51
|
-
const propertyKeys = propertyEntries.map(([key]) => key);
|
|
52
|
-
|
|
53
|
-
if (schema.required) {
|
|
54
|
-
if (!Array.isArray(schema.required)) return false;
|
|
55
|
-
const invalidRequired = schema.required.some((key) => typeof key !== 'string' || !propertyKeys.includes(key));
|
|
56
|
-
if (invalidRequired) return false;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return propertyEntries.every(([, rawSchema]) => {
|
|
60
|
-
if (!rawSchema || typeof rawSchema !== 'object') return false;
|
|
61
|
-
const primitive = rawSchema as PrimitiveSchema & { properties?: unknown; items?: unknown }; // narrow for guards
|
|
62
|
-
|
|
63
|
-
if ('properties' in primitive || 'items' in primitive) return false; // nested schemas unsupported
|
|
64
|
-
|
|
65
|
-
if (Array.isArray((primitive as any).enum)) {
|
|
66
|
-
const enumValues = (primitive as any).enum;
|
|
67
|
-
const allStrings = enumValues.every((value: unknown) => typeof value === 'string');
|
|
68
|
-
if (!allStrings) return false;
|
|
69
|
-
return !('type' in primitive) || (primitive as any).type === 'string';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if ((primitive as any).type === 'string') return true;
|
|
73
|
-
if ((primitive as any).type === 'number' || (primitive as any).type === 'integer') return true;
|
|
74
|
-
if ((primitive as any).type === 'boolean') return true;
|
|
75
|
-
|
|
76
|
-
return false;
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async function elicit(message: string, requestedSchema: ElicitSchema, opts: ElicitOptions = {}) {
|
|
81
|
-
if (!supported || !isSafeSchema(requestedSchema)) {
|
|
82
|
-
if (opts.alternate) return opts.alternate();
|
|
83
|
-
return { ok: false, error: 'elicitation-unsupported' };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const params = { message, requestedSchema } as any;
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
const elicitMethod = (server as any)?.elicitInput;
|
|
90
|
-
if (typeof elicitMethod !== 'function') {
|
|
91
|
-
supported = false;
|
|
92
|
-
throw new Error('elicitInput-not-available');
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const requestedTimeout = opts.timeoutMs;
|
|
96
|
-
const timeoutMs = Math.max(MIN_TIMEOUT_MS, requestedTimeout ?? defaultTimeoutMs);
|
|
97
|
-
const res: any = await elicitMethod.call(server, params, { timeout: timeoutMs });
|
|
98
|
-
const action = res?.action;
|
|
99
|
-
const content = res?.content;
|
|
100
|
-
|
|
101
|
-
if (action === 'accept') return { ok: true, value: content };
|
|
102
|
-
if (action === 'decline' || action === 'cancel') {
|
|
103
|
-
if (opts.alternate) return opts.alternate();
|
|
104
|
-
return { ok: false, error: action };
|
|
105
|
-
}
|
|
106
|
-
if (opts.alternate) return opts.alternate();
|
|
107
|
-
return { ok: false, error: 'unexpected-response' };
|
|
108
|
-
} catch (e: any) {
|
|
109
|
-
const msg = String(e?.message || e);
|
|
110
|
-
const code = (e as any)?.code ?? (e as any)?.error?.code;
|
|
111
|
-
// If client doesn't support it, don’t try again this session
|
|
112
|
-
if (
|
|
113
|
-
msg.includes('Method not found') ||
|
|
114
|
-
msg.includes('elicitInput-not-available') ||
|
|
115
|
-
msg.includes('request-not-available') ||
|
|
116
|
-
String(code) === '-32601'
|
|
117
|
-
) {
|
|
118
|
-
supported = false;
|
|
119
|
-
}
|
|
120
|
-
// Use an alternate handler if provided when elicitation fails.
|
|
121
|
-
log.debug('Elicitation failed; using alternate handler', { error: msg, code });
|
|
122
|
-
if (opts.alternate) return opts.alternate();
|
|
123
|
-
return { ok: false, error: msg.includes('timeout') ? 'timeout' : 'rpc-failed' };
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
supports: () => supported,
|
|
129
|
-
elicit,
|
|
130
|
-
getDefaultTimeoutMs: () => defaultTimeoutMs
|
|
131
|
-
};
|
|
132
|
-
}
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import { Logger } from './logger.js';
|
|
2
|
-
import { BaseToolResponse } from '../types/tool-types.js';
|
|
3
|
-
|
|
4
|
-
const log = new Logger('ErrorHandler');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Error types for categorization
|
|
8
|
-
*/
|
|
9
|
-
export enum ErrorType {
|
|
10
|
-
VALIDATION = 'VALIDATION',
|
|
11
|
-
CONNECTION = 'CONNECTION',
|
|
12
|
-
UNREAL_ENGINE = 'UNREAL_ENGINE',
|
|
13
|
-
PARAMETER = 'PARAMETER',
|
|
14
|
-
EXECUTION = 'EXECUTION',
|
|
15
|
-
TIMEOUT = 'TIMEOUT',
|
|
16
|
-
UNKNOWN = 'UNKNOWN'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Debug information attached to error responses in development mode
|
|
21
|
-
*/
|
|
22
|
-
interface ErrorResponseDebug {
|
|
23
|
-
errorType: ErrorType;
|
|
24
|
-
originalError: string;
|
|
25
|
-
stack?: string;
|
|
26
|
-
context?: Record<string, unknown>;
|
|
27
|
-
retriable: boolean;
|
|
28
|
-
scope: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Extended error response with optional debug info
|
|
33
|
-
*/
|
|
34
|
-
interface ErrorToolResponse extends BaseToolResponse {
|
|
35
|
-
_debug?: ErrorResponseDebug;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Represents any error object with common properties
|
|
40
|
-
*/
|
|
41
|
-
interface ErrorLike {
|
|
42
|
-
message?: string;
|
|
43
|
-
code?: string;
|
|
44
|
-
type?: string;
|
|
45
|
-
errorType?: string;
|
|
46
|
-
stack?: string;
|
|
47
|
-
response?: { status?: number };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Normalize any error type to ErrorLike interface
|
|
52
|
-
*/
|
|
53
|
-
function normalizeErrorToLike(error: unknown): ErrorLike {
|
|
54
|
-
if (error instanceof Error) {
|
|
55
|
-
return {
|
|
56
|
-
message: error.message,
|
|
57
|
-
stack: error.stack,
|
|
58
|
-
code: (error as NodeJS.ErrnoException).code
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
if (typeof error === 'object' && error !== null) {
|
|
62
|
-
const obj = error as Record<string, unknown>;
|
|
63
|
-
return {
|
|
64
|
-
message: typeof obj.message === 'string' ? obj.message : undefined,
|
|
65
|
-
code: typeof obj.code === 'string' ? obj.code : undefined,
|
|
66
|
-
type: typeof obj.type === 'string' ? obj.type : undefined,
|
|
67
|
-
errorType: typeof obj.errorType === 'string' ? obj.errorType : undefined,
|
|
68
|
-
stack: typeof obj.stack === 'string' ? obj.stack : undefined,
|
|
69
|
-
response: typeof obj.response === 'object' && obj.response !== null
|
|
70
|
-
? {
|
|
71
|
-
status: typeof (obj.response as Record<string, unknown>).status === 'number'
|
|
72
|
-
? (obj.response as Record<string, unknown>).status as number
|
|
73
|
-
: undefined
|
|
74
|
-
}
|
|
75
|
-
: undefined
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
return { message: String(error) };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Consistent error handling for all tools
|
|
83
|
-
*/
|
|
84
|
-
export class ErrorHandler {
|
|
85
|
-
/**
|
|
86
|
-
* Create a standardized error response
|
|
87
|
-
* @param error - The error object (can be Error, string, object with message, or unknown)
|
|
88
|
-
* @param toolName - Name of the tool that failed
|
|
89
|
-
* @param context - Optional additional context for debugging
|
|
90
|
-
*/
|
|
91
|
-
static createErrorResponse(
|
|
92
|
-
error: unknown,
|
|
93
|
-
toolName: string,
|
|
94
|
-
context?: Record<string, unknown>
|
|
95
|
-
): ErrorToolResponse {
|
|
96
|
-
const errorObj = normalizeErrorToLike(error);
|
|
97
|
-
const errorType = this.categorizeError(errorObj);
|
|
98
|
-
const userMessage = this.getUserFriendlyMessage(errorType, errorObj);
|
|
99
|
-
const retriable = this.isRetriable(errorObj);
|
|
100
|
-
const scope = (context?.scope as string) || `tool-call/${toolName}`;
|
|
101
|
-
const errorMessage = errorObj.message || String(error);
|
|
102
|
-
const errorStack = errorObj.stack;
|
|
103
|
-
|
|
104
|
-
log.error(`Tool ${toolName} failed:`, {
|
|
105
|
-
type: errorType,
|
|
106
|
-
message: errorMessage,
|
|
107
|
-
retriable,
|
|
108
|
-
scope,
|
|
109
|
-
context
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const response: ErrorToolResponse = {
|
|
113
|
-
success: false,
|
|
114
|
-
error: userMessage,
|
|
115
|
-
message: `Failed to execute ${toolName}: ${userMessage}`,
|
|
116
|
-
retriable,
|
|
117
|
-
scope
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
// Add debug info in development
|
|
121
|
-
if (process.env.NODE_ENV === 'development') {
|
|
122
|
-
response._debug = {
|
|
123
|
-
errorType,
|
|
124
|
-
originalError: errorMessage,
|
|
125
|
-
stack: errorStack,
|
|
126
|
-
context,
|
|
127
|
-
retriable,
|
|
128
|
-
scope
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return response;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Categorize error by type
|
|
137
|
-
* @param error - The error to categorize
|
|
138
|
-
*/
|
|
139
|
-
private static categorizeError(error: ErrorLike | Error | string): ErrorType {
|
|
140
|
-
const errorObj = typeof error === 'object' ? error as ErrorLike : null;
|
|
141
|
-
const explicitType = (errorObj?.type || errorObj?.errorType || '').toString().toUpperCase();
|
|
142
|
-
if (explicitType && Object.values(ErrorType).includes(explicitType as ErrorType)) {
|
|
143
|
-
return explicitType as ErrorType;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const errorMessage = (errorObj?.message || String(error)).toLowerCase();
|
|
147
|
-
|
|
148
|
-
// Connection errors
|
|
149
|
-
if (
|
|
150
|
-
errorMessage.includes('econnrefused') ||
|
|
151
|
-
errorMessage.includes('timeout') ||
|
|
152
|
-
errorMessage.includes('connection') ||
|
|
153
|
-
errorMessage.includes('network')
|
|
154
|
-
) {
|
|
155
|
-
return ErrorType.CONNECTION;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Validation errors
|
|
159
|
-
if (
|
|
160
|
-
errorMessage.includes('invalid') ||
|
|
161
|
-
errorMessage.includes('required') ||
|
|
162
|
-
errorMessage.includes('must be') ||
|
|
163
|
-
errorMessage.includes('validation')
|
|
164
|
-
) {
|
|
165
|
-
return ErrorType.VALIDATION;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Unreal Engine specific errors
|
|
169
|
-
if (
|
|
170
|
-
errorMessage.includes('unreal') ||
|
|
171
|
-
errorMessage.includes('connection failed') ||
|
|
172
|
-
errorMessage.includes('blueprint') ||
|
|
173
|
-
errorMessage.includes('actor') ||
|
|
174
|
-
errorMessage.includes('asset')
|
|
175
|
-
) {
|
|
176
|
-
return ErrorType.UNREAL_ENGINE;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Parameter errors
|
|
180
|
-
if (
|
|
181
|
-
errorMessage.includes('parameter') ||
|
|
182
|
-
errorMessage.includes('argument') ||
|
|
183
|
-
errorMessage.includes('missing')
|
|
184
|
-
) {
|
|
185
|
-
return ErrorType.PARAMETER;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Timeout errors
|
|
189
|
-
if (errorMessage.includes('timeout')) {
|
|
190
|
-
return ErrorType.TIMEOUT;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return ErrorType.UNKNOWN;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Get user-friendly error message
|
|
198
|
-
* @param type - The categorized error type
|
|
199
|
-
* @param error - The original error
|
|
200
|
-
*/
|
|
201
|
-
private static getUserFriendlyMessage(type: ErrorType, error: ErrorLike | Error | string): string {
|
|
202
|
-
const originalMessage = (typeof error === 'object' && error !== null && 'message' in error)
|
|
203
|
-
? (error as { message?: string }).message || String(error)
|
|
204
|
-
: String(error);
|
|
205
|
-
|
|
206
|
-
switch (type) {
|
|
207
|
-
case ErrorType.CONNECTION:
|
|
208
|
-
return 'Failed to connect to Unreal Engine. Please ensure the Automation Bridge plugin is active and the editor is running.';
|
|
209
|
-
|
|
210
|
-
case ErrorType.VALIDATION:
|
|
211
|
-
return `Invalid input: ${originalMessage}`;
|
|
212
|
-
|
|
213
|
-
case ErrorType.UNREAL_ENGINE:
|
|
214
|
-
return `Unreal Engine error: ${originalMessage}`;
|
|
215
|
-
|
|
216
|
-
case ErrorType.PARAMETER:
|
|
217
|
-
return `Invalid parameters: ${originalMessage}`;
|
|
218
|
-
|
|
219
|
-
case ErrorType.TIMEOUT:
|
|
220
|
-
return 'Operation timed out. Unreal Engine may be busy or unresponsive.';
|
|
221
|
-
|
|
222
|
-
case ErrorType.EXECUTION:
|
|
223
|
-
return `Execution failed: ${originalMessage}`;
|
|
224
|
-
|
|
225
|
-
default:
|
|
226
|
-
return originalMessage;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Determine if an error is likely retriable
|
|
232
|
-
* @param error - The error to check
|
|
233
|
-
*/
|
|
234
|
-
private static isRetriable(error: ErrorLike | Error | string): boolean {
|
|
235
|
-
try {
|
|
236
|
-
const errorObj = typeof error === 'object' ? error as ErrorLike : null;
|
|
237
|
-
const code = (errorObj?.code || '').toString().toUpperCase();
|
|
238
|
-
const msg = (errorObj?.message || String(error) || '').toLowerCase();
|
|
239
|
-
const status = Number(errorObj?.response?.status);
|
|
240
|
-
if (['ECONNRESET', 'ECONNREFUSED', 'ETIMEDOUT', 'EPIPE'].includes(code)) return true;
|
|
241
|
-
if (/timeout|timed out|network|connection|closed|unavailable|busy|temporar/.test(msg)) return true;
|
|
242
|
-
if (!isNaN(status) && (status === 429 || (status >= 500 && status < 600))) return true;
|
|
243
|
-
} catch (err) {
|
|
244
|
-
// Error checking retriability is uncommon; log at debug level
|
|
245
|
-
log.debug('isRetriable check failed', err instanceof Error ? err.message : String(err));
|
|
246
|
-
}
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Retry a function with exponential backoff
|
|
252
|
-
* @param fn - The async function to retry
|
|
253
|
-
* @param options - Retry configuration options
|
|
254
|
-
*/
|
|
255
|
-
static async retryWithBackoff<T>(
|
|
256
|
-
fn: () => Promise<T>,
|
|
257
|
-
options: {
|
|
258
|
-
maxRetries?: number;
|
|
259
|
-
initialDelay?: number;
|
|
260
|
-
maxDelay?: number;
|
|
261
|
-
backoffMultiplier?: number;
|
|
262
|
-
shouldRetry?: (error: ErrorLike | Error | unknown) => boolean;
|
|
263
|
-
} = {}
|
|
264
|
-
): Promise<T> {
|
|
265
|
-
const maxRetries = options.maxRetries ?? 3;
|
|
266
|
-
const initialDelay = options.initialDelay ?? 1000;
|
|
267
|
-
const maxDelay = options.maxDelay ?? 10000;
|
|
268
|
-
const multiplier = options.backoffMultiplier ?? 2;
|
|
269
|
-
const shouldRetry = options.shouldRetry ?? ((err: unknown) => this.isRetriable(err as ErrorLike));
|
|
270
|
-
|
|
271
|
-
let delay = initialDelay;
|
|
272
|
-
|
|
273
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
274
|
-
try {
|
|
275
|
-
return await fn();
|
|
276
|
-
} catch (error) {
|
|
277
|
-
if (attempt === maxRetries || !shouldRetry(error)) {
|
|
278
|
-
throw error;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
282
|
-
delay = Math.min(delay * multiplier, maxDelay);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
throw new Error('Max retries exceeded');
|
|
286
|
-
}
|
|
287
|
-
}
|
package/src/utils/ini-reader.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
export async function readIniFile(filePath: string): Promise<Record<string, Record<string, string>>> {
|
|
5
|
-
try {
|
|
6
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
7
|
-
const result: Record<string, Record<string, string>> = {};
|
|
8
|
-
let currentSection = '';
|
|
9
|
-
|
|
10
|
-
const lines = content.split(/\r?\n/);
|
|
11
|
-
for (const line of lines) {
|
|
12
|
-
const trimmed = line.trim();
|
|
13
|
-
if (!trimmed || trimmed.startsWith(';') || trimmed.startsWith('#')) {
|
|
14
|
-
continue;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
18
|
-
currentSection = trimmed.substring(1, trimmed.length - 1);
|
|
19
|
-
result[currentSection] = {};
|
|
20
|
-
} else if (currentSection) {
|
|
21
|
-
const parts = trimmed.split('=');
|
|
22
|
-
if (parts.length >= 2) {
|
|
23
|
-
const key = parts[0].trim();
|
|
24
|
-
const value = parts.slice(1).join('=').trim();
|
|
25
|
-
result[currentSection][key] = value;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return result;
|
|
31
|
-
} catch (error) {
|
|
32
|
-
throw new Error(`Failed to read INI file at ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function getProjectSetting(projectPath: string, category: string, sectionName: string, key?: string): Promise<any> {
|
|
37
|
-
// Normalize project path to directory
|
|
38
|
-
let dirPath = projectPath;
|
|
39
|
-
if (dirPath.toLowerCase().endsWith('.uproject')) {
|
|
40
|
-
dirPath = path.dirname(dirPath);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Possible file names/locations in order of preference (Config/DefaultX.ini, Saved/Config/WindowsEditor/X.ini)
|
|
44
|
-
// category is usually 'Project', 'Engine', 'Game', 'Input', etc.
|
|
45
|
-
const cleanCategory = category.replace(/^Default/, ''); // If caller passed 'DefaultEngine', normalize to 'Engine'
|
|
46
|
-
|
|
47
|
-
const candidates = [
|
|
48
|
-
path.join(dirPath, 'Config', `Default${cleanCategory}.ini`),
|
|
49
|
-
path.join(dirPath, 'Saved', 'Config', 'WindowsEditor', `${cleanCategory}.ini`),
|
|
50
|
-
path.join(dirPath, 'Saved', 'Config', 'Windows', `${cleanCategory}.ini`),
|
|
51
|
-
path.join(dirPath, 'Saved', 'Config', 'Mac', `${cleanCategory}.ini`),
|
|
52
|
-
path.join(dirPath, 'Saved', 'Config', 'Linux', `${cleanCategory}.ini`)
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
for (const configPath of candidates) {
|
|
56
|
-
try {
|
|
57
|
-
const iniData = await readIniFile(configPath);
|
|
58
|
-
// If we successfully read the file, check for the section
|
|
59
|
-
if (sectionName) {
|
|
60
|
-
const section = iniData[sectionName];
|
|
61
|
-
if (section) {
|
|
62
|
-
if (key) {
|
|
63
|
-
return section[key];
|
|
64
|
-
}
|
|
65
|
-
return section;
|
|
66
|
-
}
|
|
67
|
-
// If section not found in this file, continue to next candidate?
|
|
68
|
-
// Usually we want the most authoritative, but if it's missing the section, maybe it's in another?
|
|
69
|
-
// For now, if we find the file, we return the data from it or null if section missing.
|
|
70
|
-
// Merging is complex without a proper config hierarchy implementation.
|
|
71
|
-
// We will assume if the file exists, it's the one we want, or if section is missing, we fail for this file.
|
|
72
|
-
// But 'Default' might lack user overrides.
|
|
73
|
-
// Given this is a simple reader, we'll return the first match that contains the section,
|
|
74
|
-
// or if sectionName is empty, the first file found.
|
|
75
|
-
} else {
|
|
76
|
-
if (Object.keys(iniData).length > 0) {
|
|
77
|
-
return iniData;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
} catch (_e) {
|
|
81
|
-
// Continue to next candidate
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return null;
|
|
86
|
-
}
|
package/src/utils/logger.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2
|
-
|
|
3
|
-
export class Logger {
|
|
4
|
-
private level: LogLevel;
|
|
5
|
-
|
|
6
|
-
constructor(private scope: string, level: LogLevel = 'info') {
|
|
7
|
-
const envLevel = (process.env.LOG_LEVEL || process.env.LOGLEVEL || level).toString().toLowerCase();
|
|
8
|
-
this.level = (['debug', 'info', 'warn', 'error'] as LogLevel[]).includes(envLevel as LogLevel)
|
|
9
|
-
? (envLevel as LogLevel)
|
|
10
|
-
: 'info';
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
private shouldLog(level: LogLevel) {
|
|
14
|
-
const order: LogLevel[] = ['debug', 'info', 'warn', 'error'];
|
|
15
|
-
return order.indexOf(level) >= order.indexOf(this.level);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
debug(...args: any[]) {
|
|
19
|
-
if (!this.shouldLog('debug')) return;
|
|
20
|
-
// Write to stderr to avoid corrupting MCP stdout stream
|
|
21
|
-
console.error(`[${this.scope}]`, ...args);
|
|
22
|
-
}
|
|
23
|
-
info(...args: any[]) {
|
|
24
|
-
if (!this.shouldLog('info')) return;
|
|
25
|
-
// Write to stderr to avoid corrupting MCP stdout stream
|
|
26
|
-
console.error(`[${this.scope}]`, ...args);
|
|
27
|
-
}
|
|
28
|
-
warn(...args: any[]) {
|
|
29
|
-
if (!this.shouldLog('warn')) return;
|
|
30
|
-
console.warn(`[${this.scope}]`, ...args);
|
|
31
|
-
}
|
|
32
|
-
error(...args: any[]) {
|
|
33
|
-
if (this.shouldLog('error')) console.error(`[${this.scope}]`, ...args);
|
|
34
|
-
}
|
|
35
|
-
}
|