@hybridlabor-api/aos 4.3.0 → 4.4.0
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/.claude/hooks/memb-inject.mjs +121 -0
- package/.claude/settings.json +10 -0
- package/README.de.md +0 -2
- package/README.md +0 -2
- package/README.pt.md +0 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/docs/skills_table.md +0 -2
- package/installer.js +17 -6
- package/package.json +16 -2
- package/skills/global_config/aos-project-init/SKILL.md +194 -0
- package/skills/global_config/aos-project-init/assets/AGENTS.template.md +56 -0
- package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +137 -0
- package/skills/global_config/aos-setup/SKILL.md +222 -0
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +262 -0
- package/skills/global_config/ask-tim/SKILL.md +2 -2
- package/assets/Give_AI_Agents_Control_of_Creative_Software.mp4 +0 -0
- package/mcps/RhinoMCP/connector/icon-dark.png +0 -3
- package/mcps/RhinoMCP/connector/icon-light.png +0 -3
- package/mcps/RhinoMCP/connector/screenshots/casa-rhino.png +0 -3
- package/mcps/RhinoMCP/docs/assets/css/custom.css +0 -640
- package/mcps/RhinoMCP/docs/content/_index.md +0 -88
- package/mcps/RhinoMCP/docs/content/docs/_index.md +0 -35
- package/mcps/RhinoMCP/docs/content/docs/advanced/_index.md +0 -37
- package/mcps/RhinoMCP/docs/content/docs/advanced/bulk-file-processing.md +0 -70
- package/mcps/RhinoMCP/docs/content/docs/advanced/headless-render-farm.md +0 -60
- package/mcps/RhinoMCP/docs/content/docs/advanced/make-this-parametric.md +0 -56
- package/mcps/RhinoMCP/docs/content/docs/advanced/sketch-to-model.md +0 -58
- package/mcps/RhinoMCP/docs/content/docs/advanced/upgrade-gh1-to-gh2.md +0 -51
- package/mcps/RhinoMCP/docs/content/docs/developers/_index.md +0 -39
- package/mcps/RhinoMCP/docs/content/docs/developers/dev-troubleshooting.md +0 -15
- package/mcps/RhinoMCP/docs/content/docs/developers/plugin-prototyping.md +0 -56
- package/mcps/RhinoMCP/docs/content/docs/developers/upgrade-gh1-to-gh2.md +0 -98
- package/mcps/RhinoMCP/docs/content/docs/developers/upgrade-to-netcore.md +0 -53
- package/mcps/RhinoMCP/docs/content/docs/developers/windows-to-cross-platform.md +0 -58
- package/mcps/RhinoMCP/docs/content/docs/developers/wpf-to-eto.md +0 -64
- package/mcps/RhinoMCP/docs/content/docs/getting-started/_index.md +0 -45
- package/mcps/RhinoMCP/docs/content/docs/getting-started/cc-plugin.md +0 -116
- package/mcps/RhinoMCP/docs/content/docs/getting-started/connector.md +0 -65
- package/mcps/RhinoMCP/docs/content/docs/getting-started/copilot.md +0 -61
- package/mcps/RhinoMCP/docs/content/docs/getting-started/lm-studio.md +0 -62
- package/mcps/RhinoMCP/docs/content/docs/troubleshooting.md +0 -66
- package/mcps/RhinoMCP/docs/content/docs/try-it-out/_index.md +0 -39
- package/mcps/RhinoMCP/docs/content/docs/try-it-out/examples/_index.md +0 -25
- package/mcps/RhinoMCP/docs/content/docs/try-it-out/examples/build-grasshopper.md +0 -26
- package/mcps/RhinoMCP/docs/content/docs/try-it-out/examples/generate-variations.md +0 -25
- package/mcps/RhinoMCP/docs/content/docs/try-it-out/examples/inspect-and-report.md +0 -26
- package/mcps/RhinoMCP/docs/content/docs/try-it-out/examples/layers.md +0 -28
- package/mcps/RhinoMCP/docs/content/docs/try-it-out/examples/model-from-image.md +0 -27
- package/mcps/RhinoMCP/docs/content/docs/try-it-out/recipes.md +0 -178
- package/mcps/RhinoMCP/docs/data/icons.yaml +0 -3
- package/mcps/RhinoMCP/docs/go.mod +0 -5
- package/mcps/RhinoMCP/docs/go.sum +0 -4
- package/mcps/RhinoMCP/docs/hugo.yaml +0 -78
- package/mcps/RhinoMCP/docs/layouts/_partials/sidebar.html +0 -333
- package/mcps/RhinoMCP/docs/layouts/docs/list.html +0 -29
- package/mcps/RhinoMCP/docs/layouts/docs/single.html +0 -29
- package/mcps/RhinoMCP/docs/layouts/partials/custom/head-end.html +0 -3
- package/mcps/RhinoMCP/docs/layouts/shortcodes/download-asset.html +0 -21
- package/mcps/RhinoMCP/docs/layouts/shortcodes/github.html +0 -21
- package/mcps/RhinoMCP/docs/layouts/shortcodes/prompt.html +0 -23
- package/mcps/RhinoMCP/docs/layouts/shortcodes/yak.html +0 -21
- package/mcps/RhinoMCP/docs/static/developer/sel-arc.png +0 -3
- package/mcps/RhinoMCP/docs/static/developer/voxelizer-gh2-conversion.png +0 -3
- package/mcps/RhinoMCP/docs/static/examples/ai-kettle.png +0 -3
- package/mcps/RhinoMCP/docs/static/examples/casa_rhino_shapes.png +0 -3
- package/mcps/RhinoMCP/docs/static/examples/kettle.jpg +0 -0
- package/mcps/RhinoMCP/docs/static/examples/raygun-layers.png +0 -3
- package/mcps/RhinoMCP/docs/static/examples/raygun-thumbnail.png +0 -3
- package/mcps/RhinoMCP/docs/static/examples/twisty-tower-gh.png +0 -3
- package/mcps/RhinoMCP/docs/static/favicon.svg +0 -26
- package/mcps/RhinoMCP/docs/static/images/landing-dark.png +0 -3
- package/mcps/RhinoMCP/docs/static/images/landing.png +0 -3
- package/mcps/RhinoMCP/docs/static/images/logo-dark.svg +0 -26
- package/mcps/RhinoMCP/docs/static/images/logo.svg +0 -26
- package/mcps/RhinoMCP/docs/static/local-llm.png +0 -3
- package/mcps/RhinoMCP/rhino/plugin/icon.png +0 -3
- package/mcps/RhinoMCP/tests/Acp.Tests/Acp.Tests.csproj +0 -29
- package/mcps/RhinoMCP/tests/Acp.Tests/CoverageTests.cs +0 -52
- package/mcps/RhinoMCP/tests/Acp.Tests/Fakes.cs +0 -90
- package/mcps/RhinoMCP/tests/Acp.Tests/GlobalUsings.cs +0 -1
- package/mcps/RhinoMCP/tests/Acp.Tests/LoopbackTests.cs +0 -59
- package/mcps/RhinoMCP/tests/Acp.Tests/RobustnessTests.cs +0 -124
- package/mcps/RhinoMCP/tests/Acp.Tests/SerializationTests.cs +0 -94
- package/mcps/RhinoMCP/tests/Integration.Tests/AdoptedSlotTests.cs +0 -136
- package/mcps/RhinoMCP/tests/Integration.Tests/AutoSpawnNotificationTests.cs +0 -63
- package/mcps/RhinoMCP/tests/Integration.Tests/CloseSlotAgentTests.cs +0 -56
- package/mcps/RhinoMCP/tests/Integration.Tests/CloseSlotTests.cs +0 -37
- package/mcps/RhinoMCP/tests/Integration.Tests/DocLifecycleTests.cs +0 -42
- package/mcps/RhinoMCP/tests/Integration.Tests/GlobalUsings.cs +0 -3
- package/mcps/RhinoMCP/tests/Integration.Tests/GrasshopperStartTests.cs +0 -56
- package/mcps/RhinoMCP/tests/Integration.Tests/Harness/ReturnResult.cs +0 -28
- package/mcps/RhinoMCP/tests/Integration.Tests/Harness/RhinoMcpFixture.cs +0 -90
- package/mcps/RhinoMCP/tests/Integration.Tests/Harness/RhinoMcpRouter.cs +0 -111
- package/mcps/RhinoMCP/tests/Integration.Tests/Harness/RhinoRouterPaths.cs +0 -83
- package/mcps/RhinoMCP/tests/Integration.Tests/Harness/RouterFixture.cs +0 -50
- package/mcps/RhinoMCP/tests/Integration.Tests/Integration.Tests.csproj +0 -31
- package/mcps/RhinoMCP/tests/Integration.Tests/ListSlotsShapeTests.cs +0 -55
- package/mcps/RhinoMCP/tests/Integration.Tests/ListSlotsTests.cs +0 -19
- package/mcps/RhinoMCP/tests/Integration.Tests/MacSharedProcessTests.cs +0 -87
- package/mcps/RhinoMCP/tests/Integration.Tests/MultiRouterTests.cs +0 -74
- package/mcps/RhinoMCP/tests/Integration.Tests/PluginToolTests.cs +0 -115
- package/mcps/RhinoMCP/tests/Integration.Tests/README.md +0 -35
- package/mcps/RhinoMCP/tests/Integration.Tests/RhinoCrashHandlingTests.cs +0 -107
- package/mcps/RhinoMCP/tests/Integration.Tests/SlotReapingTests.cs +0 -84
- package/mcps/RhinoMCP/tests/Integration.Tests/SpawnErrorTests.cs +0 -52
- package/mcps/RhinoMCP/tests/Integration.Tests/SpawnSlotTests.cs +0 -66
- package/mcps/RhinoMCP/tests/Integration.Tests/ToolDispatchBySlotTests.cs +0 -53
- package/mcps/RhinoMCP/tests/Integration.Tests/WindowsProcessIsolationTests.cs +0 -62
- package/mcps/RhinoMCP/tests/Router.Tests/CodegenTests.cs +0 -125
- package/mcps/RhinoMCP/tests/Router.Tests/ReturnResultTests.cs +0 -90
- package/mcps/RhinoMCP/tests/Router.Tests/RhinoCrashReportFinderTests.cs +0 -207
- package/mcps/RhinoMCP/tests/Router.Tests/RhinoLocatorOverrideTests.cs +0 -61
- package/mcps/RhinoMCP/tests/Router.Tests/RhinoLocatorTests.cs +0 -38
- package/mcps/RhinoMCP/tests/Router.Tests/RhinoManagerResolutionTests.cs +0 -151
- package/mcps/RhinoMCP/tests/Router.Tests/Router.Tests.csproj +0 -31
- package/mcps/RhinoMCP/tests/Router.Tests/RouterConfigTests.cs +0 -92
- package/mcps/RhinoMCP/tests/Router.Tests/SlotStoreLaunchingAbsenceTests.cs +0 -70
- package/mcps/RhinoMCP/tests/Router.Tests/SlotStorePortReservationTests.cs +0 -92
- package/mcps/RhinoMCP/tests/Router.Tests/SpawnDiagnosticsTests.cs +0 -100
- package/mcps/RhinoMCP/tests/Router.Tests/SpawnSlotToolDiagnoseTests.cs +0 -66
- package/mcps/RhinoMCP/tests/Server.Tests/McpConfigEditTests.cs +0 -223
- package/mcps/RhinoMCP/tests/Server.Tests/ParameterBinderTests.cs +0 -208
- package/mcps/RhinoMCP/tests/Server.Tests/ProtocolTests.cs +0 -200
- package/mcps/RhinoMCP/tests/Server.Tests/ResourceRegistryTests.cs +0 -218
- package/mcps/RhinoMCP/tests/Server.Tests/ResultUnwrapperTests.cs +0 -53
- package/mcps/RhinoMCP/tests/Server.Tests/SchemaBuilderTests.cs +0 -166
- package/mcps/RhinoMCP/tests/Server.Tests/Server.Tests.csproj +0 -40
- package/mcps/RhinoMCP/tests/StreamJson.Tests/AcpMessageMapperTests.cs +0 -82
- package/mcps/RhinoMCP/tests/StreamJson.Tests/AgentPromptsTests.cs +0 -56
- package/mcps/RhinoMCP/tests/StreamJson.Tests/AgentRegistryOverlayTests.cs +0 -88
- package/mcps/RhinoMCP/tests/StreamJson.Tests/AgentRegistryResolutionTests.cs +0 -152
- package/mcps/RhinoMCP/tests/StreamJson.Tests/AgentRunnerTurnTests.cs +0 -149
- package/mcps/RhinoMCP/tests/StreamJson.Tests/ClaudeStreamJsonParserTests.cs +0 -118
- package/mcps/RhinoMCP/tests/StreamJson.Tests/CodexStreamJsonParserTests.cs +0 -100
- package/mcps/RhinoMCP/tests/StreamJson.Tests/ConversationStorePruneTests.cs +0 -94
- package/mcps/RhinoMCP/tests/StreamJson.Tests/ConversationStoreRoundTripTests.cs +0 -70
- package/mcps/RhinoMCP/tests/StreamJson.Tests/ConversationTests.cs +0 -153
- package/mcps/RhinoMCP/tests/StreamJson.Tests/ConversationUsageTests.cs +0 -56
- package/mcps/RhinoMCP/tests/StreamJson.Tests/GlobalUsings.cs +0 -12
- package/mcps/RhinoMCP/tests/StreamJson.Tests/Shims.cs +0 -93
- package/mcps/RhinoMCP/tests/StreamJson.Tests/StreamJson.Tests.csproj +0 -56
- package/mcps/RhinoMCP/tests/StreamJson.Tests/StreamJsonAgentLoopbackTests.cs +0 -75
- package/mcps/RhinoMCP/tests/StreamJson.Tests/StreamJsonParserEdgeCaseTests.cs +0 -128
- package/mcps/RhinoMCP/tests/StreamJson.Tests/TokenUsageTests.cs +0 -40
- package/mcps/RhinoMCP/tests/launcher/launcher.test.mjs +0 -461
- package/mcps/RhinoMCP/tests/launcher/package.json +0 -8
- package/mcps/ae-mcp/docs/demo.png +0 -0
- package/mcps/ae-mcp/docs/demo1.png +0 -0
- package/mcps/ae-mcp/docs/demo3.png +0 -0
- package/mcps/ae-mcp/docs/video.png +0 -0
- package/mcps/after-effects-mcp/assets/MCP Auto Bridge.png +0 -0
- package/mcps/bdb-remoteos-mcp/tests/__init__.py +0 -1
- package/mcps/bdb-remoteos-mcp/tests/mock_incus.py +0 -60
- package/mcps/bdb-remoteos-mcp/tests/test_mcp_server.py +0 -27
- package/mcps/bdb-remoteos-mcp/tests/test_security_redteam.py +0 -349
- package/mcps/bdb-remoteos-mcp/tests/test_webhook.py +0 -61
- package/mcps/blender-mcp/assets/addon-instructions.png +0 -0
- package/mcps/blender-mcp/assets/hammer-icon.png +0 -0
- package/mcps/blender-mcp-server/docs/architecture.md +0 -209
- package/mcps/blender-mcp-server/docs/images/demo_render.png +0 -0
- package/mcps/blender-mcp-server/docs/python-execute-design.md +0 -515
- package/mcps/blender-mcp-server/tests/__init__.py +0 -0
- package/mcps/blender-mcp-server/tests/test_addon.py +0 -953
- package/mcps/blender-mcp-server/tests/test_server.py +0 -364
- package/mcps/davinci-mcp-professional/docs/README.md +0 -67
- package/mcps/davinci-mcp-professional/docs/html/README_8md.html +0 -113
- package/mcps/davinci-mcp-professional/docs/html/____init_____8py.html +0 -126
- package/mcps/davinci-mcp-professional/docs/html/____init_____8py.js +0 -6
- package/mcps/davinci-mcp-professional/docs/html/____init_____8py_source.html +0 -125
- package/mcps/davinci-mcp-professional/docs/html/__version_8py.html +0 -130
- package/mcps/davinci-mcp-professional/docs/html/__version_8py.js +0 -9
- package/mcps/davinci-mcp-professional/docs/html/__version_8py_source.html +0 -130
- package/mcps/davinci-mcp-professional/docs/html/annotated.html +0 -123
- package/mcps/davinci-mcp-professional/docs/html/annotated_dup.js +0 -21
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveClient-members.html +0 -131
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveClient.html +0 -706
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveClient.js +0 -26
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveConnectionError.html +0 -143
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveConnectionError__coll__graph.map +0 -7
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveConnectionError__coll__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveConnectionError__coll__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveConnectionError__inherit__graph.map +0 -7
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveConnectionError__inherit__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveConnectionError__inherit__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveError.html +0 -143
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveError__coll__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveError__coll__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveError__coll__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveError__inherit__graph.map +0 -9
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveError__inherit__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveError__inherit__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveNotRunningError.html +0 -143
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveNotRunningError__coll__graph.map +0 -7
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveNotRunningError__coll__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveNotRunningError__coll__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveNotRunningError__inherit__graph.map +0 -7
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveNotRunningError__inherit__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1resolve__client_1_1DaVinciResolveNotRunningError__inherit__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1server_1_1DaVinciMCPServer-members.html +0 -115
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1server_1_1DaVinciMCPServer.html +0 -325
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1server_1_1DaVinciMCPServer.js +0 -10
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool-members.html +0 -110
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool.html +0 -188
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool__coll__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool__coll__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool__coll__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool__inherit__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool__inherit__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciMediaPool__inherit__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject-members.html +0 -113
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject.html +0 -248
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject.js +0 -8
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager-members.html +0 -113
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager.html +0 -252
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager.js +0 -8
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager__coll__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager__coll__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager__coll__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager__inherit__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager__inherit__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProjectManager__inherit__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject__coll__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject__coll__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject__coll__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject__inherit__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject__inherit__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciProject__inherit__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp-members.html +0 -115
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp.html +0 -288
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp.js +0 -10
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp__coll__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp__coll__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp__coll__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp__inherit__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp__inherit__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciResolveApp__inherit__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline-members.html +0 -110
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline.html +0 -188
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline__coll__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline__coll__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline__coll__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline__inherit__graph.map +0 -5
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline__inherit__graph.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/classdavinci__mcp_1_1types_1_1DaVinciTimeline__inherit__graph.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/classes.html +0 -111
- package/mcps/davinci-mcp-professional/docs/html/cli_8py.html +0 -135
- package/mcps/davinci-mcp-professional/docs/html/cli_8py.js +0 -11
- package/mcps/davinci-mcp-professional/docs/html/cli_8py_source.html +0 -249
- package/mcps/davinci-mcp-professional/docs/html/clipboard.js +0 -61
- package/mcps/davinci-mcp-professional/docs/html/cookie.js +0 -58
- package/mcps/davinci-mcp-professional/docs/html/dir_1a1069c9a5427270b3ccd00c87d405fe.html +0 -127
- package/mcps/davinci-mcp-professional/docs/html/dir_1a1069c9a5427270b3ccd00c87d405fe.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/dir_1a1069c9a5427270b3ccd00c87d405fe_dep.map +0 -4
- package/mcps/davinci-mcp-professional/docs/html/dir_1a1069c9a5427270b3ccd00c87d405fe_dep.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/dir_1a1069c9a5427270b3ccd00c87d405fe_dep.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/dir_6a5346f4427b2e9426ba2ccfd9f0b603.html +0 -128
- package/mcps/davinci-mcp-professional/docs/html/dir_6a5346f4427b2e9426ba2ccfd9f0b603.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/dir_6a5346f4427b2e9426ba2ccfd9f0b603_dep.map +0 -4
- package/mcps/davinci-mcp-professional/docs/html/dir_6a5346f4427b2e9426ba2ccfd9f0b603_dep.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/dir_6a5346f4427b2e9426ba2ccfd9f0b603_dep.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/dir_77c8a4d399bde190a30252eceec792ef.html +0 -127
- package/mcps/davinci-mcp-professional/docs/html/dir_77c8a4d399bde190a30252eceec792ef.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/dir_77c8a4d399bde190a30252eceec792ef_dep.map +0 -4
- package/mcps/davinci-mcp-professional/docs/html/dir_77c8a4d399bde190a30252eceec792ef_dep.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/dir_77c8a4d399bde190a30252eceec792ef_dep.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/dir_f94b29b73815c35a8351f4403bcc4f74.html +0 -129
- package/mcps/davinci-mcp-professional/docs/html/dir_f94b29b73815c35a8351f4403bcc4f74.js +0 -12
- package/mcps/davinci-mcp-professional/docs/html/doxygen.css +0 -2540
- package/mcps/davinci-mcp-professional/docs/html/doxygen.svg +0 -28
- package/mcps/davinci-mcp-professional/docs/html/doxygen_crawl.html +0 -170
- package/mcps/davinci-mcp-professional/docs/html/dynsections.js +0 -198
- package/mcps/davinci-mcp-professional/docs/html/files.html +0 -123
- package/mcps/davinci-mcp-professional/docs/html/files_dup.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/functions.html +0 -190
- package/mcps/davinci-mcp-professional/docs/html/functions_func.html +0 -184
- package/mcps/davinci-mcp-professional/docs/html/functions_vars.html +0 -110
- package/mcps/davinci-mcp-professional/docs/html/graph_legend.html +0 -165
- package/mcps/davinci-mcp-professional/docs/html/graph_legend.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/graph_legend.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/hierarchy.html +0 -123
- package/mcps/davinci-mcp-professional/docs/html/hierarchy.js +0 -18
- package/mcps/davinci-mcp-professional/docs/html/index.html +0 -200
- package/mcps/davinci-mcp-professional/docs/html/index.js +0 -9
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_0.map +0 -3
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_0.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_0.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_1.map +0 -3
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_1.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_1.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_2.map +0 -9
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_2.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_2.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_3.map +0 -13
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_3.md5 +0 -1
- package/mcps/davinci-mcp-professional/docs/html/inherit_graph_3.png +0 -0
- package/mcps/davinci-mcp-professional/docs/html/inherits.html +0 -145
- package/mcps/davinci-mcp-professional/docs/html/jquery.js +0 -204
- package/mcps/davinci-mcp-professional/docs/html/menu.js +0 -131
- package/mcps/davinci-mcp-professional/docs/html/menudata.js +0 -73
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp.html +0 -209
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp.js +0 -34
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1__version.html +0 -260
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1cli.html +0 -303
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1resolve__client.html +0 -147
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1resolve__client.js +0 -8
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1resources.html +0 -140
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1server.html +0 -144
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1server.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1tools.html +0 -140
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1types.html +0 -216
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1types.js +0 -13
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1utils.html +0 -155
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1utils.js +0 -11
- package/mcps/davinci-mcp-professional/docs/html/namespacedavinci__mcp_1_1utils_1_1platform.html +0 -232
- package/mcps/davinci-mcp-professional/docs/html/namespacemembers.html +0 -173
- package/mcps/davinci-mcp-professional/docs/html/namespacemembers_func.html +0 -114
- package/mcps/davinci-mcp-professional/docs/html/namespacemembers_vars.html +0 -121
- package/mcps/davinci-mcp-professional/docs/html/namespaces.html +0 -119
- package/mcps/davinci-mcp-professional/docs/html/namespaces_dup.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/navtree.css +0 -327
- package/mcps/davinci-mcp-professional/docs/html/navtree.js +0 -901
- package/mcps/davinci-mcp-professional/docs/html/navtreedata.js +0 -68
- package/mcps/davinci-mcp-professional/docs/html/navtreeindex0.js +0 -212
- package/mcps/davinci-mcp-professional/docs/html/platform_8py.html +0 -130
- package/mcps/davinci-mcp-professional/docs/html/platform_8py.js +0 -8
- package/mcps/davinci-mcp-professional/docs/html/platform_8py_source.html +0 -245
- package/mcps/davinci-mcp-professional/docs/html/resolve__client_8py.html +0 -132
- package/mcps/davinci-mcp-professional/docs/html/resolve__client_8py.js +0 -8
- package/mcps/davinci-mcp-professional/docs/html/resolve__client_8py_source.html +0 -501
- package/mcps/davinci-mcp-professional/docs/html/resources_2____init_____8py.html +0 -125
- package/mcps/davinci-mcp-professional/docs/html/resources_2____init_____8py.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/resources_2____init_____8py_source.html +0 -169
- package/mcps/davinci-mcp-professional/docs/html/search/all_0.js +0 -22
- package/mcps/davinci-mcp-professional/docs/html/search/all_1.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/all_10.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/all_11.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/all_12.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/all_13.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/all_2.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/all_3.js +0 -15
- package/mcps/davinci-mcp-professional/docs/html/search/all_4.js +0 -26
- package/mcps/davinci-mcp-professional/docs/html/search/all_5.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/all_6.js +0 -6
- package/mcps/davinci-mcp-professional/docs/html/search/all_7.js +0 -25
- package/mcps/davinci-mcp-professional/docs/html/search/all_8.js +0 -7
- package/mcps/davinci-mcp-professional/docs/html/search/all_9.js +0 -9
- package/mcps/davinci-mcp-professional/docs/html/search/all_a.js +0 -6
- package/mcps/davinci-mcp-professional/docs/html/search/all_b.js +0 -6
- package/mcps/davinci-mcp-professional/docs/html/search/all_c.js +0 -9
- package/mcps/davinci-mcp-professional/docs/html/search/all_d.js +0 -10
- package/mcps/davinci-mcp-professional/docs/html/search/all_e.js +0 -11
- package/mcps/davinci-mcp-professional/docs/html/search/all_f.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/classes_0.js +0 -13
- package/mcps/davinci-mcp-professional/docs/html/search/files_0.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/files_1.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/files_2.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/files_3.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/files_4.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/files_5.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/functions_0.js +0 -9
- package/mcps/davinci-mcp-professional/docs/html/search/functions_1.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/functions_2.js +0 -10
- package/mcps/davinci-mcp-professional/docs/html/search/functions_3.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/functions_4.js +0 -25
- package/mcps/davinci-mcp-professional/docs/html/search/functions_5.js +0 -6
- package/mcps/davinci-mcp-professional/docs/html/search/functions_6.js +0 -7
- package/mcps/davinci-mcp-professional/docs/html/search/functions_7.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/functions_8.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/functions_9.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/functions_a.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/functions_b.js +0 -6
- package/mcps/davinci-mcp-professional/docs/html/search/namespaces_0.js +0 -13
- package/mcps/davinci-mcp-professional/docs/html/search/pages_0.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/pages_1.js +0 -6
- package/mcps/davinci-mcp-professional/docs/html/search/pages_2.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/pages_3.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/pages_4.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/pages_5.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/pages_6.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/pages_7.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/pages_8.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/pages_9.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/pages_a.js +0 -6
- package/mcps/davinci-mcp-professional/docs/html/search/pages_b.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/pages_c.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/pages_d.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/search.css +0 -377
- package/mcps/davinci-mcp-professional/docs/html/search/search.js +0 -708
- package/mcps/davinci-mcp-professional/docs/html/search/searchdata.js +0 -33
- package/mcps/davinci-mcp-professional/docs/html/search/variables_0.js +0 -14
- package/mcps/davinci-mcp-professional/docs/html/search/variables_1.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/variables_2.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/variables_3.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/variables_4.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/variables_5.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/variables_6.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/search/variables_7.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/variables_8.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/search/variables_9.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/server_8py.html +0 -129
- package/mcps/davinci-mcp-professional/docs/html/server_8py.js +0 -5
- package/mcps/davinci-mcp-professional/docs/html/server_8py_source.html +0 -318
- package/mcps/davinci-mcp-professional/docs/html/tabs.css +0 -1
- package/mcps/davinci-mcp-professional/docs/html/tools_2____init_____8py.html +0 -125
- package/mcps/davinci-mcp-professional/docs/html/tools_2____init_____8py.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/tools_2____init_____8py_source.html +0 -253
- package/mcps/davinci-mcp-professional/docs/html/types_8py.html +0 -137
- package/mcps/davinci-mcp-professional/docs/html/types_8py.js +0 -13
- package/mcps/davinci-mcp-professional/docs/html/types_8py_source.html +0 -309
- package/mcps/davinci-mcp-professional/docs/html/utils_2____init_____8py.html +0 -125
- package/mcps/davinci-mcp-professional/docs/html/utils_2____init_____8py.js +0 -4
- package/mcps/davinci-mcp-professional/docs/html/utils_2____init_____8py_source.html +0 -123
- package/mcps/davinci-mcp-professional/tests/README.md +0 -49
- package/mcps/davinci-mcp-professional/tests/__init__.py +0 -1
- package/mcps/davinci-mcp-professional/tests/conftest.py +0 -75
- package/mcps/davinci-mcp-professional/tests/test_security.py +0 -251
- package/mcps/davinci-resolve-mcp/docs/README.md +0 -56
- package/mcps/davinci-resolve-mcp/docs/SKILL.md +0 -1635
- package/mcps/davinci-resolve-mcp/docs/authoring/fuse-dctl-authoring.md +0 -242
- package/mcps/davinci-resolve-mcp/docs/authoring/script-plugin-authoring.md +0 -195
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/README.md +0 -152
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/references/category-patterns.md +0 -780
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/references/controls.md +0 -259
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/references/format.md +0 -568
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/references/gotchas.md +0 -168
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/references/thumbnails.md +0 -106
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Blur.setting +0 -46
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Color Tint.setting +0 -78
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Cross Dissolve.setting +0 -57
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Fade Title.setting +0 -111
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Glow.setting +0 -55
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Gradient.setting +0 -52
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Iris.setting +0 -127
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Lower Third.setting +0 -192
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Noise.setting +0 -74
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Solid Color.setting +0 -55
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Title.setting +0 -105
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Vignette.setting +0 -98
- package/mcps/davinci-resolve-mcp/docs/authoring/setting-files/templates/MCP Test Wipe.setting +0 -98
- package/mcps/davinci-resolve-mcp/docs/contributing.md +0 -82
- package/mcps/davinci-resolve-mcp/docs/guides/color-decision-guide.md +0 -427
- package/mcps/davinci-resolve-mcp/docs/guides/control-panel.md +0 -234
- package/mcps/davinci-resolve-mcp/docs/guides/editorial-decision-guide.md +0 -165
- package/mcps/davinci-resolve-mcp/docs/guides/media-analysis-guide.md +0 -763
- package/mcps/davinci-resolve-mcp/docs/guides/multicam-setup-guide.md +0 -138
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/01-overview.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/02-review-bin-grid.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/03-clip-detail.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/04-transcript.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/05-shot-detail.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/06-inventory.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/07-diagnostics-resolve.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/08-preferences-analysis.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/09-ai-console.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/10-history.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/images/control-panel/11-edit-plans.png +0 -0
- package/mcps/davinci-resolve-mcp/docs/install.md +0 -208
- package/mcps/davinci-resolve-mcp/docs/integrations/workflow-integrations.md +0 -120
- package/mcps/davinci-resolve-mcp/docs/kernels/README.md +0 -28
- package/mcps/davinci-resolve-mcp/docs/kernels/audio-fairlight-kernel.md +0 -86
- package/mcps/davinci-resolve-mcp/docs/kernels/color-grade-kernel.md +0 -103
- package/mcps/davinci-resolve-mcp/docs/kernels/extension-authoring-kernel.md +0 -101
- package/mcps/davinci-resolve-mcp/docs/kernels/fusion-composition-kernel.md +0 -121
- package/mcps/davinci-resolve-mcp/docs/kernels/media-pool-ingest-kernel.md +0 -147
- package/mcps/davinci-resolve-mcp/docs/kernels/project-lifecycle-kernel.md +0 -120
- package/mcps/davinci-resolve-mcp/docs/kernels/render-deliver-kernel.md +0 -92
- package/mcps/davinci-resolve-mcp/docs/kernels/review-annotation-kernel.md +0 -110
- package/mcps/davinci-resolve-mcp/docs/kernels/timeline-conform-interchange-kernel.md +0 -102
- package/mcps/davinci-resolve-mcp/docs/kernels/timeline-edit-kernel.md +0 -189
- package/mcps/davinci-resolve-mcp/docs/notes/codec-plugin-notes.md +0 -136
- package/mcps/davinci-resolve-mcp/docs/notes/dctl-notes.md +0 -234
- package/mcps/davinci-resolve-mcp/docs/notes/fusion-template-notes.md +0 -136
- package/mcps/davinci-resolve-mcp/docs/notes/lut-notes.md +0 -136
- package/mcps/davinci-resolve-mcp/docs/notes/openfx-notes.md +0 -120
- package/mcps/davinci-resolve-mcp/docs/process/release-process.md +0 -180
- package/mcps/davinci-resolve-mcp/docs/reference/api-coverage.md +0 -521
- package/mcps/davinci-resolve-mcp/docs/reference/api-limitations.md +0 -259
- package/mcps/davinci-resolve-mcp/docs/reference/readwrite-symmetry.md +0 -25
- package/mcps/davinci-resolve-mcp/docs/reference/resolve_scripting_api.txt +0 -1024
- package/mcps/davinci-resolve-mcp/tests/_error_envelope_helpers.py +0 -35
- package/mcps/davinci-resolve-mcp/tests/benchmark_server.py +0 -270
- package/mcps/davinci-resolve-mcp/tests/create_test_timeline.py +0 -177
- package/mcps/davinci-resolve-mcp/tests/live_api_gap_verification.py +0 -274
- package/mcps/davinci-resolve-mcp/tests/live_audio_fairlight_validation.py +0 -77
- package/mcps/davinci-resolve-mcp/tests/live_auto_sync_settings_check.py +0 -76
- package/mcps/davinci-resolve-mcp/tests/live_color_grade_validation.py +0 -89
- package/mcps/davinci-resolve-mcp/tests/live_delete_governance_check.py +0 -71
- package/mcps/davinci-resolve-mcp/tests/live_duplicate_clips_validation.py +0 -831
- package/mcps/davinci-resolve-mcp/tests/live_edit_engine_validation.py +0 -277
- package/mcps/davinci-resolve-mcp/tests/live_enum_settings_check.py +0 -89
- package/mcps/davinci-resolve-mcp/tests/live_extension_authoring_validation.py +0 -77
- package/mcps/davinci-resolve-mcp/tests/live_fuse_diagnose.py +0 -230
- package/mcps/davinci-resolve-mcp/tests/live_fuse_smoke.py +0 -250
- package/mcps/davinci-resolve-mcp/tests/live_fusion_composition_validation.py +0 -82
- package/mcps/davinci-resolve-mcp/tests/live_fusion_keyframe_validation.py +0 -116
- package/mcps/davinci-resolve-mcp/tests/live_fusion_mask_title_validation.py +0 -286
- package/mcps/davinci-resolve-mcp/tests/live_marker_validation.py +0 -439
- package/mcps/davinci-resolve-mcp/tests/live_media_pool_ingest_validation.py +0 -98
- package/mcps/davinci-resolve-mcp/tests/live_metadata_field_inventory_validation.py +0 -379
- package/mcps/davinci-resolve-mcp/tests/live_metadata_publish_validation.py +0 -192
- package/mcps/davinci-resolve-mcp/tests/live_multicam_setup_validation.py +0 -198
- package/mcps/davinci-resolve-mcp/tests/live_path_probe.py +0 -119
- package/mcps/davinci-resolve-mcp/tests/live_project_lifecycle_validation.py +0 -77
- package/mcps/davinci-resolve-mcp/tests/live_render_deliver_validation.py +0 -82
- package/mcps/davinci-resolve-mcp/tests/live_review_annotation_validation.py +0 -91
- package/mcps/davinci-resolve-mcp/tests/live_script_smoke.py +0 -141
- package/mcps/davinci-resolve-mcp/tests/live_sync_event_validation.py +0 -165
- package/mcps/davinci-resolve-mcp/tests/live_timeline_conform_validation.py +0 -77
- package/mcps/davinci-resolve-mcp/tests/live_v233_validation.py +0 -282
- package/mcps/davinci-resolve-mcp/tests/test-after-restart.bat +0 -83
- package/mcps/davinci-resolve-mcp/tests/test-after-restart.sh +0 -87
- package/mcps/davinci-resolve-mcp/tests/test_action_help.py +0 -47
- package/mcps/davinci-resolve-mcp/tests/test_action_list_drift.py +0 -163
- package/mcps/davinci-resolve-mcp/tests/test_ai_console_dispatch.py +0 -91
- package/mcps/davinci-resolve-mcp/tests/test_analysis_caps.py +0 -210
- package/mcps/davinci-resolve-mcp/tests/test_analysis_runs.py +0 -157
- package/mcps/davinci-resolve-mcp/tests/test_analysis_store.py +0 -366
- package/mcps/davinci-resolve-mcp/tests/test_api_limitations_doc.py +0 -56
- package/mcps/davinci-resolve-mcp/tests/test_api_truth.py +0 -64
- package/mcps/davinci-resolve-mcp/tests/test_api_truth_mitigations.py +0 -45
- package/mcps/davinci-resolve-mcp/tests/test_append_clip_infos_result_handling.py +0 -679
- package/mcps/davinci-resolve-mcp/tests/test_audio_fairlight_probe.py +0 -216
- package/mcps/davinci-resolve-mcp/tests/test_auto_run.py +0 -76
- package/mcps/davinci-resolve-mcp/tests/test_auto_sync_audio.py +0 -171
- package/mcps/davinci-resolve-mcp/tests/test_batch_cli.py +0 -253
- package/mcps/davinci-resolve-mcp/tests/test_brain_edits.py +0 -218
- package/mcps/davinci-resolve-mcp/tests/test_bridge_metrics.py +0 -52
- package/mcps/davinci-resolve-mcp/tests/test_bulk_match_to_hero.py +0 -219
- package/mcps/davinci-resolve-mcp/tests/test_caps_events_and_history.py +0 -147
- package/mcps/davinci-resolve-mcp/tests/test_caps_integration.py +0 -315
- package/mcps/davinci-resolve-mcp/tests/test_cdl_and_install_config.py +0 -372
- package/mcps/davinci-resolve-mcp/tests/test_clip_query.py +0 -57
- package/mcps/davinci-resolve-mcp/tests/test_cloud_settings.py +0 -62
- package/mcps/davinci-resolve-mcp/tests/test_color_grade_probe.py +0 -230
- package/mcps/davinci-resolve-mcp/tests/test_confirm_token.py +0 -85
- package/mcps/davinci-resolve-mcp/tests/test_confirm_token_preferences.py +0 -22
- package/mcps/davinci-resolve-mcp/tests/test_contracts.py +0 -81
- package/mcps/davinci-resolve-mcp/tests/test_create_subtitles_settings.py +0 -111
- package/mcps/davinci-resolve-mcp/tests/test_custom_timeline.py +0 -137
- package/mcps/davinci-resolve-mcp/tests/test_cut_executor.py +0 -87
- package/mcps/davinci-resolve-mcp/tests/test_cut_ir.py +0 -82
- package/mcps/davinci-resolve-mcp/tests/test_dashboard_transport.py +0 -47
- package/mcps/davinci-resolve-mcp/tests/test_deep_vision.py +0 -311
- package/mcps/davinci-resolve-mcp/tests/test_description_xml_shape.py +0 -71
- package/mcps/davinci-resolve-mcp/tests/test_destructive_decorator_coverage.py +0 -92
- package/mcps/davinci-resolve-mcp/tests/test_destructive_hook.py +0 -245
- package/mcps/davinci-resolve-mcp/tests/test_destructive_registry_drift.py +0 -108
- package/mcps/davinci-resolve-mcp/tests/test_edit_engine.py +0 -574
- package/mcps/davinci-resolve-mcp/tests/test_embeddings.py +0 -302
- package/mcps/davinci-resolve-mcp/tests/test_entities.py +0 -225
- package/mcps/davinci-resolve-mcp/tests/test_error_envelope.py +0 -179
- package/mcps/davinci-resolve-mcp/tests/test_exhaustive_wave_a.py +0 -101
- package/mcps/davinci-resolve-mcp/tests/test_extension_authoring_probe.py +0 -77
- package/mcps/davinci-resolve-mcp/tests/test_extract_frames.py +0 -42
- package/mcps/davinci-resolve-mcp/tests/test_extract_source_frame_ranges.py +0 -129
- package/mcps/davinci-resolve-mcp/tests/test_failure_tracker.py +0 -103
- package/mcps/davinci-resolve-mcp/tests/test_fuse_dctl_authoring.py +0 -596
- package/mcps/davinci-resolve-mcp/tests/test_fusion_comp_targeting.py +0 -269
- package/mcps/davinci-resolve-mcp/tests/test_fusion_composition_probe.py +0 -156
- package/mcps/davinci-resolve-mcp/tests/test_fusion_group_settings.py +0 -284
- package/mcps/davinci-resolve-mcp/tests/test_fusion_mask_title.py +0 -205
- package/mcps/davinci-resolve-mcp/tests/test_fusion_node_ops.py +0 -212
- package/mcps/davinci-resolve-mcp/tests/test_governance_identity.py +0 -155
- package/mcps/davinci-resolve-mcp/tests/test_grade_evidence_base.py +0 -132
- package/mcps/davinci-resolve-mcp/tests/test_import.py +0 -153
- package/mcps/davinci-resolve-mcp/tests/test_improvements.py +0 -334
- package/mcps/davinci-resolve-mcp/tests/test_inventory_exclude_bins.py +0 -139
- package/mcps/davinci-resolve-mcp/tests/test_live_api.py +0 -315
- package/mcps/davinci-resolve-mcp/tests/test_marker_params.py +0 -234
- package/mcps/davinci-resolve-mcp/tests/test_mcp_prompts.py +0 -77
- package/mcps/davinci-resolve-mcp/tests/test_mcp_resources.py +0 -117
- package/mcps/davinci-resolve-mcp/tests/test_mcp_transport.py +0 -74
- package/mcps/davinci-resolve-mcp/tests/test_media_analysis.py +0 -4637
- package/mcps/davinci-resolve-mcp/tests/test_media_pool_append_verification.py +0 -153
- package/mcps/davinci-resolve-mcp/tests/test_media_pool_changes.py +0 -105
- package/mcps/davinci-resolve-mcp/tests/test_media_pool_delete_governance.py +0 -69
- package/mcps/davinci-resolve-mcp/tests/test_media_pool_ingest_probe.py +0 -546
- package/mcps/davinci-resolve-mcp/tests/test_media_pool_walk.py +0 -79
- package/mcps/davinci-resolve-mcp/tests/test_multicam_setup.py +0 -178
- package/mcps/davinci-resolve-mcp/tests/test_object_inspection.py +0 -140
- package/mcps/davinci-resolve-mcp/tests/test_open_control_panel.py +0 -172
- package/mcps/davinci-resolve-mcp/tests/test_p1_param_validation.py +0 -57
- package/mcps/davinci-resolve-mcp/tests/test_p1_whitelist_and_delete.py +0 -81
- package/mcps/davinci-resolve-mcp/tests/test_page_lock.py +0 -52
- package/mcps/davinci-resolve-mcp/tests/test_panel_docs_drift.py +0 -77
- package/mcps/davinci-resolve-mcp/tests/test_partial_success_manifest.py +0 -113
- package/mcps/davinci-resolve-mcp/tests/test_persistence_safety.py +0 -147
- package/mcps/davinci-resolve-mcp/tests/test_prefer_handle.py +0 -89
- package/mcps/davinci-resolve-mcp/tests/test_project_cleanup.py +0 -111
- package/mcps/davinci-resolve-mcp/tests/test_project_lifecycle_probe.py +0 -256
- package/mcps/davinci-resolve-mcp/tests/test_project_lint.py +0 -79
- package/mcps/davinci-resolve-mcp/tests/test_project_spec.py +0 -246
- package/mcps/davinci-resolve-mcp/tests/test_propose_grade.py +0 -116
- package/mcps/davinci-resolve-mcp/tests/test_provenance.py +0 -88
- package/mcps/davinci-resolve-mcp/tests/test_readback.py +0 -77
- package/mcps/davinci-resolve-mcp/tests/test_readwrite_audit.py +0 -43
- package/mcps/davinci-resolve-mcp/tests/test_reel_name_writeback.py +0 -149
- package/mcps/davinci-resolve-mcp/tests/test_render_deliver_probe.py +0 -250
- package/mcps/davinci-resolve-mcp/tests/test_resolve20_api.py +0 -282
- package/mcps/davinci-resolve-mcp/tests/test_resolve21_actions.py +0 -386
- package/mcps/davinci-resolve-mcp/tests/test_resolve_ai_governance.py +0 -92
- package/mcps/davinci-resolve-mcp/tests/test_resolve_ai_ledger.py +0 -89
- package/mcps/davinci-resolve-mcp/tests/test_resolve_busy.py +0 -134
- package/mcps/davinci-resolve-mcp/tests/test_review_annotation_probe.py +0 -162
- package/mcps/davinci-resolve-mcp/tests/test_sampling_modes.py +0 -293
- package/mcps/davinci-resolve-mcp/tests/test_script_plugin.py +0 -750
- package/mcps/davinci-resolve-mcp/tests/test_shot_relationships.py +0 -254
- package/mcps/davinci-resolve-mcp/tests/test_spec_lint_wiring.py +0 -311
- package/mcps/davinci-resolve-mcp/tests/test_static_undefined_names.py +0 -45
- package/mcps/davinci-resolve-mcp/tests/test_structural_diff.py +0 -67
- package/mcps/davinci-resolve-mcp/tests/test_sync_detection.py +0 -213
- package/mcps/davinci-resolve-mcp/tests/test_thumbnail_image.py +0 -55
- package/mcps/davinci-resolve-mcp/tests/test_timeline_brain_db.py +0 -230
- package/mcps/davinci-resolve-mcp/tests/test_timeline_conform_probe.py +0 -229
- package/mcps/davinci-resolve-mcp/tests/test_timeline_editorial_helpers.py +0 -88
- package/mcps/davinci-resolve-mcp/tests/test_timeline_export_enum.py +0 -59
- package/mcps/davinci-resolve-mcp/tests/test_timeline_kernel_probe.py +0 -70
- package/mcps/davinci-resolve-mcp/tests/test_timeline_title_text_utils.py +0 -64
- package/mcps/davinci-resolve-mcp/tests/test_timeline_versioning.py +0 -419
- package/mcps/davinci-resolve-mcp/tests/test_tool_choice_hint.py +0 -42
- package/mcps/davinci-resolve-mcp/tests/test_tool_exposure.py +0 -159
- package/mcps/davinci-resolve-mcp/tests/test_tool_registration.py +0 -91
- package/mcps/davinci-resolve-mcp/tests/test_transcript_read.py +0 -74
- package/mcps/davinci-resolve-mcp/tests/test_update_check.py +0 -171
- package/mcps/davinci-resolve-mcp/tests/test_update_hardening.py +0 -171
- package/mcps/davinci-resolve-mcp/tests/test_update_history.py +0 -116
- package/mcps/davinci-resolve-mcp/tests/test_v232_helpers.py +0 -265
- package/mcps/davinci-resolve-mcp/tests/test_v233_helpers.py +0 -307
- package/mcps/davinci-resolve-mcp/tests/test_validation_guards.py +0 -108
- package/mcps/davinci-resolve-mcp/tests/test_verification_stats.py +0 -32
- package/mcps/davinci-resolve-mcp/tests/test_waveb_p2_p3.py +0 -65
- package/mcps/golem-rhino-mcp/Nexus-AI-Agents.png +0 -0
- package/mcps/golem-rhino-mcp/docs/ARCHITECTURE.md +0 -277
- package/mcps/golem-rhino-mcp/docs/PROTOCOL.md +0 -247
- package/mcps/golem-rhino-mcp/docs/TOOL_REFERENCE.md +0 -1571
- package/mcps/golem-rhino-mcp/docs/TROUBLESHOOTING.md +0 -396
- package/mcps/golem-rhino-mcp/mcp_server/Screenshot 2026-03-20 at 18.33.06.png +0 -0
- package/mcps/golem-rhino-mcp/mcp_server/Screenshot 2026-03-21 at 1.43.01.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CAIO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CEO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CFO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CHRO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CISO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CLO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CMO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/COO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CPO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CRO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/CTO.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/king-hippo.png +0 -0
- package/mcps/golem-rhino-mcp/nexus-pngs/tier-0-csuite.png +0 -0
- package/mcps/golem-rhino-mcp/screenshots/city_monument.png +0 -0
- package/mcps/golem-rhino-mcp/screenshots/city_skyline.png +0 -0
- package/mcps/golem-rhino-mcp/screenshots/city_street.png +0 -0
- package/mcps/golem-rhino-mcp/screenshots/city_wide.png +0 -0
- package/mcps/golem-rhino-mcp/tests/__init__.py +0 -0
- package/mcps/golem-rhino-mcp/tests/conftest.py +0 -150
- package/mcps/golem-rhino-mcp/tests/test_connection.py +0 -543
- package/mcps/golem-rhino-mcp/tests/test_integration.py +0 -344
- package/mcps/golem-rhino-mcp/tests/test_models.py +0 -749
- package/mcps/golem-rhino-mcp/tests/test_protocol.py +0 -334
- package/mcps/golem-rhino-mcp/tests/test_tools_mock.py +0 -689
- package/mcps/tdmcp/.github/social-preview.png +0 -0
- package/mcps/tdmcp/docs/.vitepress/config.ts +0 -397
- package/mcps/tdmcp/docs/AI_PARTY_LLM_TRAINING_PLAN.md +0 -118
- package/mcps/tdmcp/docs/AI_PARTY_POC.md +0 -142
- package/mcps/tdmcp/docs/AI_PARTY_POC_PLAN.md +0 -112
- package/mcps/tdmcp/docs/CREATIVE_RAG.md +0 -346
- package/mcps/tdmcp/docs/DEPLOYMENT.md +0 -113
- package/mcps/tdmcp/docs/PROJECT_RAG.md +0 -477
- package/mcps/tdmcp/docs/ROADMAP.md +0 -1346
- package/mcps/tdmcp/docs/guide/ai-controlled-party.md +0 -215
- package/mcps/tdmcp/docs/guide/body-tracking.md +0 -169
- package/mcps/tdmcp/docs/guide/codex.md +0 -107
- package/mcps/tdmcp/docs/guide/components.md +0 -126
- package/mcps/tdmcp/docs/guide/dashboard-foh.md +0 -93
- package/mcps/tdmcp/docs/guide/faq.md +0 -62
- package/mcps/tdmcp/docs/guide/first-visual.md +0 -76
- package/mcps/tdmcp/docs/guide/generators.md +0 -230
- package/mcps/tdmcp/docs/guide/glossary.md +0 -123
- package/mcps/tdmcp/docs/guide/install.md +0 -200
- package/mcps/tdmcp/docs/guide/local-copilot.md +0 -154
- package/mcps/tdmcp/docs/guide/lops-integration.md +0 -133
- package/mcps/tdmcp/docs/guide/mcp-resources.md +0 -96
- package/mcps/tdmcp/docs/guide/mediapipe-adapters.md +0 -90
- package/mcps/tdmcp/docs/guide/physical-installations.md +0 -129
- package/mcps/tdmcp/docs/guide/prompt-cookbook.md +0 -2285
- package/mcps/tdmcp/docs/guide/recipes.md +0 -72
- package/mcps/tdmcp/docs/guide/session-profile.md +0 -90
- package/mcps/tdmcp/docs/guide/shader-park.md +0 -94
- package/mcps/tdmcp/docs/guide/show-timelines.md +0 -125
- package/mcps/tdmcp/docs/guide/troubleshooting.md +0 -121
- package/mcps/tdmcp/docs/guide/what-is-tdmcp.md +0 -62
- package/mcps/tdmcp/docs/index.md +0 -49
- package/mcps/tdmcp/docs/privacy.md +0 -85
- package/mcps/tdmcp/docs/pt/CREATIVE_RAG.md +0 -370
- package/mcps/tdmcp/docs/pt/PROJECT_RAG.md +0 -420
- package/mcps/tdmcp/docs/pt/guide/ai-controlled-party.md +0 -218
- package/mcps/tdmcp/docs/pt/guide/body-tracking.md +0 -175
- package/mcps/tdmcp/docs/pt/guide/codex.md +0 -113
- package/mcps/tdmcp/docs/pt/guide/components.md +0 -129
- package/mcps/tdmcp/docs/pt/guide/dashboard-foh.md +0 -95
- package/mcps/tdmcp/docs/pt/guide/faq.md +0 -62
- package/mcps/tdmcp/docs/pt/guide/first-visual.md +0 -81
- package/mcps/tdmcp/docs/pt/guide/generators.md +0 -243
- package/mcps/tdmcp/docs/pt/guide/glossary.md +0 -127
- package/mcps/tdmcp/docs/pt/guide/install.md +0 -196
- package/mcps/tdmcp/docs/pt/guide/local-copilot.md +0 -164
- package/mcps/tdmcp/docs/pt/guide/lops-integration.md +0 -143
- package/mcps/tdmcp/docs/pt/guide/mcp-resources.md +0 -96
- package/mcps/tdmcp/docs/pt/guide/mediapipe-adapters.md +0 -93
- package/mcps/tdmcp/docs/pt/guide/physical-installations.md +0 -135
- package/mcps/tdmcp/docs/pt/guide/prompt-cookbook.md +0 -2342
- package/mcps/tdmcp/docs/pt/guide/recipes.md +0 -59
- package/mcps/tdmcp/docs/pt/guide/session-profile.md +0 -92
- package/mcps/tdmcp/docs/pt/guide/shader-park.md +0 -95
- package/mcps/tdmcp/docs/pt/guide/show-timelines.md +0 -128
- package/mcps/tdmcp/docs/pt/guide/troubleshooting.md +0 -109
- package/mcps/tdmcp/docs/pt/guide/what-is-tdmcp.md +0 -61
- package/mcps/tdmcp/docs/pt/index.md +0 -49
- package/mcps/tdmcp/docs/pt/privacy.md +0 -91
- package/mcps/tdmcp/docs/pt/reference/architecture.md +0 -178
- package/mcps/tdmcp/docs/pt/reference/environment.md +0 -70
- package/mcps/tdmcp/docs/public/favicon.svg +0 -12
- package/mcps/tdmcp/docs/public/logo-400.png +0 -0
- package/mcps/tdmcp/docs/public/og-image.jpg +0 -0
- package/mcps/tdmcp/docs/public/robots.txt +0 -4
- package/mcps/tdmcp/docs/reference/API_STABILITY.md +0 -116
- package/mcps/tdmcp/docs/reference/architecture.md +0 -191
- package/mcps/tdmcp/docs/reference/bridge-api.md +0 -155
- package/mcps/tdmcp/docs/reference/cli.md +0 -288
- package/mcps/tdmcp/docs/reference/coverage-harness.md +0 -61
- package/mcps/tdmcp/docs/reference/environment.md +0 -116
- package/mcps/tdmcp/docs/reference/packages.md +0 -98
- package/mcps/tdmcp/docs/reference/tool-contract.md +0 -74
- package/mcps/tdmcp/docs/superpowers/plans/2026-05-29-shader-park-animus-integrations.md +0 -76
- package/mcps/tdmcp/docs/superpowers/plans/2026-06-02-doctor-fix-textport-auto-install.md +0 -131
- package/mcps/tdmcp/docs/superpowers/plans/2026-06-06-body-bubbles.md +0 -138
- package/mcps/tdmcp/docs/superpowers/plans/2026-06-08-deep-doppelganger-implementation.md +0 -201
- package/mcps/tdmcp/docs/superpowers/plans/2026-06-10-ai-party-ollama-integration.md +0 -55
- package/mcps/tdmcp/docs/superpowers/plans/2026-06-24-kinect-wall-harp-calibration-wizard.md +0 -53
- package/mcps/tdmcp/docs/superpowers/plans/2026-06-24-kinect-wall-harp-external-kinect.md +0 -286
- package/mcps/tdmcp/docs/superpowers/specs/2026-05-31-create-vector-lines-design.md +0 -308
- package/mcps/tdmcp/docs/superpowers/specs/2026-06-01-ai-controlled-party-plan.md +0 -461
- package/mcps/tdmcp/docs/superpowers/specs/2026-06-04-ai-party-ui24r-scene-arming-design.md +0 -296
- package/mcps/tdmcp/docs/superpowers/specs/2026-06-08-ai-controlled-party-producer-poc.md +0 -232
- package/mcps/tdmcp/docs/superpowers/specs/2026-06-08-deep-doppelganger-design.md +0 -136
- package/mcps/tdmcp/docs/superpowers/specs/2026-06-10-hermes-ai-party-poc.md +0 -383
- package/mcps/tdmcp/docs/superpowers/specs/2026-06-23-kinect-wall-harp-design.md +0 -340
- package/mcps/tdmcp/docs/superpowers/specs/2026-06-24-kinect-environment-diagnostic-design.md +0 -151
- package/mcps/tdmcp/docs/superpowers/specs/2026-06-24-kinect-wall-harp-external-kinect-design.md +0 -104
- package/mcps/tdmcp/training/showintent/data/curated/.gitkeep +0 -1
- package/mcps/tdmcp/training/showintent/data/curated/curated-approved.jsonl +0 -1
- package/mcps/tdmcp/training/showintent/data/curation_template.csv +0 -1
- package/mcps/tdmcp/training/showintent/data/generated/.gitkeep +0 -1
- package/mcps/tdmcp/training/showintent/data/generated/showintent-synthetic.jsonl +0 -2000
- package/mcps/tdmcp/training/showintent/data/raw/.gitkeep +0 -1
- package/mcps/tdmcp/training/showintent/data/splits/.gitkeep +0 -1
- package/mcps/tdmcp/training/showintent/data/splits/train-compact.jsonl +0 -1800
- package/mcps/tdmcp/training/showintent/data/splits/train.jsonl +0 -1800
- package/mcps/tdmcp/training/showintent/data/splits/validation-compact.jsonl +0 -200
- package/mcps/tdmcp/training/showintent/data/splits/validation.jsonl +0 -200
- package/mcps/touchdesigner-mcp/assets/import.png +0 -0
- package/mcps/touchdesigner-mcp/assets/nodes_list.png +0 -0
- package/mcps/touchdesigner-mcp/assets/particle_on_youtube.png +0 -0
- package/mcps/touchdesigner-mcp/assets/textport.png +0 -0
- package/mcps/touchdesigner-mcp/assets/tutorial.png +0 -0
- package/mcps/touchdesigner-mcp/assets/tutorial_docker.png +0 -0
- package/mcps/touchdesigner-mcp/docs/architecture.md +0 -1245
- package/mcps/touchdesigner-mcp/docs/development.ja.md +0 -197
- package/mcps/touchdesigner-mcp/docs/development.md +0 -212
- package/mcps/touchdesigner-mcp/docs/installation.ja.md +0 -370
- package/mcps/touchdesigner-mcp/docs/installation.md +0 -406
- package/mcps/unreal_mcp/Public/icon.png +0 -0
- package/mcps/unreal_mcp/docs/Engine-API-Reference.md +0 -2251
- package/mcps/unreal_mcp/docs/Roadmap.md +0 -2269
- package/mcps/unreal_mcp/docs/editor-plugin-extension.md +0 -373
- package/mcps/unreal_mcp/docs/handler-mapping.md +0 -1170
- package/mcps/unreal_mcp/docs/native-automation-progress.md +0 -431
- package/mcps/unreal_mcp/docs/testing-guide.md +0 -149
- package/mcps/unreal_mcp/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Domains/Test/McpAutomationBridge_TestHandlers.cpp +0 -74
- package/mcps/unreal_mcp/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Tests/McpCustomHandlerAliasTests.cpp +0 -191
- package/mcps/unreal_mcp/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Tests/McpEnvironmentSnapshotSchemaTests.cpp +0 -192
- package/mcps/unreal_mcp/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/Tests/McpPropertyReflectionImportTests.cpp +0 -269
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentAcpClientProtocolAutomation.cpp +0 -152
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentAcpProtocolTestHelpers.cpp +0 -136
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentAcpProtocolTestHelpers.h +0 -49
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentAutomationTestDelegates.h +0 -12
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentAutomationTests.cpp +0 -34
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentAutomationWidgetHelpers.cpp +0 -116
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentAutomationWidgetHelpers.h +0 -15
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentFakeAcpScript.cpp +0 -76
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentPanelAutomation.h +0 -35
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentPanelAutomationFixture.cpp +0 -118
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentPanelHistoryChecks.cpp +0 -162
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentPanelLayoutChecks.cpp +0 -158
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentPanelTranscriptChecks.cpp +0 -117
- package/mcps/unreal_mcp/plugins/UnrealAgent/Source/UnrealAgent/Private/Tests/UnrealAgentStudioKitAutomationChecks.cpp +0 -155
- package/mcps/unreal_mcp/tests/AGENTS.md +0 -73
- package/mcps/unreal_mcp/tests/expectation-utils.mjs +0 -29
- package/mcps/unreal_mcp/tests/heartbeat-progress.test.mjs +0 -143
- package/mcps/unreal_mcp/tests/integration/get_ai_info_characterization.mjs +0 -216
- package/mcps/unreal_mcp/tests/integration.mjs +0 -94
- package/mcps/unreal_mcp/tests/mcp-tools/core/control-actor.test.mjs +0 -114
- package/mcps/unreal_mcp/tests/mcp-tools/core/control-editor.test.mjs +0 -86
- package/mcps/unreal_mcp/tests/mcp-tools/core/inspect.test.mjs +0 -85
- package/mcps/unreal_mcp/tests/mcp-tools/core/manage-asset.test.mjs +0 -302
- package/mcps/unreal_mcp/tests/mcp-tools/core/manage-blueprint.test.mjs +0 -331
- package/mcps/unreal_mcp/tests/mcp-tools/core/manage-level.test.mjs +0 -73
- package/mcps/unreal_mcp/tests/mcp-tools/core/manage-tools.test.mjs +0 -30
- package/mcps/unreal_mcp/tests/mcp-tools/core/system-control.test.mjs +0 -205
- package/mcps/unreal_mcp/tests/mcp-tools/gameplay/animation-physics.test.mjs +0 -277
- package/mcps/unreal_mcp/tests/mcp-tools/gameplay/manage-ai.test.mjs +0 -299
- package/mcps/unreal_mcp/tests/mcp-tools/gameplay/manage-character.test.mjs +0 -85
- package/mcps/unreal_mcp/tests/mcp-tools/gameplay/manage-combat.test.mjs +0 -106
- package/mcps/unreal_mcp/tests/mcp-tools/gameplay/manage-effect.test.mjs +0 -108
- package/mcps/unreal_mcp/tests/mcp-tools/gameplay/manage-gas.test.mjs +0 -96
- package/mcps/unreal_mcp/tests/mcp-tools/gameplay/manage-interaction.test.mjs +0 -122
- package/mcps/unreal_mcp/tests/mcp-tools/gameplay/manage-inventory.test.mjs +0 -146
- package/mcps/unreal_mcp/tests/mcp-tools/utility/behavior-tree-get-tree.test.mjs +0 -233
- package/mcps/unreal_mcp/tests/mcp-tools/utility/manage-audio.test.mjs +0 -160
- package/mcps/unreal_mcp/tests/mcp-tools/utility/manage-behavior-tree.test.mjs +0 -223
- package/mcps/unreal_mcp/tests/mcp-tools/utility/manage-networking.test.mjs +0 -635
- package/mcps/unreal_mcp/tests/mcp-tools/utility/manage-sequence.test.mjs +0 -95
- package/mcps/unreal_mcp/tests/mcp-tools/world/build-environment.test.mjs +0 -282
- package/mcps/unreal_mcp/tests/mcp-tools/world/manage-geometry.test.mjs +0 -130
- package/mcps/unreal_mcp/tests/mcp-tools/world/manage-level-structure.test.mjs +0 -149
- package/mcps/unreal_mcp/tests/mcp-tools/world/manage-pcg.test.mjs +0 -471
- package/mcps/unreal_mcp/tests/mcp-tools/world/rendering-cases.cjs +0 -775
- package/mcps/unreal_mcp/tests/mcp-tools/world/rendering.test.mjs +0 -15
- package/mcps/unreal_mcp/tests/native-mcp-parity-audit.mjs +0 -260
- package/mcps/unreal_mcp/tests/native-mcp-source-parser.mjs +0 -229
- package/mcps/unreal_mcp/tests/native-mcp-typescript-parity-parser.mjs +0 -121
- package/mcps/unreal_mcp/tests/parameter-audit-cli.mjs +0 -23
- package/mcps/unreal_mcp/tests/parameter-audit-context.mjs +0 -14
- package/mcps/unreal_mcp/tests/parameter-audit-coverage.mjs +0 -164
- package/mcps/unreal_mcp/tests/parameter-audit-schema.mjs +0 -190
- package/mcps/unreal_mcp/tests/parameter-audit-suites.mjs +0 -218
- package/mcps/unreal_mcp/tests/parameter-combination-audit.mjs +0 -37
- package/mcps/unreal_mcp/tests/test-runner-response-utils.mjs +0 -132
- package/mcps/unreal_mcp/tests/test-runner.mjs +0 -1798
- package/mcps/unreal_mcp/tests/unit/automation/bridge_host_validation.test.ts +0 -165
- package/mcps/unreal_mcp/tests/unit/config.test.ts +0 -205
- package/mcps/unreal_mcp/tests/unit/native_mcp_parity_audit.test.ts +0 -281
- package/mcps/unreal_mcp/tests/unit/native_mcp_parity_comment_filtering.test.ts +0 -175
- package/mcps/unreal_mcp/tests/unit/parameter_audit_schema.test.ts +0 -273
- package/mcps/unreal_mcp/tests/unit/plugin/automation_event_stream_contracts.test.ts +0 -195
- package/mcps/unreal_mcp/tests/unit/plugin/environment_asset_name_contracts.test.ts +0 -115
- package/mcps/unreal_mcp/tests/unit/plugin/environment_build_adapter_contracts.test.ts +0 -377
- package/mcps/unreal_mcp/tests/unit/plugin/environment_snapshot_path_contracts.test.ts +0 -122
- package/mcps/unreal_mcp/tests/unit/plugin/handler_routing_contracts.test.ts +0 -120
- package/mcps/unreal_mcp/tests/unit/plugin/level_lighting_contracts.test.ts +0 -125
- package/mcps/unreal_mcp/tests/unit/plugin/plugin_manifest_contracts.test.ts +0 -154
- package/mcps/unreal_mcp/tests/unit/plugin/plugin_packaging_contracts.test.ts +0 -124
- package/mcps/unreal_mcp/tests/unit/plugin/runtime_behavior_contracts.test.ts +0 -372
- package/mcps/unreal_mcp/tests/unit/plugin/security_contracts.test.ts +0 -81
- package/mcps/unreal_mcp/tests/unit/plugin/source_structure.test.ts +0 -101
- package/mcps/unreal_mcp/tests/unit/plugin/source_structure_contracts.test.ts +0 -103
- package/mcps/unreal_mcp/tests/unit/plugin/websocket_origin_contracts.test.ts +0 -25
- package/mcps/unreal_mcp/tests/unit/server_shutdown_contracts.test.ts +0 -33
- package/mcps/unreal_mcp/tests/unit/source_structure.test.ts +0 -79
- package/mcps/unreal_mcp/tests/unit/test_runner.test.ts +0 -342
- package/mcps/unreal_mcp/tests/unit/test_runner_response_utils.test.ts +0 -105
- package/mcps/unreal_mcp/tests/unit/tools/asset_handlers_security.test.ts +0 -246
- package/mcps/unreal_mcp/tests/unit/tools/behavior_tree_get_tree.test.ts +0 -20
- package/mcps/unreal_mcp/tests/unit/tools/blueprint_handlers.test.ts +0 -122
- package/mcps/unreal_mcp/tests/unit/tools/editor.test.ts +0 -56
- package/mcps/unreal_mcp/tests/unit/tools/handler_structure.test.ts +0 -59
- package/mcps/unreal_mcp/tests/unit/tools/inspect_handlers.test.ts +0 -231
- package/mcps/unreal_mcp/tests/unit/tools/level.test.ts +0 -56
- package/mcps/unreal_mcp/tests/unit/tools/level_security.test.ts +0 -45
- package/mcps/unreal_mcp/tests/unit/tools/lighting_timeout_propagation.test.ts +0 -123
- package/mcps/windows-computer-use-mcp/cua-reports/app-1781542686.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/bridge-1781542694.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/bridge-ok-1781442393.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/bridge-ok-1781442915.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/bridge-snap-1781444105.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/bridge-snap-1781444214.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/bridge-snap-1781457035.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/cua-smoke-1781440024.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/cua-smoke-1781440234.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/cua-smoke-1781442383.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/cua-smoke-1781442906.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/cua-smoke-1781444096.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/cua-smoke-1781444209.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/cua-smoke-1781457029.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/dashboard-1781542713.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/help-1781542738.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/logging-1781542722.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/nav-dashboard-1781444225.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/nav-dashboard-1781457051.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/nav-help-1781444245.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/nav-help-1781457075.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/nav-logging-1781444232.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/nav-logging-1781457059.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/nav-settings-1781444239.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/nav-settings-1781457067.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav/settings-1781542730.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav-dashboard-1781442925.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav-help-1781442941.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav-logging-1781442930.png +0 -0
- package/mcps/windows-computer-use-mcp/cua-reports/nav-settings-1781442936.png +0 -0
- package/mcps/windows-computer-use-mcp/docs/ARCHITECTURE.md +0 -46
- package/mcps/windows-computer-use-mcp/docs/ASSESSMENT_BY_CURSOR_2026-06-14_CUA_NSIS.md +0 -383
- package/mcps/windows-computer-use-mcp/docs/AUTOMATION_ASSERT_SPEC.md +0 -202
- package/mcps/windows-computer-use-mcp/docs/CUA_PARITY.md +0 -39
- package/mcps/windows-computer-use-mcp/docs/DEVELOPMENT.md +0 -51
- package/mcps/windows-computer-use-mcp/docs/MEMOPS_CUA.md +0 -147
- package/mcps/windows-computer-use-mcp/docs/PRD.md +0 -93
- package/mcps/windows-computer-use-mcp/docs/README.md +0 -34
- package/mcps/windows-computer-use-mcp/docs/ROADMAP.md +0 -142
- package/mcps/windows-computer-use-mcp/docs/SAFETY.md +0 -138
- package/mcps/windows-computer-use-mcp/docs/TESTING.md +0 -90
- package/mcps/windows-computer-use-mcp/docs/TOOLS.md +0 -80
- package/mcps/windows-computer-use-mcp/docs/TOOL_DOCSTRING_STANDARD.md +0 -538
- package/mcps/windows-computer-use-mcp/docs/_stale/AHK_VS_PYWINAUTO_COMPARISON.md +0 -353
- package/mcps/windows-computer-use-mcp/docs/_stale/ASSESSMENT.md +0 -54
- package/mcps/windows-computer-use-mcp/docs/_stale/ASSESSMENT_2026-06-08.md +0 -309
- package/mcps/windows-computer-use-mcp/docs/_stale/COMPLETE_DOCUMENTATION_STRUCTURE.md +0 -5
- package/mcps/windows-computer-use-mcp/docs/_stale/CUA_ASSISTANT_TODO.md +0 -84
- package/mcps/windows-computer-use-mcp/docs/_stale/CUA_PARITY_ROADMAP.md +0 -81
- package/mcps/windows-computer-use-mcp/docs/_stale/CUA_ROADMAP.md +0 -306
- package/mcps/windows-computer-use-mcp/docs/_stale/DESKTOP_APP.md +0 -125
- package/mcps/windows-computer-use-mcp/docs/_stale/DOCUMENTATION_INDEX.md +0 -59
- package/mcps/windows-computer-use-mcp/docs/_stale/GLAMA_AI_CRITICISM_ANALYSIS.md +0 -259
- package/mcps/windows-computer-use-mcp/docs/_stale/GLAMA_AI_PLATFORM.md +0 -175
- package/mcps/windows-computer-use-mcp/docs/_stale/GLAMA_AI_RESCAN_GUIDE.md +0 -216
- package/mcps/windows-computer-use-mcp/docs/_stale/GOLD_STATUS_ACHIEVEMENT.md +0 -197
- package/mcps/windows-computer-use-mcp/docs/_stale/LLM_REPO_CONTEXT.md +0 -7
- package/mcps/windows-computer-use-mcp/docs/_stale/MCP_PRODUCTION_CHECKLIST.md +0 -105
- package/mcps/windows-computer-use-mcp/docs/_stale/OFFICE_BACKGROUND_MATRIX.md +0 -19
- package/mcps/windows-computer-use-mcp/docs/_stale/OPERATOR_PROTOCOL.md +0 -37
- package/mcps/windows-computer-use-mcp/docs/_stale/ORGANIZATION_SUMMARY.md +0 -305
- package/mcps/windows-computer-use-mcp/docs/_stale/RENAME-TO-AUTOMATION-MCP.md +0 -191
- package/mcps/windows-computer-use-mcp/docs/_stale/STATUS_REPORT.md +0 -288
- package/mcps/windows-computer-use-mcp/docs/_stale/TARGETS_PAGE_SKETCH.md +0 -977
- package/mcps/windows-computer-use-mcp/docs/_stale/TOOL_DOCSTRING_MIGRATION.md +0 -365
- package/mcps/windows-computer-use-mcp/docs/_stale/USAGE_SCENARIOS.md +0 -697
- package/mcps/windows-computer-use-mcp/docs/_stale/desktop-state-tool.md +0 -464
- package/mcps/windows-computer-use-mcp/docs/_stale/development/README.md +0 -18
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/AI_DEVELOPMENT_RULES.md +0 -928
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/AI_DEVELOPMENT_TOOLS_COMPARISON.md +0 -364
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/BULLETPROOF_MCP_GUIDE.md +0 -793
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/DEBUGGING_LESSONS_LEARNED.md +0 -635
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/DEVELOPMENT_PAIN_POINTS.md +0 -699
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/FILE_VALIDATION_COMPLETE.md +0 -410
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/FILE_VALIDATION_GUIDE.md +0 -575
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/LINK_PARSER_FIX.md +0 -769
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/MCP_SYNC_DEBUGGING_GUIDE.md +0 -512
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/PYTHON_DEPENDENCY_HELL_FIX.md +0 -568
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/PYTHON_SNIPPETS_USAGE_GUIDE.md +0 -717
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/README.md +0 -25
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/SYNC_HEALTH_IMPROVEMENTS_SUMMARY.md +0 -496
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/SYNC_HEALTH_INTEGRATION.md +0 -381
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/SYSTEMATIC_PROJECT_UPDATES.md +0 -532
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/mcp-prompt-templates-vs-docstrings.md +0 -657
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/mcp-tool-docstring-best-practices.md +0 -439
- package/mcps/windows-computer-use-mcp/docs/_stale/development/archive/mcp-tool-documentation-standards.md +0 -1153
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/CI_CD_GLAMA_OPTIMIZATION_GUIDE.md +0 -850
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GLAMA_AI_CRITICISM_ANALYSIS.md +0 -259
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GLAMA_AI_OPTIMIZATION_SUMMARY.md +0 -204
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GLAMA_AI_PLATFORM.md +0 -175
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GLAMA_AI_RESCAN_GUIDE.md +0 -216
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GLAMA_GITHUB_APP_SETUP.md +0 -199
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GLAMA_INTEGRATION.md +0 -181
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GLAMA_RESCAN_EMAIL.txt +0 -43
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GOLD_STATUS_ACHIEVEMENT.md +0 -197
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/GOLD_STATUS_UPDATE_2025_10_08.md +0 -378
- package/mcps/windows-computer-use-mcp/docs/_stale/glama-platform/README.md +0 -632
- package/mcps/windows-computer-use-mcp/docs/_stale/legacy/requirements-fastmcp.txt +0 -8
- package/mcps/windows-computer-use-mcp/docs/_stale/legacy/requirements_minimal.txt +0 -4
- package/mcps/windows-computer-use-mcp/docs/_stale/mcp-technical/CLAUDE_DESKTOP_DEBUGGING.md +0 -561
- package/mcps/windows-computer-use-mcp/docs/_stale/mcp-technical/CONTAINERIZATION_GUIDELINES.md +0 -707
- package/mcps/windows-computer-use-mcp/docs/_stale/mcp-technical/MCP_PRODUCTION_CHECKLIST.md +0 -101
- package/mcps/windows-computer-use-mcp/docs/_stale/mcp-technical/MONITORING_STACK_DEPLOYMENT.md +0 -532
- package/mcps/windows-computer-use-mcp/docs/_stale/mcp-technical/README.md +0 -266
- package/mcps/windows-computer-use-mcp/docs/_stale/mcp-technical/TROUBLESHOOTING_FASTMCP_2.12.md +0 -670
- package/mcps/windows-computer-use-mcp/docs/_stale/mcpb-packaging/MCPB_BUILDING_GUIDE.md +0 -1921
- package/mcps/windows-computer-use-mcp/docs/_stale/mcpb-packaging/MCPB_IMPLEMENTATION_SUMMARY.md +0 -387
- package/mcps/windows-computer-use-mcp/docs/_stale/mcpb-packaging/PYPI_PUBLISHING_GUIDE.md +0 -789
- package/mcps/windows-computer-use-mcp/docs/_stale/mcpb-packaging/README.md +0 -404
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/COMMUNITY_AND_SUPPORT.md +0 -976
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/LANGUAGE_SERVER_PROTOCOL_EXPLAINED.md +0 -416
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/MCP_TOOL_CORRUPTION_ISSUE.md +0 -279
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/NOTEPADPP_ALTERNATIVES.md +0 -308
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/NOTEPADPP_COLOR_FIX_2025_10_08.md +0 -187
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/NOTEPADPP_COMPLETE_GUIDE.md +0 -1259
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/NOTEPADPP_NUCLEAR_REINSTALL_2025_10_08.md +0 -196
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/NPP_WHITE_ON_WHITE_BATTLE_PLAN.md +0 -336
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/PLUGIN_ECOSYSTEM_COMPREHENSIVE.md +0 -887
- package/mcps/windows-computer-use-mcp/docs/_stale/notepadpp/README.md +0 -472
- package/mcps/windows-computer-use-mcp/docs/_stale/repository-protection/BACKUP_AND_RECOVERY_GUIDE.md +0 -455
- package/mcps/windows-computer-use-mcp/docs/_stale/repository-protection/BRANCH_PROTECTION_SETTINGS.md +0 -236
- package/mcps/windows-computer-use-mcp/docs/_stale/repository-protection/BRANCH_STRATEGY_AND_AI_WORKFLOW.md +0 -616
- package/mcps/windows-computer-use-mcp/docs/_stale/repository-protection/README.md +0 -333
- package/mcps/windows-computer-use-mcp/docs/_stale/serena/SERENA_COPY_TO_OTHER_REPOS.md +0 -159
- package/mcps/windows-computer-use-mcp/docs/_stale/serena/SERENA_GUIDE.md +0 -632
- package/mcps/windows-computer-use-mcp/docs/_stale/serena/SERENA_INSTALL_AND_TEST.md +0 -569
- package/mcps/windows-computer-use-mcp/docs/_stale/serena/SERENA_NEXT_STEPS.md +0 -351
- package/mcps/windows-computer-use-mcp/docs/_stale/serena/SERENA_QUICK_INSTALL.md +0 -195
- package/mcps/windows-computer-use-mcp/docs/_stale/state-tool-implementation.md +0 -498
- package/mcps/windows-computer-use-mcp/docs/composing-with-playwright.md +0 -55
- package/mcps/windows-computer-use-mcp/docs/cua-nsis-certification.md +0 -101
- package/mcps/windows-computer-use-mcp/docs/ocr.md +0 -107
- package/mcps/windows-computer-use-mcp/docs/py-stack.md +0 -47
- package/mcps/windows-computer-use-mcp/native/icons/icon.png +0 -0
- package/mcps/windows-computer-use-mcp/screenshot_demo.png +0 -0
- package/mcps/windows-computer-use-mcp/src/windows_computer_use_mcp/templates/vroidstudio/default/export_complete_toast.png +0 -0
- package/mcps/windows-computer-use-mcp/src/windows_computer_use_mcp/templates/vroidstudio/default/export_dialog_title.png +0 -0
- package/mcps/windows-computer-use-mcp/src/windows_computer_use_mcp/templates/vroidstudio/default/file_dialog_path_field.png +0 -0
- package/mcps/windows-computer-use-mcp/src/windows_computer_use_mcp/templates/vroidstudio/default/sample_tile_female.png +0 -0
- package/mcps/windows-computer-use-mcp/tests/README.md +0 -155
- package/mcps/windows-computer-use-mcp/tests/__init__.py +0 -1
- package/mcps/windows-computer-use-mcp/tests/conftest.py +0 -281
- package/mcps/windows-computer-use-mcp/tests/conftest_env.py +0 -116
- package/mcps/windows-computer-use-mcp/tests/e2e/conftest.py +0 -96
- package/mcps/windows-computer-use-mcp/tests/e2e/test_libreoffice_cua_loop.py +0 -72
- package/mcps/windows-computer-use-mcp/tests/test_app_integration.py +0 -83
- package/mcps/windows-computer-use-mcp/tests/test_app_profiles.py +0 -28
- package/mcps/windows-computer-use-mcp/tests/test_automation_assert.py +0 -185
- package/mcps/windows-computer-use-mcp/tests/test_automation_dialog.py +0 -43
- package/mcps/windows-computer-use-mcp/tests/test_automation_elements.py +0 -138
- package/mcps/windows-computer-use-mcp/tests/test_automation_keyboard.py +0 -57
- package/mcps/windows-computer-use-mcp/tests/test_automation_mouse.py +0 -57
- package/mcps/windows-computer-use-mcp/tests/test_automation_shortcut.py +0 -41
- package/mcps/windows-computer-use-mcp/tests/test_automation_task.py +0 -115
- package/mcps/windows-computer-use-mcp/tests/test_automation_windows.py +0 -105
- package/mcps/windows-computer-use-mcp/tests/test_cameras_api.py +0 -43
- package/mcps/windows-computer-use-mcp/tests/test_cua_parity.py +0 -51
- package/mcps/windows-computer-use-mcp/tests/test_dependency_failures.py +0 -39
- package/mcps/windows-computer-use-mcp/tests/test_desktop_state.py +0 -99
- package/mcps/windows-computer-use-mcp/tests/test_face_recognition.py +0 -238
- package/mcps/windows-computer-use-mcp/tests/test_face_recognition_api.py +0 -161
- package/mcps/windows-computer-use-mcp/tests/test_images/README.md +0 -28
- package/mcps/windows-computer-use-mcp/tests/test_mission.py +0 -42
- package/mcps/windows-computer-use-mcp/tests/test_portmanteau_windows_mock.py +0 -173
- package/mcps/windows-computer-use-mcp/tests/test_portmanteau_windows_real.py +0 -139
- package/mcps/windows-computer-use-mcp/tests/test_retry.py +0 -26
- package/mcps/windows-computer-use-mcp/tests/test_safety_api.py +0 -24
- package/mcps/windows-computer-use-mcp/tests/test_template_library.py +0 -53
- package/mcps/windows-computer-use-mcp/tests/test_utils.py +0 -185
- package/mcps/windows-computer-use-mcp/web_sota/src-tauri/icons/icon.png +0 -0
- package/skills/global_config/google-sheets-automation/SKILL.md +0 -150
- package/skills/global_config/senior-fullstack/SKILL.md +0 -221
- package/skills/global_config/senior-fullstack/references/architecture_patterns.md +0 -103
- package/skills/global_config/senior-fullstack/references/development_workflows.md +0 -103
- package/skills/global_config/senior-fullstack/references/tech_stack_guide.md +0 -103
- package/skills/global_config/senior-fullstack/scripts/code_quality_analyzer.py +0 -114
- package/skills/global_config/senior-fullstack/scripts/fullstack_scaffolder.py +0 -114
- package/skills/global_config/senior-fullstack/scripts/project_scaffolder.py +0 -114
|
@@ -1,1798 +0,0 @@
|
|
|
1
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
-
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import fs from 'node:fs/promises';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import net from 'node:net';
|
|
7
|
-
import { expectedCondition as conditionFromExpectation, splitExpectedConditions } from './expectation-utils.mjs';
|
|
8
|
-
import { evaluateAssertions, selectCaptureValue } from './test-runner-response-utils.mjs';
|
|
9
|
-
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = path.dirname(__filename);
|
|
12
|
-
const repoRoot = path.resolve(__dirname, '..');
|
|
13
|
-
const reportsDir = path.join(__dirname, 'reports');
|
|
14
|
-
|
|
15
|
-
// CRITICAL: Include both singular and plural forms for flexible matching
|
|
16
|
-
const failureKeywords = ['failed', 'error', 'exception', 'invalid', 'not found', 'not_found', 'missing', 'timed out', 'timeout', 'unsupported', 'unknown', 'not implemented', 'not_implemented', 'traversal', 'blocked', 'denied', 'forbidden', 'security', 'violation', 'invalid_path', 'object_not_found', 'actor_not_found', 'actors not found', 'not exist'];
|
|
17
|
-
const successKeywords = ['success', 'created', 'updated', 'deleted', 'completed', 'done', 'ok', 'skipped', 'handled'];
|
|
18
|
-
const bridgeDisconnectedIndicators = [
|
|
19
|
-
'unreal engine is not connected',
|
|
20
|
-
'automation bridge connection failed',
|
|
21
|
-
'automation bridge connection timeout',
|
|
22
|
-
'automation bridge not connected',
|
|
23
|
-
'ue_not_connected',
|
|
24
|
-
'bridge disconnected',
|
|
25
|
-
'connection lost',
|
|
26
|
-
'econnrefused',
|
|
27
|
-
'econnreset',
|
|
28
|
-
'socket hang up'
|
|
29
|
-
];
|
|
30
|
-
const infrastructureErrorCodes = [
|
|
31
|
-
'no_navmesh', 'no_nav_sys', 'no_world', 'no_component', 'no_smart_link',
|
|
32
|
-
'not_found', 'invalid_class', 'create_failed', 'spawn_failed', 'already_exists',
|
|
33
|
-
'asset_exists', 'invalid_bp', 'cdo_failed', 'level_already_exists', 'asset_not_found',
|
|
34
|
-
'texture_error', 'invalid_texture', 'source_invalid', 'lock_failed', 'node_not_found',
|
|
35
|
-
'physics_failed', 'function_not_found'
|
|
36
|
-
];
|
|
37
|
-
const baseCrashIndicators = ['1006', 'econnreset', 'socket hang up', 'connection lost', 'bridge disconnected', 'ue_not_connected', 'automation bridge not connected'];
|
|
38
|
-
const crashIndicatorsWithDisconnect = [...baseCrashIndicators, 'disconnect'];
|
|
39
|
-
// Defaults for spawning the MCP server.
|
|
40
|
-
let serverCommand = process.env.UNREAL_MCP_SERVER_CMD ?? 'node';
|
|
41
|
-
let serverArgs = process.env.UNREAL_MCP_SERVER_ARGS ? process.env.UNREAL_MCP_SERVER_ARGS.split(',') : [path.join(repoRoot, 'dist', 'cli.js')];
|
|
42
|
-
const serverCwd = process.env.UNREAL_MCP_SERVER_CWD ?? repoRoot;
|
|
43
|
-
const serverEnv = Object.assign({}, process.env);
|
|
44
|
-
|
|
45
|
-
const DEFAULT_RESPONSE_LOG_MAX_CHARS = 6000; // default max chars
|
|
46
|
-
const RESPONSE_LOGGING_ENABLED = process.env.UNREAL_MCP_TEST_LOG_RESPONSES !== '0';
|
|
47
|
-
|
|
48
|
-
function clampString(value, maxChars) {
|
|
49
|
-
if (typeof value !== 'string') return '';
|
|
50
|
-
if (value.length <= maxChars) return value;
|
|
51
|
-
return value.slice(0, maxChars) + `\n... (truncated, ${value.length - maxChars} chars omitted)`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function tryParseJson(text) {
|
|
55
|
-
if (typeof text !== 'string') return null;
|
|
56
|
-
try {
|
|
57
|
-
return JSON.parse(text);
|
|
58
|
-
} catch {
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function normalizeMcpResponse(response) {
|
|
64
|
-
const normalized = {
|
|
65
|
-
isError: Boolean(response?.isError),
|
|
66
|
-
structuredContent: response?.structuredContent ?? null,
|
|
67
|
-
contentText: '',
|
|
68
|
-
content: response?.content ?? undefined
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
if (normalized.structuredContent === null && Array.isArray(response?.content)) {
|
|
72
|
-
for (const entry of response.content) {
|
|
73
|
-
if (entry?.type !== 'text' || typeof entry.text !== 'string') continue;
|
|
74
|
-
const parsed = tryParseJson(entry.text);
|
|
75
|
-
if (parsed !== null) {
|
|
76
|
-
normalized.structuredContent = parsed;
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (Array.isArray(response?.content) && response.content.length > 0) {
|
|
83
|
-
normalized.contentText = response.content
|
|
84
|
-
.map((entry) => (entry && typeof entry.text === 'string' ? entry.text : ''))
|
|
85
|
-
.filter((text) => text.length > 0)
|
|
86
|
-
.join('\n');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return normalized;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function logMcpResponse(toolName, normalizedResponse) {
|
|
93
|
-
const maxChars = Number(process.env.UNREAL_MCP_TEST_RESPONSE_MAX_CHARS ?? DEFAULT_RESPONSE_LOG_MAX_CHARS);
|
|
94
|
-
const payload = {
|
|
95
|
-
isError: normalizedResponse.isError,
|
|
96
|
-
structuredContent: normalizedResponse.structuredContent,
|
|
97
|
-
contentText: normalizedResponse.contentText,
|
|
98
|
-
content: normalizedResponse.content
|
|
99
|
-
};
|
|
100
|
-
const json = JSON.stringify(payload, null, 2);
|
|
101
|
-
console.log(`[MCP RESPONSE] ${toolName}:`);
|
|
102
|
-
console.log(clampString(json, Number.isFinite(maxChars) && maxChars > 0 ? maxChars : DEFAULT_RESPONSE_LOG_MAX_CHARS));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function collectResponseText(value) {
|
|
106
|
-
if (value === null || value === undefined) return '';
|
|
107
|
-
if (typeof value === 'string') return value;
|
|
108
|
-
if (typeof value === 'number' || typeof value === 'boolean') return String(value);
|
|
109
|
-
if (Array.isArray(value)) return value.map((entry) => collectResponseText(entry)).join(' ');
|
|
110
|
-
if (typeof value === 'object') {
|
|
111
|
-
return Object.values(value).map((entry) => collectResponseText(entry)).join(' ');
|
|
112
|
-
}
|
|
113
|
-
return '';
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function isRecord(value) {
|
|
117
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function findNestedFailure(value) {
|
|
121
|
-
if (!isRecord(value)) return null;
|
|
122
|
-
if (value.success === false || value.isError === true) return value;
|
|
123
|
-
|
|
124
|
-
const dataFailure = findNestedFailure(value.data);
|
|
125
|
-
if (dataFailure) return dataFailure;
|
|
126
|
-
|
|
127
|
-
const resultFailure = findNestedFailure(value.result);
|
|
128
|
-
if (resultFailure) return resultFailure;
|
|
129
|
-
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function firstNonEmptyString(...values) {
|
|
134
|
-
for (const value of values) {
|
|
135
|
-
if (typeof value === 'string' && value.length > 0) return value;
|
|
136
|
-
}
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function normalizeConditionText(value) {
|
|
141
|
-
return String(value).replace(/_/g, ' ').replace(/\s+/g, ' ').trim();
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function conditionMatchesResponseText(condition, responseText) {
|
|
145
|
-
const normalizedCondition = normalizeConditionText(condition);
|
|
146
|
-
const normalizedResponseText = normalizeConditionText(responseText);
|
|
147
|
-
if (!normalizedCondition || !normalizedResponseText) return false;
|
|
148
|
-
if (responseText.includes(condition) || normalizedResponseText.includes(normalizedCondition)) return true;
|
|
149
|
-
if (normalizedCondition === 'already exists') return /\b(already|asset|level) exists\b/.test(normalizedResponseText);
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const explicitFailureAlternatives = [
|
|
154
|
-
'already exists',
|
|
155
|
-
'already_exists',
|
|
156
|
-
'asset exists',
|
|
157
|
-
'asset_exists',
|
|
158
|
-
'level already exists',
|
|
159
|
-
'level_already_exists',
|
|
160
|
-
'not found',
|
|
161
|
-
'not_found',
|
|
162
|
-
'object_not_found',
|
|
163
|
-
'actor_not_found',
|
|
164
|
-
'actors not found',
|
|
165
|
-
'asset_not_found',
|
|
166
|
-
'node_not_found',
|
|
167
|
-
'function_not_found',
|
|
168
|
-
'property_not_found',
|
|
169
|
-
'component_not_found',
|
|
170
|
-
'class_not_found',
|
|
171
|
-
'does not exist',
|
|
172
|
-
'not exist',
|
|
173
|
-
'not loaded',
|
|
174
|
-
'not_loaded',
|
|
175
|
-
'not in pie',
|
|
176
|
-
'not_in_pie',
|
|
177
|
-
'cannot enable',
|
|
178
|
-
'not enabled',
|
|
179
|
-
'not partitioned',
|
|
180
|
-
'not_partitioned',
|
|
181
|
-
'not available',
|
|
182
|
-
'world partition',
|
|
183
|
-
'sc_disabled'
|
|
184
|
-
];
|
|
185
|
-
const normalizedExplicitFailureAlternatives = explicitFailureAlternatives.map(normalizeConditionText);
|
|
186
|
-
|
|
187
|
-
function isExplicitFailureAlternative(condition) {
|
|
188
|
-
const normalizedCondition = normalizeConditionText(condition);
|
|
189
|
-
return explicitFailureAlternatives.some((alternative, index) => {
|
|
190
|
-
const normalizedAlternative = normalizedExplicitFailureAlternatives[index];
|
|
191
|
-
return condition.includes(alternative) || normalizedCondition.includes(normalizedAlternative);
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function findMatchedExplicitFailureAlternative(conditions, responseText) {
|
|
196
|
-
for (const condition of conditions.slice(1)) {
|
|
197
|
-
if (!isExplicitFailureAlternative(condition)) continue;
|
|
198
|
-
if (conditionMatchesResponseText(condition, responseText)) return condition;
|
|
199
|
-
}
|
|
200
|
-
return null;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function getExpectationIntent(expectation) {
|
|
204
|
-
const expectedCondition = conditionFromExpectation(expectation);
|
|
205
|
-
const lowerExpected = expectedCondition.toLowerCase();
|
|
206
|
-
const expectedConditions = splitExpectedConditions(lowerExpected);
|
|
207
|
-
const primaryCondition = expectedConditions[0] ?? '';
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
expectedCondition,
|
|
211
|
-
lowerExpected,
|
|
212
|
-
expectedConditions,
|
|
213
|
-
primaryCondition,
|
|
214
|
-
containsFailure: failureKeywords.some((word) => lowerExpected.includes(word)),
|
|
215
|
-
containsSuccess: successKeywords.some((word) => lowerExpected.includes(word)),
|
|
216
|
-
primaryExpectsSuccess: successKeywords.some((word) => primaryCondition.includes(word)),
|
|
217
|
-
primaryExpectsFailure: failureKeywords.some((word) => primaryCondition.includes(word)),
|
|
218
|
-
primaryExpectsTimeout: primaryCondition === 'timeout' || primaryCondition.includes('timeout')
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function normalizeResponseForEvaluation(response) {
|
|
223
|
-
const normalized = normalizeMcpResponse(response);
|
|
224
|
-
return { ...response, structuredContent: normalized.structuredContent, contentText: normalized.contentText };
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function responseTextContext(response, outcome) {
|
|
228
|
-
const actualMessage = outcome.actualMessage || response.message || null;
|
|
229
|
-
const actualError = outcome.actualError || response.error || null;
|
|
230
|
-
const contentText = typeof response.contentText === 'string'
|
|
231
|
-
? response.contentText
|
|
232
|
-
: normalizeMcpResponse(response).contentText;
|
|
233
|
-
const messageStr = (actualMessage || '').toString().toLowerCase();
|
|
234
|
-
const errorStr = (actualError || '').toString().toLowerCase();
|
|
235
|
-
const contentStr = contentText.toString().toLowerCase();
|
|
236
|
-
|
|
237
|
-
return {
|
|
238
|
-
actualMessage,
|
|
239
|
-
actualError,
|
|
240
|
-
contentText,
|
|
241
|
-
messageStr,
|
|
242
|
-
errorStr,
|
|
243
|
-
contentStr,
|
|
244
|
-
combined: `${messageStr} ${errorStr} ${contentStr}`
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function responseDetail(response) {
|
|
249
|
-
if (response.isError) {
|
|
250
|
-
return response.content?.map((entry) => ('text' in entry ? entry.text : JSON.stringify(entry))).join('\n');
|
|
251
|
-
}
|
|
252
|
-
if (response.structuredContent) return JSON.stringify(response.structuredContent);
|
|
253
|
-
if (response.content?.length) {
|
|
254
|
-
return response.content.map((entry) => ('text' in entry ? entry.text : JSON.stringify(entry))).join('\n');
|
|
255
|
-
}
|
|
256
|
-
return 'No structured response returned';
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function getTestCaseTimeoutMs(testCase) {
|
|
260
|
-
return Number(process.env.UNREAL_MCP_TEST_CASE_TIMEOUT_MS ?? testCase.timeoutMs ?? testCase.arguments?.timeoutMs ?? '5000');
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
export function getResponseOutcome(response) {
|
|
264
|
-
const structuredContent = isRecord(response?.structuredContent) ? response.structuredContent : {};
|
|
265
|
-
const nestedFailure = findNestedFailure(structuredContent);
|
|
266
|
-
const structuredSuccess = nestedFailure
|
|
267
|
-
? false
|
|
268
|
-
: (typeof structuredContent.success === 'boolean' ? structuredContent.success : undefined);
|
|
269
|
-
const actualSuccess = structuredSuccess ?? !(response?.isError || structuredContent.isError);
|
|
270
|
-
const errorSource = nestedFailure ?? structuredContent;
|
|
271
|
-
|
|
272
|
-
return {
|
|
273
|
-
structuredContent,
|
|
274
|
-
nestedFailure,
|
|
275
|
-
structuredSuccess,
|
|
276
|
-
actualSuccess,
|
|
277
|
-
actualError: firstNonEmptyString(errorSource.error, errorSource.errorCode, structuredContent.error),
|
|
278
|
-
actualMessage: firstNonEmptyString(errorSource.message, structuredContent.message)
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function isBridgeDisconnectedSignal(value) {
|
|
283
|
-
const text = collectResponseText(value).toLowerCase();
|
|
284
|
-
if (!text) return false;
|
|
285
|
-
return bridgeDisconnectedIndicators.some((indicator) => text.includes(indicator));
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function formatResultLine(testCase, status, detail, durationMs) {
|
|
289
|
-
const durationText = typeof durationMs === 'number' ? ` (${durationMs.toFixed(1)} ms)` : '';
|
|
290
|
-
return `[${status.toUpperCase()}] ${testCase.scenario}${durationText}${detail ? ` => ${detail}` : ''}`;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
async function persistResults(toolName, results) {
|
|
294
|
-
await fs.mkdir(reportsDir, { recursive: true });
|
|
295
|
-
const timestamp = new Date().toISOString().replace(/[:]/g, '-');
|
|
296
|
-
const resultsPath = path.join(reportsDir, `${toolName}-test-results-${timestamp}.json`);
|
|
297
|
-
const serializable = results.map((result) => ({
|
|
298
|
-
scenario: result.scenario,
|
|
299
|
-
toolName: result.toolName,
|
|
300
|
-
arguments: result.arguments,
|
|
301
|
-
expected: result.expected,
|
|
302
|
-
status: result.status,
|
|
303
|
-
durationMs: result.durationMs,
|
|
304
|
-
detail: result.detail,
|
|
305
|
-
responseSuccess: result.responseSuccess,
|
|
306
|
-
responseIsError: result.responseIsError,
|
|
307
|
-
responseError: result.responseError,
|
|
308
|
-
responseMessage: result.responseMessage
|
|
309
|
-
}));
|
|
310
|
-
await fs.writeFile(resultsPath, JSON.stringify({ generatedAt: new Date().toISOString(), toolName, results: serializable }, null, 2));
|
|
311
|
-
return resultsPath;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function summarize(toolName, results, resultsPath) {
|
|
315
|
-
const totals = results.reduce((acc, result) => { acc.total += 1; acc[result.status] = (acc[result.status] ?? 0) + 1; return acc; }, { total: 0, passed: 0, failed: 0, skipped: 0 });
|
|
316
|
-
console.log('\n' + '='.repeat(60));
|
|
317
|
-
console.log(`${toolName} Test Summary`);
|
|
318
|
-
console.log('='.repeat(60));
|
|
319
|
-
console.log(`Total cases: ${totals.total}`);
|
|
320
|
-
console.log(`✅ Passed: ${totals.passed ?? 0}`);
|
|
321
|
-
console.log(`❌ Failed: ${totals.failed ?? 0}`);
|
|
322
|
-
console.log(`⏭️ Skipped: ${totals.skipped ?? 0}`);
|
|
323
|
-
if (totals.passed && totals.total > 0) console.log(`Pass rate: ${((totals.passed / totals.total) * 100).toFixed(1)}%`);
|
|
324
|
-
console.log(`Results saved to: ${resultsPath}`);
|
|
325
|
-
console.log('='.repeat(60));
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Evaluates whether a test case passed based on expected outcome
|
|
330
|
-
*/
|
|
331
|
-
export function evaluateExpectation(testCase, response) {
|
|
332
|
-
const expectation = testCase.expected;
|
|
333
|
-
const {
|
|
334
|
-
expectedCondition,
|
|
335
|
-
lowerExpected,
|
|
336
|
-
expectedConditions,
|
|
337
|
-
primaryCondition,
|
|
338
|
-
containsFailure,
|
|
339
|
-
containsSuccess,
|
|
340
|
-
primaryExpectsSuccess,
|
|
341
|
-
primaryExpectsFailure
|
|
342
|
-
} = getExpectationIntent(expectation);
|
|
343
|
-
|
|
344
|
-
const responseOutcome = getResponseOutcome(response);
|
|
345
|
-
const structuredSuccess = responseOutcome.structuredSuccess;
|
|
346
|
-
const actualSuccess = responseOutcome.actualSuccess;
|
|
347
|
-
const { actualError, actualMessage, messageStr, errorStr, contentStr, combined } = responseTextContext(response, responseOutcome);
|
|
348
|
-
const isObjectExpectation = typeof expectation === 'object' && expectation !== null;
|
|
349
|
-
const serializedResponse = JSON.stringify(response).toLowerCase();
|
|
350
|
-
const matchedExplicitFailureAlternative = !actualSuccess && primaryExpectsSuccess
|
|
351
|
-
? findMatchedExplicitFailureAlternative(expectedConditions, combined)
|
|
352
|
-
: null;
|
|
353
|
-
|
|
354
|
-
// Hard placeholder signals must fail before success alternatives are evaluated.
|
|
355
|
-
// Engine capability fallbacks such as "unsupported" or "not available" remain
|
|
356
|
-
// valid only when the expectation explicitly allows them.
|
|
357
|
-
const hardPluginFailureIndicators = ['does not match prefix', 'unknown', 'not implemented', 'not_implemented'];
|
|
358
|
-
const hardPluginFailureText = `${messageStr} ${errorStr}`;
|
|
359
|
-
const hasHardPluginFailure = hardPluginFailureIndicators.some(term => hardPluginFailureText.includes(term));
|
|
360
|
-
if (primaryExpectsSuccess && hasHardPluginFailure) {
|
|
361
|
-
return {
|
|
362
|
-
passed: false,
|
|
363
|
-
reason: `Expected success but plugin reported failure: ${actualMessage || actualError}`
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Object expectations can intentionally assert exact controlled error codes
|
|
368
|
-
// (for example NOT_PARTITIONED guards). Honor those before the generic
|
|
369
|
-
// "expected success" rejection below so tests don't need broad `error|...`
|
|
370
|
-
// strings that can mask unrelated failures.
|
|
371
|
-
if (isObjectExpectation && !actualSuccess && expectation.errorPattern) {
|
|
372
|
-
const pattern = String(expectation.errorPattern).toLowerCase();
|
|
373
|
-
if (serializedResponse.includes(pattern) || combined.includes(pattern)) {
|
|
374
|
-
return { passed: true, reason: `Error pattern matched: ${expectation.errorPattern}` };
|
|
375
|
-
}
|
|
376
|
-
return { passed: false, reason: `Error pattern not matched: ${expectation.errorPattern}` };
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Pipe alternatives can intentionally allow specific idempotent failure
|
|
380
|
-
// outcomes such as `success|already exists` and cleanup cases like
|
|
381
|
-
// `success|not found`. Keep rejecting broad fallbacks like `success|error`.
|
|
382
|
-
if (matchedExplicitFailureAlternative) {
|
|
383
|
-
return { passed: true, reason: `Expected explicit failure alternative met: ${matchedExplicitFailureAlternative}` };
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// CRITICAL: If response explicitly indicates an error (isError: true or structuredContent.success: false
|
|
387
|
-
// or structuredContent.isError: true) and the PRIMARY expectation is success (not just a fallback alternative),
|
|
388
|
-
// FAIL immediately. This prevents false positives where tests like "success|handled|error" pass even when
|
|
389
|
-
// the engine returns success: false.
|
|
390
|
-
if ((response.isError === true || response.structuredContent?.isError === true || structuredSuccess === false) && !primaryExpectsFailure) {
|
|
391
|
-
const errorReason = actualError || actualMessage || response.error || response.message || 'Unknown error';
|
|
392
|
-
return {
|
|
393
|
-
passed: false,
|
|
394
|
-
reason: `Response indicates error but test expected success (primary intent: ${primaryCondition}): ${errorReason}`
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// CRITICAL FIX: Detect infrastructure errors that should FAIL tests even if
|
|
399
|
-
// structuredContent.success is true or the expectation allows success as fallback.
|
|
400
|
-
// This prevents false positives where tests like "error|success|handled" pass
|
|
401
|
-
// even when the engine returns NO_NAVMESH, NOT_FOUND, NO_COMPONENT, etc.
|
|
402
|
-
// Note: 'actor_not_found' is a valid error for negative tests - do NOT add it here
|
|
403
|
-
// as that would fail tests that expect actor_not_found as the error.
|
|
404
|
-
const hasInfrastructureError = infrastructureErrorCodes.some(code =>
|
|
405
|
-
errorStr === code || errorStr.includes(code) || messageStr.includes(code)
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
if (hasInfrastructureError && !primaryExpectsFailure) {
|
|
409
|
-
return {
|
|
410
|
-
passed: false,
|
|
411
|
-
reason: `Infrastructure error detected but test expected success (primary intent: ${primaryCondition}): ${actualError || actualMessage}`
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// CRITICAL FIX: Detect crash/connection loss in error responses that should FAIL tests
|
|
416
|
-
// unless explicitly expected. This prevents false positives where tests like "error|notfound"
|
|
417
|
-
// pass on crash because "error" matches any error message.
|
|
418
|
-
// IMPORTANT: Only check crash indicators when response indicates FAILURE. A success response
|
|
419
|
-
// that contains "disconnect" (like "Disconnect operation completed.") is NOT a crash.
|
|
420
|
-
// CRITICAL FIX: Also detect "not connected" messages that indicate bridge disconnection
|
|
421
|
-
// FIX: Only check for crash indicators if response is NOT a success (success: true)
|
|
422
|
-
// This prevents false positives where "Node disconnection partial" (a valid success message)
|
|
423
|
-
// incorrectly matches "disconnect" as a substring.
|
|
424
|
-
// Word-boundary checks for ambiguous terms
|
|
425
|
-
const hasDisconnect = /\bdisconnect(ed)?\b/i.test(errorStr) || /\bdisconnect(ed)?\b/i.test(messageStr);
|
|
426
|
-
const hasConnectionLost = /\bconnection lost\b/i.test(errorStr) || /\bconnection lost\b/i.test(messageStr);
|
|
427
|
-
const hasNotConnected = /\bnot connected\b/i.test(errorStr) || /\bnot connected\b/i.test(messageStr);
|
|
428
|
-
|
|
429
|
-
// Only include 'disconnect' as crash indicator when response indicates FAILURE
|
|
430
|
-
// This fixes false positives for disconnect_nodes action that returns "Disconnect operation completed."
|
|
431
|
-
const crashIndicators = actualSuccess ? baseCrashIndicators : crashIndicatorsWithDisconnect;
|
|
432
|
-
const hasCrashIndicator = (crashIndicators.some(ind =>
|
|
433
|
-
errorStr.includes(ind) || messageStr.includes(ind) || combined.includes(ind)
|
|
434
|
-
)) || hasDisconnect || hasConnectionLost || hasNotConnected;
|
|
435
|
-
|
|
436
|
-
// Only fail on crash indicators if response is NOT successful
|
|
437
|
-
// "Node disconnection partial" is a SUCCESS message, not a crash indicator
|
|
438
|
-
const responseSuccess = structuredSuccess === true;
|
|
439
|
-
const isActuallyCrash = hasCrashIndicator && !responseSuccess;
|
|
440
|
-
|
|
441
|
-
const explicitlyExpectsCrash = lowerExpected.includes('disconnect') ||
|
|
442
|
-
lowerExpected.includes('crash') ||
|
|
443
|
-
lowerExpected.includes('connection lost') ||
|
|
444
|
-
lowerExpected.includes('ue_not_connected') ||
|
|
445
|
-
lowerExpected.includes('not connected');
|
|
446
|
-
|
|
447
|
-
// Only treat as crash if response indicates failure AND crash indicators found
|
|
448
|
-
if (isActuallyCrash && !explicitlyExpectsCrash) {
|
|
449
|
-
return {
|
|
450
|
-
passed: false,
|
|
451
|
-
reason: `Crash/connection loss detected but test did not expect it: ${actualError || actualMessage}`
|
|
452
|
-
};
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// CRITICAL FIX: Detect timeout in structured responses that should FAIL tests
|
|
456
|
-
// unless "timeout" is the PRIMARY expectation. This prevents false positives where
|
|
457
|
-
// tests like "error" or "error|timeout" pass on timeout when the timeout is an
|
|
458
|
-
// infrastructure failure, not a validation error.
|
|
459
|
-
// IMPORTANT: Use word-boundary matching to avoid false positives from "timeoutMs"
|
|
460
|
-
// in valid parameter lists (e.g., "Valid params: action, name, path, timeoutMs").
|
|
461
|
-
const hasTimeout = /\btimeout\b/i.test(combined) || combined.includes('timed out');
|
|
462
|
-
const explicitlyExpectsTimeout = primaryCondition === 'timeout' || primaryCondition.includes('timeout');
|
|
463
|
-
|
|
464
|
-
if (hasTimeout && !explicitlyExpectsTimeout) {
|
|
465
|
-
return {
|
|
466
|
-
passed: false,
|
|
467
|
-
reason: `Timeout detected (infrastructure failure) but test did not expect timeout as primary condition (expected: ${primaryCondition}): ${actualError || actualMessage}`
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// CRITICAL FIX: Detect attachment failure for add_*_volume actions.
|
|
472
|
-
// When a volume is created but attachment fails (e.g., static volume to movable actor),
|
|
473
|
-
// the test should FAIL because the requested attachment did not succeed.
|
|
474
|
-
const attachmentSucceeded = response.structuredContent?.attachmentSucceeded;
|
|
475
|
-
if (attachmentSucceeded === false && primaryExpectsSuccess && !lowerExpected.includes('attachment failed')) {
|
|
476
|
-
return {
|
|
477
|
-
passed: false,
|
|
478
|
-
reason: `Attachment failed for volume operation: ${actualMessage}. Volume was created but could not be attached to target actor.`
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
if (isObjectExpectation && actualSuccess && expectation.successPattern) {
|
|
483
|
-
const pattern = String(expectation.successPattern).toLowerCase();
|
|
484
|
-
if (serializedResponse.includes(pattern) || combined.includes(pattern)) {
|
|
485
|
-
return { passed: true, reason: `Success pattern matched: ${expectation.successPattern}` };
|
|
486
|
-
}
|
|
487
|
-
return { passed: false, reason: `Success pattern not matched: ${expectation.successPattern}` };
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// Handle multi-condition expectations using "or" or pipe separators
|
|
491
|
-
// e.g., "success or LOAD_FAILED" or "success|no_instances|load_failed"
|
|
492
|
-
if (expectedConditions.length > 1) {
|
|
493
|
-
for (const condition of expectedConditions) {
|
|
494
|
-
if (successKeywords.some((kw) => condition.includes(kw)) && actualSuccess === true) {
|
|
495
|
-
return { passed: true, reason: JSON.stringify(response.structuredContent) };
|
|
496
|
-
}
|
|
497
|
-
if (condition === 'handled' && response.structuredContent && response.structuredContent.handled === true) {
|
|
498
|
-
return { passed: true, reason: 'Handled gracefully' };
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// Special-case timeout expectations so that MCP transport timeouts
|
|
502
|
-
// (e.g. "Request timed out") satisfy conditions where "timeout" is
|
|
503
|
-
// the PRIMARY expected outcome (not just an alternative).
|
|
504
|
-
// This prevents false positives where "error|timeout" passes on timeout
|
|
505
|
-
// when the primary expectation is actually "error" (validation failure).
|
|
506
|
-
// Use word-boundary matching to avoid false positives from "timeoutMs"
|
|
507
|
-
if ((condition === 'timeout' || condition.includes('timeout')) && primaryCondition === condition) {
|
|
508
|
-
if (/\btimeout\b/i.test(combined) || combined.includes('timed out')) {
|
|
509
|
-
return { passed: true, reason: `Expected timeout condition met: ${condition}` };
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// CRITICAL FIX: Only match failure keywords in response if PRIMARY intent expects failure
|
|
514
|
-
// This prevents false positives where "success|handled|object_not_found" passes when
|
|
515
|
-
// response is success=false with "object_not_found" error - primary was "success"!
|
|
516
|
-
const conditionIsFailure = failureKeywords.some((kw) => condition.includes(kw));
|
|
517
|
-
const conditionIsSuccess = successKeywords.some((kw) => condition.includes(kw));
|
|
518
|
-
|
|
519
|
-
// CRITICAL FIX: If condition is "error" and response.isError is true, match it
|
|
520
|
-
// This handles cases where the error message doesn't contain the word "error" but
|
|
521
|
-
// isError: true clearly indicates an error state.
|
|
522
|
-
if (condition === 'error' && (response.isError === true || response.structuredContent?.isError === true)) {
|
|
523
|
-
return { passed: true, reason: `Expected condition met: isError=true` };
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
// Only allow substring match if:
|
|
527
|
-
// 1. Condition is a success keyword AND actualSuccess is true, OR
|
|
528
|
-
// 2. Condition is a failure keyword AND primary expects failure, OR
|
|
529
|
-
// 3. Condition is neither success nor failure keyword (neutral like "handled")
|
|
530
|
-
if (combined.includes(condition)) {
|
|
531
|
-
if (conditionIsSuccess && actualSuccess === true) {
|
|
532
|
-
return { passed: true, reason: `Expected condition met: ${condition}` };
|
|
533
|
-
}
|
|
534
|
-
if (conditionIsFailure && primaryExpectsFailure) {
|
|
535
|
-
return { passed: true, reason: `Expected condition met: ${condition}` };
|
|
536
|
-
}
|
|
537
|
-
if (!conditionIsSuccess && !conditionIsFailure) {
|
|
538
|
-
// Neutral keyword (like "handled") - but still require that actualSuccess matches primary intent
|
|
539
|
-
if ((primaryExpectsSuccess && actualSuccess === true) || (primaryExpectsFailure && actualSuccess === false)) {
|
|
540
|
-
return { passed: true, reason: `Expected condition met: ${condition}` };
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
// If none of the OR/pipe conditions matched, it's a failure
|
|
546
|
-
return { passed: false, reason: `None of the expected conditions matched: ${expectedCondition}` };
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// Also flag common automation/plugin failure phrases.
|
|
550
|
-
// Placeholder/not-implemented responses must never satisfy success tests.
|
|
551
|
-
const pluginFailureIndicators = ['does not match prefix', 'unknown', 'unavailable', 'unsupported', 'not implemented', 'not_implemented'];
|
|
552
|
-
const pluginFailureText = `${messageStr} ${errorStr}`;
|
|
553
|
-
const hasPluginFailure = pluginFailureIndicators.some(term => pluginFailureText.includes(term));
|
|
554
|
-
|
|
555
|
-
if (!containsFailure && hasPluginFailure) {
|
|
556
|
-
return {
|
|
557
|
-
passed: false,
|
|
558
|
-
reason: `Expected success but plugin reported failure: ${actualMessage || actualError}`
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// CRITICAL: Check if message says "failed" but success is true (FALSE POSITIVE)
|
|
563
|
-
if (actualSuccess && (
|
|
564
|
-
messageStr.includes('failed') ||
|
|
565
|
-
messageStr.includes('python execution failed') ||
|
|
566
|
-
errorStr.includes('failed')
|
|
567
|
-
)) {
|
|
568
|
-
return {
|
|
569
|
-
passed: false,
|
|
570
|
-
reason: `False positive: success=true but message indicates failure: ${actualMessage}`
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// CRITICAL FIX: UE_NOT_CONNECTED errors should ALWAYS fail tests unless explicitly expected
|
|
575
|
-
if (actualError === 'UE_NOT_CONNECTED') {
|
|
576
|
-
const explicitlyExpectsDisconnection = lowerExpected.includes('not connected') ||
|
|
577
|
-
lowerExpected.includes('ue_not_connected') ||
|
|
578
|
-
lowerExpected.includes('disconnected');
|
|
579
|
-
if (!explicitlyExpectsDisconnection) {
|
|
580
|
-
return {
|
|
581
|
-
passed: false,
|
|
582
|
-
reason: `Test requires Unreal Engine connection, but got: ${actualError} - ${actualMessage}`
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// For tests that expect specific error types, validate the actual error matches
|
|
588
|
-
const expectedFailure = containsFailure && !containsSuccess;
|
|
589
|
-
if (expectedFailure && !actualSuccess) {
|
|
590
|
-
// Test expects failure and got failure - but verify it's the RIGHT kind of failure
|
|
591
|
-
const lowerReason = actualMessage?.toLowerCase() || actualError?.toLowerCase() || contentStr || '';
|
|
592
|
-
|
|
593
|
-
// Check for specific error types (not just generic "error" keyword)
|
|
594
|
-
// Include security-related keywords for path traversal / injection tests
|
|
595
|
-
// Include engine-specific error codes (OBJECT_NOT_FOUND, ACTOR_NOT_FOUND)
|
|
596
|
-
// Support both lowercase (for readability) and uppercase (engine output) variants
|
|
597
|
-
// CRITICAL FIX: Include plural forms like 'actors not found' to match 'actor_not_found'
|
|
598
|
-
// The engine may return "Actors not found" (plural) for batch operations
|
|
599
|
-
const specificErrorTypes = ['not found', 'not_found', 'invalid', 'missing', 'already exists', 'does not exist', 'sc_disabled', 'invalid_path', 'security', 'blocked', 'violation', 'object_not_found', 'actor_not_found', 'actors not found', 'CLASS_NOT_FOUND', 'ACTOR_NOT_FOUND', 'OBJECT_NOT_FOUND', 'COMPONENT_NOT_FOUND', 'PHYSICS_FAILED', 'FUNCTION_NOT_FOUND', 'NOT_FOUND', 'PROPERTY_NOT_FOUND'];
|
|
600
|
-
const expectedErrorType = specificErrorTypes.find(type => lowerExpected.includes(type.toLowerCase()));
|
|
601
|
-
// Normalize underscores/spaces for comparison (engine may return NOT_FOUND or "not found")
|
|
602
|
-
const normalizedReason = lowerReason.replace(/_/g, ' ');
|
|
603
|
-
const normalizedExpected = expectedErrorType ? expectedErrorType.toLowerCase().replace(/_/g, ' ') : '';
|
|
604
|
-
let errorTypeMatch = expectedErrorType ?
|
|
605
|
-
(normalizedReason.includes(normalizedExpected) || lowerReason.includes(expectedErrorType.toLowerCase()) || lowerReason.includes(expectedErrorType.toUpperCase())) :
|
|
606
|
-
failureKeywords.some(keyword => lowerExpected.includes(keyword) && lowerReason.includes(keyword));
|
|
607
|
-
|
|
608
|
-
// Also check detail field if main error check failed (handles wrapped exceptions)
|
|
609
|
-
if (!errorTypeMatch && response.detail && typeof response.detail === 'string') {
|
|
610
|
-
const lowerDetail = response.detail.toLowerCase();
|
|
611
|
-
if (expectedErrorType) {
|
|
612
|
-
if (lowerDetail.includes(expectedErrorType)) errorTypeMatch = true;
|
|
613
|
-
} else {
|
|
614
|
-
// If no specific error type, just check if detail contains expected string
|
|
615
|
-
if (lowerDetail.includes(lowerExpected)) errorTypeMatch = true;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// If expected outcome specifies an error type, actual error should match it
|
|
620
|
-
if (lowerExpected.includes('not found') || lowerExpected.includes('not_found') || lowerExpected.includes('invalid') ||
|
|
621
|
-
lowerExpected.includes('missing') || lowerExpected.includes('already exists') ||
|
|
622
|
-
lowerExpected.includes('sc_disabled') || lowerExpected.includes('security') ||
|
|
623
|
-
lowerExpected.includes('blocked') || lowerExpected.includes('violation') ||
|
|
624
|
-
lowerExpected.includes('object_not_found') || lowerExpected.includes('actor_not_found') ||
|
|
625
|
-
lowerExpected.includes('actors not found') || // CRITICAL FIX: Handle plural form
|
|
626
|
-
lowerExpected.includes('class_not_found') || lowerExpected.includes('component_not_found') ||
|
|
627
|
-
lowerExpected.includes('physics_failed') || lowerExpected.includes('function_not_found') ||
|
|
628
|
-
lowerExpected.includes('property_not_found')) {
|
|
629
|
-
|
|
630
|
-
// CRITICAL FIX: Special handling for actor_not_found vs "actors not found" (plural)
|
|
631
|
-
// The engine may return "Actors not found" for batch operations even for single actor
|
|
632
|
-
if ((lowerExpected.includes('actor_not_found') || lowerExpected.includes('actors not found')) &&
|
|
633
|
-
(normalizedReason.includes('actors not found') || normalizedReason.includes('actor not found'))) {
|
|
634
|
-
return { passed: true, reason: `Expected error type matched (actor/actors not found): ${actualMessage || actualError}` };
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
const passed = errorTypeMatch;
|
|
638
|
-
const reason = responseDetail(response);
|
|
639
|
-
return { passed, reason };
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
// Default evaluation logic
|
|
644
|
-
const passed = expectedFailure ? !actualSuccess : !!actualSuccess;
|
|
645
|
-
const reason = responseDetail(response);
|
|
646
|
-
return { passed, reason };
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
export function summarizeResponseForReport(response) {
|
|
650
|
-
const outcome = getResponseOutcome(response);
|
|
651
|
-
return {
|
|
652
|
-
responseSuccess: typeof outcome.structuredSuccess === 'boolean' ? outcome.structuredSuccess : undefined,
|
|
653
|
-
responseIsError: response?.isError === true || outcome.structuredContent.isError === true || outcome.nestedFailure !== null,
|
|
654
|
-
responseError: outcome.actualError ?? undefined,
|
|
655
|
-
responseMessage: outcome.actualMessage ?? undefined
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
function createToolCaller(client, { useProgressTimeouts = false } = {}) {
|
|
660
|
-
return async function callToolOnce(callOptions, baseTimeoutMs) {
|
|
661
|
-
const envDefault = Number(process.env.UNREAL_MCP_TEST_CALL_TIMEOUT_MS ?? '60000') || 60000;
|
|
662
|
-
const perCall = Number(callOptions?.arguments?.timeoutMs) || undefined;
|
|
663
|
-
const base = typeof baseTimeoutMs === 'number' && baseTimeoutMs > 0 ? baseTimeoutMs : (perCall || envDefault);
|
|
664
|
-
const serverTimeoutMs = base;
|
|
665
|
-
const clientTimeoutMs = useProgressTimeouts
|
|
666
|
-
? Number(process.env.UNREAL_MCP_TEST_CLIENT_TIMEOUT_MS ?? '300000') || 300000
|
|
667
|
-
: serverTimeoutMs;
|
|
668
|
-
const timeoutLabel = useProgressTimeouts
|
|
669
|
-
? `server timeout: ${serverTimeoutMs}ms, client timeout: ${clientTimeoutMs}ms`
|
|
670
|
-
: `timeout ${clientTimeoutMs}ms`;
|
|
671
|
-
|
|
672
|
-
try {
|
|
673
|
-
console.log(`[CALL] ${callOptions.name} (${timeoutLabel})`);
|
|
674
|
-
const outgoing = Object.assign({}, callOptions, { arguments: { ...(callOptions.arguments || {}), timeoutMs: serverTimeoutMs } });
|
|
675
|
-
let callPromise;
|
|
676
|
-
try {
|
|
677
|
-
callPromise = client.callTool(outgoing, undefined, { timeout: clientTimeoutMs });
|
|
678
|
-
} catch (err) {
|
|
679
|
-
try {
|
|
680
|
-
callPromise = client.callTool(outgoing, { timeout: clientTimeoutMs });
|
|
681
|
-
} catch (inner) {
|
|
682
|
-
try {
|
|
683
|
-
callPromise = client.callTool(outgoing);
|
|
684
|
-
} catch (inner2) {
|
|
685
|
-
throw inner2 || inner || err;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
let timeoutId;
|
|
691
|
-
const timeoutPromise = new Promise((_, rej) => {
|
|
692
|
-
timeoutId = setTimeout(() => rej(new Error(`Local test runner timeout after ${clientTimeoutMs}ms`)), clientTimeoutMs);
|
|
693
|
-
if (timeoutId && typeof timeoutId.unref === 'function') {
|
|
694
|
-
timeoutId.unref();
|
|
695
|
-
}
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
try {
|
|
699
|
-
return await Promise.race([callPromise, timeoutPromise]);
|
|
700
|
-
} finally {
|
|
701
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
702
|
-
}
|
|
703
|
-
} catch (e) {
|
|
704
|
-
const msg = String(e?.message || e || '');
|
|
705
|
-
if (msg.includes('Unknown blueprint action')) {
|
|
706
|
-
return { structuredContent: { success: false, error: msg } };
|
|
707
|
-
}
|
|
708
|
-
throw e;
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
function automationBridgeTarget() {
|
|
714
|
-
const host = process.env.MCP_AUTOMATION_WS_HOST ?? '127.0.0.1';
|
|
715
|
-
const ports = process.env.MCP_AUTOMATION_WS_PORTS
|
|
716
|
-
? process.env.MCP_AUTOMATION_WS_PORTS.split(',').map((port) => parseInt(port.trim(), 10)).filter(Boolean)
|
|
717
|
-
: [8090, 8091];
|
|
718
|
-
return { host, ports };
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
async function waitForAnyPort(host, ports, timeoutMs = 10000) {
|
|
722
|
-
const start = Date.now();
|
|
723
|
-
while (Date.now() - start < timeoutMs) {
|
|
724
|
-
for (const port of ports) {
|
|
725
|
-
try {
|
|
726
|
-
await new Promise((resolve, reject) => {
|
|
727
|
-
const sock = new net.Socket();
|
|
728
|
-
let settled = false;
|
|
729
|
-
sock.setTimeout(1000);
|
|
730
|
-
sock.once('connect', () => { settled = true; sock.destroy(); resolve(true); });
|
|
731
|
-
sock.once('timeout', () => { if (!settled) { settled = true; sock.destroy(); reject(new Error('timeout')); } });
|
|
732
|
-
sock.once('error', () => { if (!settled) { settled = true; sock.destroy(); reject(new Error('error')); } });
|
|
733
|
-
sock.connect(port, host);
|
|
734
|
-
});
|
|
735
|
-
console.log(`✅ Automation bridge appears to be listening on ${host}:${port}`);
|
|
736
|
-
return port;
|
|
737
|
-
} catch {
|
|
738
|
-
// Ignore and try the next port until the overall timeout expires.
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
await new Promise((resolve) => setImmediate(resolve));
|
|
742
|
-
}
|
|
743
|
-
throw new Error(`Timed out waiting for automation bridge on ports: ${ports.join(',')}`);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
async function getLatestMtime(dir) {
|
|
747
|
-
let latest = 0;
|
|
748
|
-
try {
|
|
749
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
750
|
-
for (const entry of entries) {
|
|
751
|
-
const fullPath = path.join(dir, entry.name);
|
|
752
|
-
if (entry.isDirectory()) {
|
|
753
|
-
const child = await getLatestMtime(fullPath);
|
|
754
|
-
if (child > latest) latest = child;
|
|
755
|
-
} else {
|
|
756
|
-
try {
|
|
757
|
-
const stat = await fs.stat(fullPath);
|
|
758
|
-
const mtime = stat.mtimeMs || 0;
|
|
759
|
-
if (mtime > latest) latest = mtime;
|
|
760
|
-
} catch {
|
|
761
|
-
// Ignore files that disappear while scanning mtimes.
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
} catch {
|
|
766
|
-
// Ignore missing directories when deciding whether dist is stale.
|
|
767
|
-
}
|
|
768
|
-
return latest;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
async function runNpmBuild() {
|
|
772
|
-
const { spawn } = await import('node:child_process');
|
|
773
|
-
await new Promise((resolve, reject) => {
|
|
774
|
-
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
775
|
-
const child = process.platform === 'win32'
|
|
776
|
-
? spawn(`${npmCmd} run build`, { cwd: repoRoot, stdio: 'inherit', shell: true })
|
|
777
|
-
: spawn(npmCmd, ['run', 'build'], { cwd: repoRoot, stdio: 'inherit' });
|
|
778
|
-
child.on('close', (code) => (code === 0 ? resolve() : reject(new Error(`Build failed with code ${code}`))));
|
|
779
|
-
child.on('error', (err) => reject(err));
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
async function resolveServerLaunch() {
|
|
784
|
-
const distPath = path.join(repoRoot, 'dist', 'cli.js');
|
|
785
|
-
const srcDir = path.join(repoRoot, 'src');
|
|
786
|
-
let useDist = false;
|
|
787
|
-
let distExists = false;
|
|
788
|
-
|
|
789
|
-
try {
|
|
790
|
-
await fs.access(distPath);
|
|
791
|
-
distExists = true;
|
|
792
|
-
} catch {
|
|
793
|
-
distExists = false;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
if (process.env.UNREAL_MCP_FORCE_DIST === '1') {
|
|
797
|
-
useDist = true;
|
|
798
|
-
console.log('Forcing use of dist build via UNREAL_MCP_FORCE_DIST=1');
|
|
799
|
-
} else if (distExists) {
|
|
800
|
-
try {
|
|
801
|
-
const distStat = await fs.stat(distPath);
|
|
802
|
-
const srcLatest = await getLatestMtime(srcDir);
|
|
803
|
-
const srcIsNewer = srcLatest > (distStat.mtimeMs || 0);
|
|
804
|
-
const autoBuildEnabled = process.env.UNREAL_MCP_AUTO_BUILD === '1';
|
|
805
|
-
const autoBuildDisabled = process.env.UNREAL_MCP_NO_AUTO_BUILD === '1';
|
|
806
|
-
if (srcIsNewer) {
|
|
807
|
-
if (!autoBuildEnabled && !autoBuildDisabled) {
|
|
808
|
-
console.log('Detected newer source files than dist; attempting automatic build to refresh dist/ (set UNREAL_MCP_NO_AUTO_BUILD=1 to disable)');
|
|
809
|
-
}
|
|
810
|
-
if (autoBuildEnabled || !autoBuildDisabled) {
|
|
811
|
-
try {
|
|
812
|
-
await runNpmBuild();
|
|
813
|
-
console.log('Build succeeded — using dist/ for live tests');
|
|
814
|
-
useDist = true;
|
|
815
|
-
} catch (buildErr) {
|
|
816
|
-
console.warn('Automatic build failed or could not stat files — falling back to TypeScript source for live tests:', String(buildErr));
|
|
817
|
-
useDist = false;
|
|
818
|
-
}
|
|
819
|
-
} else {
|
|
820
|
-
console.log('Detected newer source files than dist but automatic build is disabled.');
|
|
821
|
-
console.log('Set UNREAL_MCP_AUTO_BUILD=1 to enable automatic builds, or run `npm run build` manually.');
|
|
822
|
-
useDist = false;
|
|
823
|
-
}
|
|
824
|
-
} else {
|
|
825
|
-
useDist = true;
|
|
826
|
-
console.log('Using built dist for live tests');
|
|
827
|
-
}
|
|
828
|
-
} catch (buildErr) {
|
|
829
|
-
console.warn('Automatic build failed or could not stat files — falling back to TypeScript source for live tests:', String(buildErr));
|
|
830
|
-
useDist = false;
|
|
831
|
-
console.log('Preferring TypeScript source for tests to pick up local changes (set UNREAL_MCP_FORCE_DIST=1 to force dist)');
|
|
832
|
-
}
|
|
833
|
-
} else {
|
|
834
|
-
console.log('dist not found — attempting to run `npm run build` to produce dist/ for live tests');
|
|
835
|
-
try {
|
|
836
|
-
await runNpmBuild();
|
|
837
|
-
useDist = true;
|
|
838
|
-
console.log('Build succeeded — using dist/ for live tests');
|
|
839
|
-
} catch (buildErr) {
|
|
840
|
-
console.warn('Automatic build failed — falling back to running TypeScript source with ts-node-esm:', String(buildErr));
|
|
841
|
-
useDist = false;
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
if (!useDist) {
|
|
846
|
-
return {
|
|
847
|
-
command: process.env.UNREAL_MCP_SERVER_CMD ?? 'npx',
|
|
848
|
-
args: ['ts-node-esm', path.join(repoRoot, 'src', 'cli.ts')]
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
return {
|
|
853
|
-
command: process.env.UNREAL_MCP_SERVER_CMD ?? serverCommand,
|
|
854
|
-
args: process.env.UNREAL_MCP_SERVER_ARGS?.split(',') ?? serverArgs
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
async function createConnectedClient(clientName, waitMs) {
|
|
859
|
-
const { host, ports } = automationBridgeTarget();
|
|
860
|
-
console.log(`Waiting up to ${waitMs}ms for automation bridge on ${host}:${ports.join(',')}`);
|
|
861
|
-
try {
|
|
862
|
-
await waitForAnyPort(host, ports, waitMs);
|
|
863
|
-
} catch (err) {
|
|
864
|
-
throw new Error(`Automation bridge did not become available before tests started: ${err.message}`);
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
const launch = await resolveServerLaunch();
|
|
868
|
-
const transport = new StdioClientTransport({
|
|
869
|
-
command: launch.command,
|
|
870
|
-
args: launch.args,
|
|
871
|
-
cwd: serverCwd,
|
|
872
|
-
stderr: 'inherit',
|
|
873
|
-
env: serverEnv
|
|
874
|
-
});
|
|
875
|
-
const client = new Client({ name: clientName, version: '1.0.0' });
|
|
876
|
-
|
|
877
|
-
await client.connect(transport);
|
|
878
|
-
await client.listTools({});
|
|
879
|
-
console.log('✅ Connected to Unreal MCP Server\n');
|
|
880
|
-
|
|
881
|
-
return { transport, client };
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
const capturedPlaceholderPattern = /\$\{captured:([^}]+)\}/g;
|
|
885
|
-
/** @type {(captureKey: string) => void} */
|
|
886
|
-
const noopMissingCapture = () => {};
|
|
887
|
-
|
|
888
|
-
/**
|
|
889
|
-
* Resolves ${captured:key} placeholders in nested test arguments.
|
|
890
|
-
*
|
|
891
|
-
* @param {unknown} value
|
|
892
|
-
* @param {Record<string, string>} capturedValues
|
|
893
|
-
* @param {(captureKey: string) => void} onMissingCapture
|
|
894
|
-
* @returns {unknown}
|
|
895
|
-
*/
|
|
896
|
-
export function resolveCapturedValues(value, capturedValues, onMissingCapture = noopMissingCapture) {
|
|
897
|
-
if (typeof value === 'string') {
|
|
898
|
-
return value.replace(capturedPlaceholderPattern, (match, captureKey) => {
|
|
899
|
-
const captured = capturedValues[captureKey];
|
|
900
|
-
if (captured === undefined) {
|
|
901
|
-
onMissingCapture(captureKey);
|
|
902
|
-
return match;
|
|
903
|
-
}
|
|
904
|
-
return captured;
|
|
905
|
-
});
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
if (Array.isArray(value)) {
|
|
909
|
-
return value.map((entry) => resolveCapturedValues(entry, capturedValues, onMissingCapture));
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
if (value && typeof value === 'object') {
|
|
913
|
-
return Object.fromEntries(
|
|
914
|
-
Object.entries(value).map(([key, entry]) => [key, resolveCapturedValues(entry, capturedValues, onMissingCapture)])
|
|
915
|
-
);
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
return value;
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
/**
|
|
922
|
-
* Main test runner function
|
|
923
|
-
*/
|
|
924
|
-
export async function runToolTests(toolName, testCases) {
|
|
925
|
-
console.log(`Total test cases: ${testCases.length}`);
|
|
926
|
-
console.log('='.repeat(60));
|
|
927
|
-
console.log('');
|
|
928
|
-
|
|
929
|
-
// === CAPTURED VALUES SUPPORT ===
|
|
930
|
-
// Stores values captured from previous test responses for use in subsequent tests
|
|
931
|
-
// Test cases can capture a direct field or filter an array with where/selectField,
|
|
932
|
-
// then use ${captured:key} in later arguments.
|
|
933
|
-
const capturedValues = {};
|
|
934
|
-
|
|
935
|
-
/**
|
|
936
|
-
* Captures values from a response based on captureResult configuration
|
|
937
|
-
*/
|
|
938
|
-
function captureResultValues(testCase, response) {
|
|
939
|
-
if (!testCase.captureResult || !response?.structuredContent) return;
|
|
940
|
-
|
|
941
|
-
const { key, fromField } = testCase.captureResult;
|
|
942
|
-
if (!key || !fromField) return;
|
|
943
|
-
|
|
944
|
-
const value = selectCaptureValue(response.structuredContent, testCase.captureResult);
|
|
945
|
-
if (value !== undefined) {
|
|
946
|
-
capturedValues[key] = value;
|
|
947
|
-
console.log(`📦 Captured: ${key} = ${value}`);
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
let transport;
|
|
953
|
-
let client;
|
|
954
|
-
const results = [];
|
|
955
|
-
// callToolOnce is assigned after the MCP client is initialized. Declare here so
|
|
956
|
-
// the test loop can call it regardless of block scoping rules.
|
|
957
|
-
let callToolOnce;
|
|
958
|
-
|
|
959
|
-
try {
|
|
960
|
-
({ transport, client } = await createConnectedClient('unreal-mcp-test-runner', 10000));
|
|
961
|
-
|
|
962
|
-
// Forward timeoutMs to the server while allowing the MCP client timeout to
|
|
963
|
-
// stay longer so server-side progress can extend long-running automation.
|
|
964
|
-
callToolOnce = createToolCaller(client, { useProgressTimeouts: true });
|
|
965
|
-
|
|
966
|
-
// Retry helper with exponential backoff for setup operations
|
|
967
|
-
// Helps handle transient failures like Intel GPU driver crashes
|
|
968
|
-
async function callWithRetry(callOptions, options = {}) {
|
|
969
|
-
const {
|
|
970
|
-
maxRetries = 3,
|
|
971
|
-
baseDelayMs = 1000,
|
|
972
|
-
maxDelayMs = 10000,
|
|
973
|
-
timeoutMs = 15000,
|
|
974
|
-
operationName = callOptions.name
|
|
975
|
-
} = options;
|
|
976
|
-
|
|
977
|
-
let lastError = null;
|
|
978
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
979
|
-
try {
|
|
980
|
-
const result = await callToolOnce(callOptions, timeoutMs);
|
|
981
|
-
// Check for success in structured response
|
|
982
|
-
if (result?.structuredContent?.success === false) {
|
|
983
|
-
throw new Error(result.structuredContent.error || result.structuredContent.message || 'Operation failed');
|
|
984
|
-
}
|
|
985
|
-
if (attempt > 1) {
|
|
986
|
-
console.log(` ✅ ${operationName} succeeded on attempt ${attempt}/${maxRetries}`);
|
|
987
|
-
}
|
|
988
|
-
return result;
|
|
989
|
-
} catch (err) {
|
|
990
|
-
lastError = err;
|
|
991
|
-
const errorMsg = String(err?.message || err);
|
|
992
|
-
const isDriverCrash = errorMsg.toLowerCase().includes('disconnect') ||
|
|
993
|
-
errorMsg.toLowerCase().includes('1006') ||
|
|
994
|
-
errorMsg.toLowerCase().includes('crash') ||
|
|
995
|
-
errorMsg.toLowerCase().includes('exception');
|
|
996
|
-
|
|
997
|
-
if (attempt < maxRetries) {
|
|
998
|
-
const delay = Math.min(baseDelayMs * Math.pow(2, attempt - 1), maxDelayMs);
|
|
999
|
-
const reason = isDriverCrash ? 'driver instability detected' : 'transient failure';
|
|
1000
|
-
console.warn(` ⚠️ ${operationName} failed (attempt ${attempt}/${maxRetries}, ${reason}), retrying in ${delay}ms...`);
|
|
1001
|
-
await new Promise(r => setTimeout(r, delay));
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
throw lastError;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
// === CLEANUP: Delete existing test assets from previous runs ===
|
|
1009
|
-
console.log('🧹 Cleaning up existing test assets...');
|
|
1010
|
-
try {
|
|
1011
|
-
// Delete test levels
|
|
1012
|
-
await callToolOnce({ name: 'manage_level', arguments: { action: 'unload', levelName: 'MainLevel' } }, 10000).catch(() => {});
|
|
1013
|
-
await callToolOnce({ name: 'manage_level', arguments: { action: 'unload', levelName: 'TestLevel' } }, 10000).catch(() => {});
|
|
1014
|
-
|
|
1015
|
-
// Delete geometry actors
|
|
1016
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'TestBox' } }, 5000).catch(() => {});
|
|
1017
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'TestSphere' } }, 5000).catch(() => {});
|
|
1018
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'TestCylinder' } }, 5000).catch(() => {});
|
|
1019
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'TestActor' } }, 5000).catch(() => {});
|
|
1020
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'ParentActor' } }, 5000).catch(() => {});
|
|
1021
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'ChildActor' } }, 5000).catch(() => {});
|
|
1022
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'NavTestActor' } }, 5000).catch(() => {});
|
|
1023
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'TestSpline' } }, 5000).catch(() => {});
|
|
1024
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'TestRoad' } }, 5000).catch(() => {});
|
|
1025
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'SplineControlPoints' } }, 5000).catch(() => {});
|
|
1026
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'NavLinkProxy_Test' } }, 5000).catch(() => {});
|
|
1027
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'SmartNavLink_Test' } }, 5000).catch(() => {});
|
|
1028
|
-
|
|
1029
|
-
// Delete test assets (blueprints, materials)
|
|
1030
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/BP_Test' } }, 10000).catch(() => {});
|
|
1031
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/SplineBP' } }, 10000).catch(() => {});
|
|
1032
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/TestMaterial' } }, 10000).catch(() => {});
|
|
1033
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/Parent' } }, 10000).catch(() => {});
|
|
1034
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/M_Test' } }, 10000).catch(() => {});
|
|
1035
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/ConvertedMesh' } }, 10000).catch(() => {});
|
|
1036
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/TestLandscape' } }, 10000).catch(() => {});
|
|
1037
|
-
// Delete asset test artifacts
|
|
1038
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/TestAsset' } }, 10000).catch(() => {});
|
|
1039
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/TestMesh' } }, 10000).catch(() => {});
|
|
1040
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/MCPTest/TestMat' } }, 10000).catch(() => {});
|
|
1041
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete', path: '/Game/MCPTest/TestInstance', force: true } }, 10000).catch(() => {});
|
|
1042
|
-
|
|
1043
|
-
// Delete foliage types
|
|
1044
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/Foliage/Grass' } }, 10000).catch(() => {});
|
|
1045
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/Foliage/Tree' } }, 10000).catch(() => {});
|
|
1046
|
-
await callToolOnce({ name: 'manage_asset', arguments: { action: 'delete_asset', path: '/Game/Foliage/Bush' } }, 10000).catch(() => {});
|
|
1047
|
-
|
|
1048
|
-
// Delete NavMeshBoundsVolume
|
|
1049
|
-
await callToolOnce({ name: 'control_actor', arguments: { action: 'delete', actorName: 'NavMeshBoundsVolume' } }, 5000).catch(() => {});
|
|
1050
|
-
|
|
1051
|
-
console.log('✅ Cleanup complete\n');
|
|
1052
|
-
} catch (cleanupErr) {
|
|
1053
|
-
console.warn('⚠️ Cleanup had issues:', cleanupErr?.message || cleanupErr);
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
// Setup test assets before running tests
|
|
1057
|
-
console.log('🔧 Setting up test assets...');
|
|
1058
|
-
try {
|
|
1059
|
-
// Create test folder
|
|
1060
|
-
await callToolOnce({
|
|
1061
|
-
name: 'manage_asset',
|
|
1062
|
-
arguments: { action: 'create_folder', path: '/Game/MCPTest' }
|
|
1063
|
-
}, 10000).catch(() => { /* Folder may already exist */ });
|
|
1064
|
-
|
|
1065
|
-
// Spawn TestActor with a mesh for physics tests (apply_force requires a mesh)
|
|
1066
|
-
// Use /Engine/EngineMeshes/Cube (exists in UE 5.3-5.7) instead of /Engine/BasicShapes/Cube (doesn't exist)
|
|
1067
|
-
// Use retry logic for critical actors that many tests depend on
|
|
1068
|
-
await callWithRetry({
|
|
1069
|
-
name: 'control_actor',
|
|
1070
|
-
arguments: {
|
|
1071
|
-
action: 'spawn',
|
|
1072
|
-
classPath: '/Script/Engine.StaticMeshActor',
|
|
1073
|
-
actorName: 'TestActor',
|
|
1074
|
-
meshPath: '/Engine/EngineMeshes/Cube',
|
|
1075
|
-
location: { x: 0, y: 0, z: 0 },
|
|
1076
|
-
rotation: { pitch: 0, yaw: 0, roll: 0 },
|
|
1077
|
-
scale: { x: 1, y: 1, z: 1 }
|
|
1078
|
-
}
|
|
1079
|
-
}, { maxRetries: 3, timeoutMs: 20000, operationName: 'spawn TestActor' }).catch(err => console.warn('⚠️ TestActor may already exist:', err?.message || err));
|
|
1080
|
-
|
|
1081
|
-
// Enable physics on TestActor for apply_force tests
|
|
1082
|
-
// Set collision to QueryAndPhysics and enable SimulatePhysics on the StaticMeshComponent
|
|
1083
|
-
await callToolOnce({
|
|
1084
|
-
name: 'control_actor',
|
|
1085
|
-
arguments: {
|
|
1086
|
-
action: 'set_component_property',
|
|
1087
|
-
actorName: 'TestActor',
|
|
1088
|
-
componentName: 'StaticMeshComponent0',
|
|
1089
|
-
properties: {
|
|
1090
|
-
'CollisionEnabled': 'QueryAndPhysics',
|
|
1091
|
-
'SimulatePhysics': true,
|
|
1092
|
-
'bSimulatePhysics': true
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
}, 10000).catch(err => console.warn('⚠️ Physics setup for TestActor failed:', err?.message || err));
|
|
1096
|
-
|
|
1097
|
-
// Spawn ParentActor for attach/detach tests
|
|
1098
|
-
await callToolOnce({
|
|
1099
|
-
name: 'control_actor',
|
|
1100
|
-
arguments: {
|
|
1101
|
-
action: 'spawn',
|
|
1102
|
-
classPath: '/Script/Engine.StaticMeshActor',
|
|
1103
|
-
actorName: 'ParentActor',
|
|
1104
|
-
meshPath: '/Engine/EngineMeshes/Cube',
|
|
1105
|
-
location: { x: 200, y: 0, z: 0 }
|
|
1106
|
-
}
|
|
1107
|
-
}, 15000).catch(err => console.warn('⚠️ ParentActor may already exist:', err?.message || err));
|
|
1108
|
-
|
|
1109
|
-
// Spawn ChildActor for attach/detach tests
|
|
1110
|
-
await callToolOnce({
|
|
1111
|
-
name: 'control_actor',
|
|
1112
|
-
arguments: {
|
|
1113
|
-
action: 'spawn',
|
|
1114
|
-
classPath: '/Script/Engine.StaticMeshActor',
|
|
1115
|
-
actorName: 'ChildActor',
|
|
1116
|
-
meshPath: '/Engine/EngineMeshes/Cube',
|
|
1117
|
-
location: { x: 300, y: 0, z: 0 }
|
|
1118
|
-
}
|
|
1119
|
-
}, 15000).catch(err => console.warn('⚠️ ChildActor may already exist:', err?.message || err));
|
|
1120
|
-
|
|
1121
|
-
// Create Test Blueprint (critical for many tests - use retry)
|
|
1122
|
-
await callWithRetry({
|
|
1123
|
-
name: 'manage_blueprint',
|
|
1124
|
-
arguments: {
|
|
1125
|
-
action: 'create',
|
|
1126
|
-
name: 'BP_Test',
|
|
1127
|
-
path: '/Game/MCPTest',
|
|
1128
|
-
parentClass: 'Actor'
|
|
1129
|
-
}
|
|
1130
|
-
}, { maxRetries: 3, timeoutMs: 20000, operationName: 'create BP_Test blueprint' }).catch(err => console.warn('⚠️ BP_Test may already exist:', err?.message || err));
|
|
1131
|
-
|
|
1132
|
-
// Create Test Material
|
|
1133
|
-
await callToolOnce({
|
|
1134
|
-
name: 'manage_asset',
|
|
1135
|
-
arguments: {
|
|
1136
|
-
action: 'create_material',
|
|
1137
|
-
name: 'TestMaterial',
|
|
1138
|
-
path: '/Game/MCPTest'
|
|
1139
|
-
}
|
|
1140
|
-
}, 15000).catch(err => console.warn('⚠️ TestMaterial may already exist:', err?.message || err));
|
|
1141
|
-
|
|
1142
|
-
// Create Parent Material for create_material_instance tests
|
|
1143
|
-
await callToolOnce({
|
|
1144
|
-
name: 'manage_asset',
|
|
1145
|
-
arguments: {
|
|
1146
|
-
action: 'create_material',
|
|
1147
|
-
name: 'Parent',
|
|
1148
|
-
path: '/Game/MCPTest'
|
|
1149
|
-
}
|
|
1150
|
-
}, 15000).catch(err => console.warn('⚠️ Parent material may already exist:', err?.message || err));
|
|
1151
|
-
|
|
1152
|
-
// Create M_Test Material for material authoring tests
|
|
1153
|
-
await callToolOnce({
|
|
1154
|
-
name: 'manage_asset',
|
|
1155
|
-
arguments: {
|
|
1156
|
-
action: 'create_material',
|
|
1157
|
-
name: 'M_Test',
|
|
1158
|
-
path: '/Game/MCPTest'
|
|
1159
|
-
}
|
|
1160
|
-
}, 15000).catch(err => console.warn('⚠️ M_Test material may already exist:', err?.message || err));
|
|
1161
|
-
|
|
1162
|
-
// === Asset Test Setup for manage_asset tests ===
|
|
1163
|
-
// Create TestMat material for material graph/stats tests
|
|
1164
|
-
await callToolOnce({
|
|
1165
|
-
name: 'manage_asset',
|
|
1166
|
-
arguments: {
|
|
1167
|
-
action: 'create_material',
|
|
1168
|
-
name: 'TestMat',
|
|
1169
|
-
path: '/Game/MCPTest'
|
|
1170
|
-
}
|
|
1171
|
-
}, 15000).catch(err => console.warn('⚠️ TestMat material may already exist:', err?.message || err));
|
|
1172
|
-
|
|
1173
|
-
// Create TestInstance material instance for reset_instance_parameters tests
|
|
1174
|
-
await callToolOnce({
|
|
1175
|
-
name: 'manage_asset',
|
|
1176
|
-
arguments: {
|
|
1177
|
-
action: 'create_material_instance',
|
|
1178
|
-
name: 'TestInstance',
|
|
1179
|
-
parentMaterial: '/Game/MCPTest/Parent',
|
|
1180
|
-
path: '/Game/MCPTest'
|
|
1181
|
-
}
|
|
1182
|
-
}, 15000).catch(err => console.warn('⚠️ TestInstance material instance may already exist:', err?.message || err));
|
|
1183
|
-
|
|
1184
|
-
// Create TestAsset by duplicating an engine cube mesh
|
|
1185
|
-
// This is needed for duplicate/rename/move/get_dependencies/validate etc. tests
|
|
1186
|
-
// Use /Engine/EngineMeshes/Cube (exists in UE 5.3-5.7) instead of /Engine/BasicShapes/Cube (doesn't exist)
|
|
1187
|
-
await callToolOnce({
|
|
1188
|
-
name: 'manage_asset',
|
|
1189
|
-
arguments: {
|
|
1190
|
-
action: 'duplicate',
|
|
1191
|
-
sourcePath: '/Engine/EngineMeshes/Cube',
|
|
1192
|
-
destinationPath: '/Game/MCPTest/TestAsset'
|
|
1193
|
-
}
|
|
1194
|
-
}, 15000).catch(err => console.warn('⚠️ TestAsset may already exist:', err?.message || err));
|
|
1195
|
-
|
|
1196
|
-
// Create TestMesh for generate_lods and nanite_rebuild_mesh tests
|
|
1197
|
-
await callToolOnce({
|
|
1198
|
-
name: 'manage_asset',
|
|
1199
|
-
arguments: {
|
|
1200
|
-
action: 'duplicate',
|
|
1201
|
-
sourcePath: '/Engine/EngineMeshes/Cube',
|
|
1202
|
-
destinationPath: '/Game/MCPTest/TestMesh'
|
|
1203
|
-
}
|
|
1204
|
-
}, 15000).catch(err => console.warn('⚠️ TestMesh may already exist:', err?.message || err));
|
|
1205
|
-
// === End Asset Test Setup ===
|
|
1206
|
-
|
|
1207
|
-
// === Foliage Setup for build_environment tests ===
|
|
1208
|
-
// Create Foliage folder
|
|
1209
|
-
await callToolOnce({
|
|
1210
|
-
name: 'manage_asset',
|
|
1211
|
-
arguments: { action: 'create_folder', path: '/Game/Foliage' }
|
|
1212
|
-
}, 10000).catch(() => { /* Folder may already exist */ });
|
|
1213
|
-
|
|
1214
|
-
// Create Grass foliage type using add_foliage_type action
|
|
1215
|
-
await callToolOnce({
|
|
1216
|
-
name: 'build_environment',
|
|
1217
|
-
arguments: {
|
|
1218
|
-
action: 'add_foliage_type',
|
|
1219
|
-
name: 'Grass',
|
|
1220
|
-
meshPath: '/Engine/BasicShapes/Sphere',
|
|
1221
|
-
density: 100
|
|
1222
|
-
}
|
|
1223
|
-
}, 15000).catch(err => console.warn('⚠️ Grass foliage type may already exist:', err?.message || err));
|
|
1224
|
-
|
|
1225
|
-
// Create Tree foliage type
|
|
1226
|
-
await callToolOnce({
|
|
1227
|
-
name: 'build_environment',
|
|
1228
|
-
arguments: {
|
|
1229
|
-
action: 'add_foliage_type',
|
|
1230
|
-
name: 'Tree',
|
|
1231
|
-
meshPath: '/Engine/BasicShapes/Sphere',
|
|
1232
|
-
density: 50
|
|
1233
|
-
}
|
|
1234
|
-
}, 15000).catch(err => console.warn('⚠️ Tree foliage type may already exist:', err?.message || err));
|
|
1235
|
-
|
|
1236
|
-
// Create Bush foliage type for procedural foliage tests
|
|
1237
|
-
await callToolOnce({
|
|
1238
|
-
name: 'build_environment',
|
|
1239
|
-
arguments: {
|
|
1240
|
-
action: 'add_foliage_type',
|
|
1241
|
-
name: 'Bush',
|
|
1242
|
-
meshPath: '/Engine/BasicShapes/Sphere',
|
|
1243
|
-
density: 75
|
|
1244
|
-
}
|
|
1245
|
-
}, 15000).catch(err => console.warn('⚠️ Bush foliage type may already exist:', err?.message || err));
|
|
1246
|
-
// === End Foliage Setup ===
|
|
1247
|
-
|
|
1248
|
-
// === Geometry Setup for manage_geometry tests ===
|
|
1249
|
-
// Create TestBox for geometry manipulation tests
|
|
1250
|
-
await callToolOnce({
|
|
1251
|
-
name: 'manage_geometry',
|
|
1252
|
-
arguments: { action: 'create_box', name: 'TestBox', width: 100, height: 100, depth: 100 }
|
|
1253
|
-
}, 15000).catch(err => console.warn('⚠️ TestBox may already exist:', err?.message || err));
|
|
1254
|
-
|
|
1255
|
-
// Create TestSphere for boolean operation tests
|
|
1256
|
-
await callToolOnce({
|
|
1257
|
-
name: 'manage_geometry',
|
|
1258
|
-
arguments: { action: 'create_sphere', name: 'TestSphere', radius: 50, segments: 16 }
|
|
1259
|
-
}, 15000).catch(err => console.warn('⚠️ TestSphere may already exist:', err?.message || err));
|
|
1260
|
-
|
|
1261
|
-
// Create TestCylinder for additional geometry tests
|
|
1262
|
-
await callToolOnce({
|
|
1263
|
-
name: 'manage_geometry',
|
|
1264
|
-
arguments: { action: 'create_cylinder', name: 'TestCylinder', radius: 50, height: 100, segments: 16 }
|
|
1265
|
-
}, 15000).catch(err => console.warn('⚠️ TestCylinder may already exist:', err?.message || err));
|
|
1266
|
-
// === End Geometry Setup ===
|
|
1267
|
-
|
|
1268
|
-
// === Navigation Setup for manage_ai navigation tests ===
|
|
1269
|
-
// Create NavMeshBoundsVolume so RecastNavMesh can be generated
|
|
1270
|
-
await callToolOnce({
|
|
1271
|
-
name: 'manage_level_structure',
|
|
1272
|
-
arguments: {
|
|
1273
|
-
action: 'create_nav_mesh_bounds_volume',
|
|
1274
|
-
volumeName: 'TestNavMeshBounds',
|
|
1275
|
-
location: { x: 0, y: 0, z: 0 },
|
|
1276
|
-
extent: { x: 2000, y: 2000, z: 500 }
|
|
1277
|
-
}
|
|
1278
|
-
}, 15000).catch(err => console.warn('⚠️ TestNavMeshBounds may already exist:', err?.message || err));
|
|
1279
|
-
|
|
1280
|
-
// Trigger navigation rebuild to generate RecastNavMesh
|
|
1281
|
-
await callToolOnce({
|
|
1282
|
-
name: 'manage_ai',
|
|
1283
|
-
arguments: { action: 'rebuild_navigation' }
|
|
1284
|
-
}, 30000).catch(err => console.warn('⚠️ Navigation rebuild may have failed:', err?.message || err));
|
|
1285
|
-
|
|
1286
|
-
// Create BP_Test blueprint for create_nav_modifier_component tests
|
|
1287
|
-
await callToolOnce({
|
|
1288
|
-
name: 'manage_blueprint',
|
|
1289
|
-
arguments: { action: 'create_blueprint', name: 'BP_Test', path: '/Game/MCPTest' }
|
|
1290
|
-
}, 15000).catch(err => console.warn('⚠️ BP_Test may already exist:', err?.message || err));
|
|
1291
|
-
|
|
1292
|
-
// Add NavModifier component to BP_Test blueprint
|
|
1293
|
-
await callToolOnce({
|
|
1294
|
-
name: 'manage_ai',
|
|
1295
|
-
arguments: {
|
|
1296
|
-
action: 'create_nav_modifier_component',
|
|
1297
|
-
blueprintPath: '/Game/MCPTest/BP_Test',
|
|
1298
|
-
componentName: 'NavModifier',
|
|
1299
|
-
areaClass: '/Script/NavigationSystem.NavArea_Obstacle'
|
|
1300
|
-
}
|
|
1301
|
-
}, 15000).catch(err => console.warn('⚠️ NavModifier component may already exist:', err?.message || err));
|
|
1302
|
-
|
|
1303
|
-
// Spawn actor from BP_Test for set_nav_area_class tests
|
|
1304
|
-
// Use control_actor spawn_blueprint to spawn actor from blueprint
|
|
1305
|
-
await callToolOnce({
|
|
1306
|
-
name: 'control_actor',
|
|
1307
|
-
arguments: { action: 'spawn_blueprint', blueprintPath: '/Game/MCPTest/BP_Test', actorName: 'NavTestActor', location: [0, 0, 100] }
|
|
1308
|
-
}, 15000).catch(err => console.warn('⚠️ NavTestActor may already exist:', err?.message || err));
|
|
1309
|
-
// === End Navigation Setup ===
|
|
1310
|
-
|
|
1311
|
-
// === Spline Setup for build_environment spline tests ===
|
|
1312
|
-
// Create TestSpline for spline manipulation tests
|
|
1313
|
-
await callToolOnce({
|
|
1314
|
-
name: 'build_environment',
|
|
1315
|
-
arguments: { action: 'create_spline_actor', actorName: 'TestSpline', location: {x:0,y:0,z:0} }
|
|
1316
|
-
}, 15000).catch(err => console.warn('⚠️ TestSpline may already exist:', err?.message || err));
|
|
1317
|
-
|
|
1318
|
-
// Create template spline actors for specialized spline tests
|
|
1319
|
-
await callToolOnce({
|
|
1320
|
-
name: 'build_environment',
|
|
1321
|
-
arguments: { action: 'create_road_spline', actorName: 'TestRoad', location: {x:500,y:0,z:0} }
|
|
1322
|
-
}, 15000).catch(err => console.warn('⚠️ TestRoad may already exist:', err?.message || err));
|
|
1323
|
-
|
|
1324
|
-
await callToolOnce({
|
|
1325
|
-
name: 'build_environment',
|
|
1326
|
-
arguments: { action: 'create_river_spline', actorName: 'TestRiver', location: {x:1000,y:0,z:0} }
|
|
1327
|
-
}, 15000).catch(err => console.warn('⚠️ TestRiver may already exist:', err?.message || err));
|
|
1328
|
-
|
|
1329
|
-
await callToolOnce({
|
|
1330
|
-
name: 'build_environment',
|
|
1331
|
-
arguments: { action: 'create_fence_spline', actorName: 'TestFence', location: {x:1500,y:0,z:0} }
|
|
1332
|
-
}, 15000).catch(err => console.warn('⚠️ TestFence may already exist:', err?.message || err));
|
|
1333
|
-
|
|
1334
|
-
await callToolOnce({
|
|
1335
|
-
name: 'build_environment',
|
|
1336
|
-
arguments: { action: 'create_wall_spline', actorName: 'TestWall', location: {x:2000,y:0,z:0} }
|
|
1337
|
-
}, 15000).catch(err => console.warn('⚠️ TestWall may already exist:', err?.message || err));
|
|
1338
|
-
|
|
1339
|
-
await callToolOnce({
|
|
1340
|
-
name: 'build_environment',
|
|
1341
|
-
arguments: { action: 'create_cable_spline', actorName: 'TestCable', location: {x:2500,y:0,z:100} }
|
|
1342
|
-
}, 15000).catch(err => console.warn('⚠️ TestCable may already exist:', err?.message || err));
|
|
1343
|
-
|
|
1344
|
-
await callToolOnce({
|
|
1345
|
-
name: 'build_environment',
|
|
1346
|
-
arguments: { action: 'create_pipe_spline', actorName: 'TestPipe', location: {x:3000,y:0,z:0} }
|
|
1347
|
-
}, 15000).catch(err => console.warn('⚠️ TestPipe may already exist:', err?.message || err));
|
|
1348
|
-
|
|
1349
|
-
// Create SplineBP blueprint for create_spline_mesh_component tests
|
|
1350
|
-
// Note: create_blueprint creates directly under path, so /Game/ creates /Game/SplineBP
|
|
1351
|
-
await callToolOnce({
|
|
1352
|
-
name: 'manage_blueprint',
|
|
1353
|
-
arguments: { action: 'create_blueprint', name: 'SplineBP', path: '/Game' }
|
|
1354
|
-
}, 15000).catch(err => console.warn('⚠️ SplineBP may already exist:', err?.message || err));
|
|
1355
|
-
// === End Spline Setup ===
|
|
1356
|
-
|
|
1357
|
-
// === Level Structure Setup for manage_level_structure tests ===
|
|
1358
|
-
// Create TestLevel for level blueprint and level instance tests
|
|
1359
|
-
// Use retry logic for level creation due to Intel GPU driver instability
|
|
1360
|
-
await callWithRetry({
|
|
1361
|
-
name: 'manage_level_structure',
|
|
1362
|
-
arguments: {
|
|
1363
|
-
action: 'create_level',
|
|
1364
|
-
levelName: 'TestLevel',
|
|
1365
|
-
levelPath: '/Game/MCPTest',
|
|
1366
|
-
bCreateWorldPartition: false,
|
|
1367
|
-
save: true
|
|
1368
|
-
}
|
|
1369
|
-
}, { maxRetries: 5, timeoutMs: 20000, operationName: 'create TestLevel' }).catch(err => console.warn('⚠️ TestLevel creation failed after retries:', err?.message || err));
|
|
1370
|
-
|
|
1371
|
-
// Create MainLevel for streaming/sublevel tests
|
|
1372
|
-
await callWithRetry({
|
|
1373
|
-
name: 'manage_level_structure',
|
|
1374
|
-
arguments: {
|
|
1375
|
-
action: 'create_level',
|
|
1376
|
-
levelName: 'MainLevel',
|
|
1377
|
-
levelPath: '/Game/MCPTest',
|
|
1378
|
-
bCreateWorldPartition: false,
|
|
1379
|
-
save: true
|
|
1380
|
-
}
|
|
1381
|
-
}, { maxRetries: 5, timeoutMs: 20000, operationName: 'create MainLevel' }).catch(err => console.warn('⚠️ MainLevel creation failed after retries:', err?.message || err));
|
|
1382
|
-
|
|
1383
|
-
// Create DataLayers folder for data layer tests
|
|
1384
|
-
await callToolOnce({
|
|
1385
|
-
name: 'manage_asset',
|
|
1386
|
-
arguments: { action: 'create_folder', path: '/Game/MCPTest/DataLayers' }
|
|
1387
|
-
}, 10000).catch(() => { /* Folder may already exist */ });
|
|
1388
|
-
|
|
1389
|
-
// Note: TestLayer creation requires World Partition enabled on the level
|
|
1390
|
-
// and the DataLayerEditorSubsystem to be available. We create it per-test
|
|
1391
|
-
// with unique names in the test file itself.
|
|
1392
|
-
// === End Level Structure Setup ===
|
|
1393
|
-
|
|
1394
|
-
console.log('✅ Test assets setup complete\n');
|
|
1395
|
-
} catch (setupErr) {
|
|
1396
|
-
console.warn('⚠️ Test asset setup had issues (tests may fail if assets missing):', setupErr?.message || setupErr);
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
// Helper function to reset geometry for manage_geometry tests
|
|
1400
|
-
// This prevents polygon explosion from accumulating across tests
|
|
1401
|
-
let geometryResetCounter = 0;
|
|
1402
|
-
async function resetGeometryActors() {
|
|
1403
|
-
try {
|
|
1404
|
-
// Delete existing geometry actors
|
|
1405
|
-
await callToolOnce({
|
|
1406
|
-
name: 'control_actor',
|
|
1407
|
-
arguments: { action: 'delete', actorName: 'TestBox' }
|
|
1408
|
-
}, 5000).catch(() => { /* ignore if doesn't exist */ });
|
|
1409
|
-
|
|
1410
|
-
await callToolOnce({
|
|
1411
|
-
name: 'control_actor',
|
|
1412
|
-
arguments: { action: 'delete', actorName: 'TestSphere' }
|
|
1413
|
-
}, 5000).catch(() => { /* ignore if doesn't exist */ });
|
|
1414
|
-
|
|
1415
|
-
// Recreate fresh geometry
|
|
1416
|
-
await callToolOnce({
|
|
1417
|
-
name: 'manage_geometry',
|
|
1418
|
-
arguments: { action: 'create_box', name: 'TestBox', width: 100, height: 100, depth: 100 }
|
|
1419
|
-
}, 10000);
|
|
1420
|
-
|
|
1421
|
-
await callToolOnce({
|
|
1422
|
-
name: 'manage_geometry',
|
|
1423
|
-
arguments: { action: 'create_sphere', name: 'TestSphere', radius: 50, segments: 16 }
|
|
1424
|
-
}, 10000);
|
|
1425
|
-
} catch (err) {
|
|
1426
|
-
console.warn('⚠️ Geometry reset failed:', err?.message || err);
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
// Run each test case
|
|
1431
|
-
// Rate limit: 600 req/min = 10 req/sec, so add 100ms delay between tests
|
|
1432
|
-
const TEST_THROTTLE_MS = Number(process.env.UNREAL_MCP_TEST_THROTTLE_MS ?? 100);
|
|
1433
|
-
|
|
1434
|
-
for (let i = 0; i < testCases.length; i++) {
|
|
1435
|
-
const testCase = testCases[i];
|
|
1436
|
-
const testCaseTimeoutMs = getTestCaseTimeoutMs(testCase);
|
|
1437
|
-
const startTime = performance.now();
|
|
1438
|
-
|
|
1439
|
-
try {
|
|
1440
|
-
// Log test start to Unreal Engine console without echoing scenario text.
|
|
1441
|
-
// Scenario names can contain words like "delete" that are correctly
|
|
1442
|
-
// blocked by the console command safety validator.
|
|
1443
|
-
await callToolOnce({
|
|
1444
|
-
name: 'system_control',
|
|
1445
|
-
arguments: { action: 'console_command', command: `Log Starting MCP test ${i + 1} of ${testCases.length}` }
|
|
1446
|
-
}, 5000).catch(() => { });
|
|
1447
|
-
} catch (e) { /* ignore */ }
|
|
1448
|
-
|
|
1449
|
-
try {
|
|
1450
|
-
// Resolve captured values in arguments before executing
|
|
1451
|
-
const resolvedArgs = resolveCapturedValues(testCase.arguments, capturedValues, (captureKey) => {
|
|
1452
|
-
console.warn(`⚠️ Captured value '${captureKey}' not found, using placeholder`);
|
|
1453
|
-
});
|
|
1454
|
-
const response = await callToolOnce({ name: testCase.toolName, arguments: resolvedArgs }, testCaseTimeoutMs);
|
|
1455
|
-
|
|
1456
|
-
const endTime = performance.now();
|
|
1457
|
-
const durationMs = endTime - startTime;
|
|
1458
|
-
|
|
1459
|
-
const normalizedResponse = normalizeResponseForEvaluation(response);
|
|
1460
|
-
if (RESPONSE_LOGGING_ENABLED) {
|
|
1461
|
-
logMcpResponse(testCase.toolName + " :: " + testCase.scenario, normalizeMcpResponse(normalizedResponse));
|
|
1462
|
-
}
|
|
1463
|
-
let { passed, reason } = evaluateExpectation(testCase, normalizedResponse);
|
|
1464
|
-
if (passed && testCase.assertions) {
|
|
1465
|
-
const assertionResult = evaluateAssertions(testCase, normalizedResponse);
|
|
1466
|
-
if (!assertionResult.passed) {
|
|
1467
|
-
passed = false;
|
|
1468
|
-
reason = assertionResult.reason;
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
// Capture results if specified in test case
|
|
1472
|
-
if (passed && testCase.captureResult) {
|
|
1473
|
-
captureResultValues(testCase, normalizedResponse);
|
|
1474
|
-
}
|
|
1475
|
-
|
|
1476
|
-
// CRITICAL FIX: For performance tests (tests with timeoutMs), if the response
|
|
1477
|
-
// has success=false AND the PRIMARY expectation is success, the test should FAIL.
|
|
1478
|
-
// However, if the PRIMARY expectation is failure (error/not found/etc), then
|
|
1479
|
-
// success=false is the EXPECTED outcome and the test should PASS.
|
|
1480
|
-
// This fixes negative test cases (like delete_object with non-existent actor)
|
|
1481
|
-
// where success=false is the correct expected result.
|
|
1482
|
-
const isPerformanceTest = testCase.arguments?.timeoutMs !== undefined ||
|
|
1483
|
-
testCase.scenario?.includes('performance');
|
|
1484
|
-
const responseSuccess = getResponseOutcome(normalizedResponse).structuredSuccess;
|
|
1485
|
-
|
|
1486
|
-
// Check PRIMARY intent - if the test EXPECTS failure, success=false is correct
|
|
1487
|
-
const { primaryExpectsFailure } = getExpectationIntent(testCase.expected || '');
|
|
1488
|
-
|
|
1489
|
-
// Only fail performance test if:
|
|
1490
|
-
// 1. It's a performance test AND
|
|
1491
|
-
// 2. Response shows success=false AND
|
|
1492
|
-
// 3. PRIMARY expectation is NOT failure (test expected success)
|
|
1493
|
-
if (isPerformanceTest && responseSuccess === false && !primaryExpectsFailure) {
|
|
1494
|
-
passed = false;
|
|
1495
|
-
const errorMsg = normalizedResponse?.structuredContent?.error ||
|
|
1496
|
-
normalizedResponse?.structuredContent?.message ||
|
|
1497
|
-
'Operation failed during performance test';
|
|
1498
|
-
reason = `Performance test failed: Operation returned success=false. Error: ${errorMsg}`;
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
const responseSummary = summarizeResponseForReport(normalizedResponse);
|
|
1502
|
-
|
|
1503
|
-
if (!passed) {
|
|
1504
|
-
console.log(`[FAILED] ${testCase.scenario} (${durationMs.toFixed(1)} ms) => ${reason}`);
|
|
1505
|
-
results.push({
|
|
1506
|
-
scenario: testCase.scenario,
|
|
1507
|
-
toolName: testCase.toolName,
|
|
1508
|
-
arguments: testCase.arguments,
|
|
1509
|
-
expected: testCase.expected,
|
|
1510
|
-
status: 'failed',
|
|
1511
|
-
durationMs,
|
|
1512
|
-
detail: reason,
|
|
1513
|
-
...responseSummary,
|
|
1514
|
-
response: normalizedResponse
|
|
1515
|
-
});
|
|
1516
|
-
if (isBridgeDisconnectedSignal(normalizedResponse) || isBridgeDisconnectedSignal(reason)) {
|
|
1517
|
-
console.log('🛑 Automation bridge is not connected; aborting remaining tests to avoid wasting time.');
|
|
1518
|
-
break;
|
|
1519
|
-
}
|
|
1520
|
-
} else {
|
|
1521
|
-
console.log(`[PASSED] ${testCase.scenario} (${durationMs.toFixed(1)} ms)`);
|
|
1522
|
-
results.push({
|
|
1523
|
-
scenario: testCase.scenario,
|
|
1524
|
-
toolName: testCase.toolName,
|
|
1525
|
-
arguments: testCase.arguments,
|
|
1526
|
-
expected: testCase.expected,
|
|
1527
|
-
status: 'passed',
|
|
1528
|
-
durationMs,
|
|
1529
|
-
detail: reason,
|
|
1530
|
-
...responseSummary
|
|
1531
|
-
});
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
} catch (error) {
|
|
1535
|
-
const endTime = performance.now();
|
|
1536
|
-
const durationMs = endTime - startTime;
|
|
1537
|
-
const errorMessage = String(error?.message || error || '');
|
|
1538
|
-
const lowerExpected = (testCase.expected || '').toString().toLowerCase();
|
|
1539
|
-
const lowerError = errorMessage.toLowerCase();
|
|
1540
|
-
|
|
1541
|
-
// CRITICAL: Detect crash/connection loss indicators that should ALWAYS fail tests
|
|
1542
|
-
// unless the test explicitly expects disconnection. This prevents false positives
|
|
1543
|
-
// where tests like "error|not found" pass on crash/connection loss because
|
|
1544
|
-
// "error" matches any error message.
|
|
1545
|
-
const crashIndicators = ['disconnect', '1006', 'econnreset', 'socket hang up', 'connection lost', 'bridge disconnected'];
|
|
1546
|
-
const isCrashError = crashIndicators.some(ind => lowerError.includes(ind));
|
|
1547
|
-
const explicitlyExpectsCrash = lowerExpected.includes('disconnect') ||
|
|
1548
|
-
lowerExpected.includes('crash') ||
|
|
1549
|
-
lowerExpected.includes('connection lost') ||
|
|
1550
|
-
lowerExpected.includes('ue_not_connected');
|
|
1551
|
-
|
|
1552
|
-
if (isCrashError && !explicitlyExpectsCrash) {
|
|
1553
|
-
console.log(`[FAILED] ${testCase.scenario} (${durationMs.toFixed(1)} ms) => CRASH/CONNECTION LOSS: ${errorMessage}`);
|
|
1554
|
-
results.push({
|
|
1555
|
-
scenario: testCase.scenario,
|
|
1556
|
-
toolName: testCase.toolName,
|
|
1557
|
-
arguments: testCase.arguments,
|
|
1558
|
-
expected: testCase.expected,
|
|
1559
|
-
status: 'failed',
|
|
1560
|
-
durationMs,
|
|
1561
|
-
detail: `Infrastructure failure (crash/disconnection): ${errorMessage}`,
|
|
1562
|
-
responseSuccess: false,
|
|
1563
|
-
responseIsError: true,
|
|
1564
|
-
responseError: errorMessage
|
|
1565
|
-
});
|
|
1566
|
-
console.log('🛑 Automation bridge is not connected; aborting remaining tests to avoid wasting time.');
|
|
1567
|
-
break;
|
|
1568
|
-
}
|
|
1569
|
-
|
|
1570
|
-
const { primaryExpectsTimeout } = getExpectationIntent(testCase.expected || '');
|
|
1571
|
-
|
|
1572
|
-
// If the test's PRIMARY expectation is a timeout, then an MCP/client timeout
|
|
1573
|
-
// should be treated as the expected outcome. Accept both "timeout" and "timed out"
|
|
1574
|
-
// phrasing from different MCP client implementations.
|
|
1575
|
-
//
|
|
1576
|
-
// CRITICAL: This fixes the bug where tests like "error|timeout|success" would pass
|
|
1577
|
-
// on timeout even though the PRIMARY expectation is "error" (validation failure).
|
|
1578
|
-
// A timeout in such cases is an infrastructure failure, not a validation success.
|
|
1579
|
-
if (primaryExpectsTimeout && (lowerError.includes('timeout') || lowerError.includes('timed out'))) {
|
|
1580
|
-
console.log(`[PASSED] ${testCase.scenario} (${durationMs.toFixed(1)} ms)`);
|
|
1581
|
-
results.push({
|
|
1582
|
-
scenario: testCase.scenario,
|
|
1583
|
-
toolName: testCase.toolName,
|
|
1584
|
-
arguments: testCase.arguments,
|
|
1585
|
-
expected: testCase.expected,
|
|
1586
|
-
status: 'passed',
|
|
1587
|
-
durationMs,
|
|
1588
|
-
detail: errorMessage,
|
|
1589
|
-
responseSuccess: false,
|
|
1590
|
-
responseIsError: true,
|
|
1591
|
-
responseError: errorMessage
|
|
1592
|
-
});
|
|
1593
|
-
continue;
|
|
1594
|
-
}
|
|
1595
|
-
|
|
1596
|
-
console.log(`[FAILED] ${testCase.scenario} (${durationMs.toFixed(1)} ms) => Error: ${errorMessage}`);
|
|
1597
|
-
results.push({
|
|
1598
|
-
scenario: testCase.scenario,
|
|
1599
|
-
toolName: testCase.toolName,
|
|
1600
|
-
arguments: testCase.arguments,
|
|
1601
|
-
expected: testCase.expected,
|
|
1602
|
-
status: 'failed',
|
|
1603
|
-
durationMs,
|
|
1604
|
-
detail: errorMessage,
|
|
1605
|
-
responseSuccess: false,
|
|
1606
|
-
responseIsError: true,
|
|
1607
|
-
responseError: errorMessage
|
|
1608
|
-
});
|
|
1609
|
-
if (isBridgeDisconnectedSignal(errorMessage)) {
|
|
1610
|
-
console.log('🛑 Automation bridge is not connected; aborting remaining tests to avoid wasting time.');
|
|
1611
|
-
break;
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
// Throttle to avoid rate limiting (600 req/min = 10 req/sec)
|
|
1616
|
-
if (TEST_THROTTLE_MS > 0 && i < testCases.length - 1) {
|
|
1617
|
-
await new Promise(resolve => setTimeout(resolve, TEST_THROTTLE_MS));
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
// GEOMETRY RESET: Reset geometry actors between manage_geometry tests to prevent
|
|
1621
|
-
// polygon explosion from accumulating. Destructive operations (subdivide, bevel, shell,
|
|
1622
|
-
// etc.) can create millions of triangles, eventually causing OOM crashes.
|
|
1623
|
-
// We reset every N destructive geometry tests to balance performance vs memory safety.
|
|
1624
|
-
const GEOMETRY_RESET_INTERVAL = 5; // Reset every 5 destructive geometry tests (reduced from 10)
|
|
1625
|
-
|
|
1626
|
-
// High-impact operations that cause exponential triangle growth - ALWAYS reset before these
|
|
1627
|
-
const HIGH_IMPACT_OPS = ['poke', 'subdivide', 'triangulate', 'array_radial', 'array_linear'];
|
|
1628
|
-
|
|
1629
|
-
const isGeometryTest = testCase.toolName === 'manage_geometry';
|
|
1630
|
-
const testAction = testCase.arguments?.action || '';
|
|
1631
|
-
const isDestructiveGeometryOp = isGeometryTest && [
|
|
1632
|
-
'subdivide', 'extrude', 'inset', 'outset', 'bevel', 'offset_faces', 'shell', 'chamfer',
|
|
1633
|
-
'boolean_union', 'boolean_subtract', 'boolean_intersection', 'remesh_uniform', 'poke',
|
|
1634
|
-
'array_linear', 'array_radial', 'cylindrify', 'spherify', 'bend', 'twist', 'taper',
|
|
1635
|
-
'noise_deform', 'smooth', 'relax', 'stretch', 'triangulate'
|
|
1636
|
-
].some(op => testAction.includes(op));
|
|
1637
|
-
|
|
1638
|
-
// Always reset BEFORE high-impact operations to prevent POLYGON_LIMIT_EXCEEDED
|
|
1639
|
-
const isHighImpactOp = isGeometryTest && HIGH_IMPACT_OPS.some(op => testAction.includes(op));
|
|
1640
|
-
if (isHighImpactOp) {
|
|
1641
|
-
console.log(' 🔄 Resetting geometry before high-impact operation: ' + testAction);
|
|
1642
|
-
await resetGeometryActors();
|
|
1643
|
-
} else if (isDestructiveGeometryOp) {
|
|
1644
|
-
geometryResetCounter++;
|
|
1645
|
-
if (geometryResetCounter % GEOMETRY_RESET_INTERVAL === 0) {
|
|
1646
|
-
console.log(' 🔄 Resetting geometry actors to prevent polygon accumulation...');
|
|
1647
|
-
await resetGeometryActors();
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
|
-
const resultsPath = await persistResults(toolName, results);
|
|
1653
|
-
summarize(toolName, results, resultsPath);
|
|
1654
|
-
|
|
1655
|
-
const hasFailures = results.some((result) => result.status === 'failed');
|
|
1656
|
-
process.exitCode = hasFailures ? 1 : 0;
|
|
1657
|
-
|
|
1658
|
-
} catch (error) {
|
|
1659
|
-
console.error('Test runner failed:', error);
|
|
1660
|
-
process.exit(1);
|
|
1661
|
-
} finally {
|
|
1662
|
-
if (client) {
|
|
1663
|
-
try {
|
|
1664
|
-
await client.close();
|
|
1665
|
-
} catch {
|
|
1666
|
-
// ignore
|
|
1667
|
-
}
|
|
1668
|
-
}
|
|
1669
|
-
if (transport) {
|
|
1670
|
-
try {
|
|
1671
|
-
await transport.close();
|
|
1672
|
-
} catch {
|
|
1673
|
-
// ignore
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
|
|
1679
|
-
export class TestRunner {
|
|
1680
|
-
constructor(suiteName) {
|
|
1681
|
-
this.suiteName = suiteName || 'Test Suite';
|
|
1682
|
-
this.steps = [];
|
|
1683
|
-
}
|
|
1684
|
-
|
|
1685
|
-
addStep(name, fn) {
|
|
1686
|
-
this.steps.push({ name, fn });
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
async run() {
|
|
1690
|
-
if (this.steps.length === 0) {
|
|
1691
|
-
console.warn(`No steps registered for ${this.suiteName}`);
|
|
1692
|
-
return;
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
|
-
console.log('\n' + '='.repeat(60));
|
|
1696
|
-
console.log(`${this.suiteName}`);
|
|
1697
|
-
console.log('='.repeat(60));
|
|
1698
|
-
console.log(`Total steps: ${this.steps.length}`);
|
|
1699
|
-
console.log('');
|
|
1700
|
-
|
|
1701
|
-
let transport;
|
|
1702
|
-
let client;
|
|
1703
|
-
const results = [];
|
|
1704
|
-
|
|
1705
|
-
try {
|
|
1706
|
-
const waitMs = parseInt(process.env.UNREAL_MCP_WAIT_PORT_MS ?? '5000', 10);
|
|
1707
|
-
({ transport, client } = await createConnectedClient('unreal-mcp-step-runner', waitMs));
|
|
1708
|
-
|
|
1709
|
-
const callToolOnce = createToolCaller(client);
|
|
1710
|
-
|
|
1711
|
-
const tools = {
|
|
1712
|
-
async executeTool(toolName, args, options = {}) {
|
|
1713
|
-
const timeoutMs = typeof options.timeoutMs === 'number' ? options.timeoutMs : undefined;
|
|
1714
|
-
const response = await callToolOnce({ name: toolName, arguments: args }, timeoutMs);
|
|
1715
|
-
if (isBridgeDisconnectedSignal(response)) {
|
|
1716
|
-
throw new Error('Unreal Engine is not connected');
|
|
1717
|
-
}
|
|
1718
|
-
const { structuredContent } = normalizeResponseForEvaluation(response);
|
|
1719
|
-
|
|
1720
|
-
if (structuredContent && typeof structuredContent === 'object') {
|
|
1721
|
-
return structuredContent;
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
return {
|
|
1725
|
-
success: !response.isError,
|
|
1726
|
-
message: undefined,
|
|
1727
|
-
error: undefined
|
|
1728
|
-
};
|
|
1729
|
-
}
|
|
1730
|
-
};
|
|
1731
|
-
|
|
1732
|
-
for (const step of this.steps) {
|
|
1733
|
-
const startTime = performance.now();
|
|
1734
|
-
|
|
1735
|
-
try {
|
|
1736
|
-
// Log step start to Unreal Engine console without echoing scenario text.
|
|
1737
|
-
await callToolOnce({
|
|
1738
|
-
name: 'system_control',
|
|
1739
|
-
arguments: { action: 'console_command', command: 'Log Starting MCP test step' }
|
|
1740
|
-
}, 5000).catch(() => { });
|
|
1741
|
-
} catch (e) { /* ignore */ }
|
|
1742
|
-
|
|
1743
|
-
try {
|
|
1744
|
-
const ok = await step.fn(tools);
|
|
1745
|
-
const durationMs = performance.now() - startTime;
|
|
1746
|
-
const status = ok ? 'passed' : 'failed';
|
|
1747
|
-
console.log(formatResultLine({ scenario: step.name }, status, ok ? '' : 'Step returned false', durationMs));
|
|
1748
|
-
results.push({
|
|
1749
|
-
scenario: step.name,
|
|
1750
|
-
toolName: null,
|
|
1751
|
-
arguments: null,
|
|
1752
|
-
status,
|
|
1753
|
-
durationMs,
|
|
1754
|
-
detail: ok ? undefined : 'Step returned false'
|
|
1755
|
-
});
|
|
1756
|
-
} catch (err) {
|
|
1757
|
-
const durationMs = performance.now() - startTime;
|
|
1758
|
-
const detail = err?.message || String(err);
|
|
1759
|
-
console.log(formatResultLine({ scenario: step.name }, 'failed', detail, durationMs));
|
|
1760
|
-
results.push({
|
|
1761
|
-
scenario: step.name,
|
|
1762
|
-
toolName: null,
|
|
1763
|
-
arguments: null,
|
|
1764
|
-
status: 'failed',
|
|
1765
|
-
durationMs,
|
|
1766
|
-
detail
|
|
1767
|
-
});
|
|
1768
|
-
if (isBridgeDisconnectedSignal(detail)) {
|
|
1769
|
-
console.log('🛑 Automation bridge is not connected; aborting remaining steps to avoid wasting time.');
|
|
1770
|
-
break;
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
|
|
1775
|
-
const resultsPath = await persistResults(this.suiteName, results);
|
|
1776
|
-
summarize(this.suiteName, results, resultsPath);
|
|
1777
|
-
|
|
1778
|
-
const hasFailures = results.some((result) => result.status === 'failed');
|
|
1779
|
-
process.exitCode = hasFailures ? 1 : 0;
|
|
1780
|
-
} catch (error) {
|
|
1781
|
-
console.error('Step-based test runner failed:', error);
|
|
1782
|
-
process.exit(1);
|
|
1783
|
-
} finally {
|
|
1784
|
-
if (client) {
|
|
1785
|
-
try {
|
|
1786
|
-
await client.close();
|
|
1787
|
-
} catch {
|
|
1788
|
-
}
|
|
1789
|
-
}
|
|
1790
|
-
if (transport) {
|
|
1791
|
-
try {
|
|
1792
|
-
await transport.close();
|
|
1793
|
-
} catch {
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
|
-
}
|