summer-engine 3.7.0 → 4.0.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-plugin/marketplace.json +2 -13
- package/.claude-plugin/plugin.json +25 -22
- package/.codex-plugin/plugin.json +8 -14
- package/.cursor-plugin/plugin.json +7 -13
- package/.factory-plugin/plugin.json +7 -13
- package/AGENTS.md +19 -12
- package/CHANGELOG.md +112 -0
- package/GEMINI.md +3 -3
- package/README.md +111 -31
- package/assets/icon.png +0 -0
- package/commands/start.md +71 -0
- package/commands/summer.md +5 -3
- package/dist/cli/banner.js +3 -0
- package/dist/cli/commands/login.d.ts +27 -0
- package/dist/cli/commands/login.js +58 -12
- package/dist/cli/commands/ops.d.ts +47 -0
- package/dist/cli/commands/ops.js +301 -0
- package/dist/cli/commands/setup.d.ts +2 -0
- package/dist/cli/commands/setup.js +37 -12
- package/dist/cli/commands/skills.js +11 -7
- package/dist/cli/index.js +7 -0
- package/dist/core/agent-host.d.ts +65 -0
- package/dist/core/agent-host.js +193 -0
- package/dist/core/capabilities/agent-playbook.d.ts +3 -0
- package/dist/core/capabilities/agent-playbook.js +54 -2
- package/dist/core/capabilities/apps.d.ts +341 -0
- package/dist/core/capabilities/apps.js +353 -0
- package/dist/core/capabilities/doctor.d.ts +3 -0
- package/dist/core/capabilities/doctor.js +20 -15
- package/dist/core/capabilities/enable-plugin.d.ts +27 -0
- package/dist/core/capabilities/enable-plugin.js +75 -0
- package/dist/core/capabilities/fabricate-mesh.d.ts +2 -2
- package/dist/core/capabilities/game-task-plan.d.ts +12 -6
- package/dist/core/capabilities/game-task-plan.js +80 -5
- package/dist/core/capabilities/motion-generation.js +2 -2
- package/dist/core/capabilities/navigation/open.d.ts +6 -2
- package/dist/core/capabilities/navigation/open.js +3 -0
- package/dist/core/capabilities/publish-build.js +2 -0
- package/dist/core/capabilities/runtime-control.d.ts +4 -4
- package/dist/core/capabilities/scene-script-target.d.ts +17 -0
- package/dist/core/capabilities/scene-script-target.js +70 -0
- package/dist/core/capabilities/sfx-choices.d.ts +4 -0
- package/dist/core/capabilities/sfx-choices.js +13 -6
- package/dist/core/capabilities/tool-dispatch.d.ts +12 -3
- package/dist/core/capabilities/tool-dispatch.js +130 -46
- package/dist/core/capability-skew.js +4 -0
- package/dist/core/embeddings.d.ts +2 -0
- package/dist/core/embeddings.js +1 -1
- package/dist/core/error-codes.d.ts +62 -0
- package/dist/core/error-codes.js +97 -0
- package/dist/core/format.d.ts +2 -0
- package/dist/core/format.js +2 -1
- package/dist/core/hosted-mcp.d.ts +22 -0
- package/dist/core/hosted-mcp.js +56 -1
- package/dist/core/library-read.js +5 -0
- package/dist/core/library-search.js +2 -1
- package/dist/core/oauth.js +4 -0
- package/dist/core/ops/catalog.d.ts +41 -0
- package/dist/core/ops/catalog.js +145 -0
- package/dist/core/ops/cloud.d.ts +56 -0
- package/dist/core/ops/cloud.js +175 -0
- package/dist/core/ops/contract.d.ts +119 -0
- package/dist/core/ops/contract.js +142 -0
- package/dist/core/ops/engine-answer.d.ts +25 -0
- package/dist/core/ops/engine-answer.js +117 -0
- package/dist/core/ops/engine.d.ts +55 -0
- package/dist/core/ops/engine.js +649 -0
- package/dist/core/ops/save-files.d.ts +78 -0
- package/dist/core/ops/save-files.js +419 -0
- package/dist/core/ops/search.d.ts +9 -0
- package/dist/core/ops/search.js +55 -0
- package/dist/core/skills-registry.d.ts +16 -1
- package/dist/core/skills-registry.js +35 -2
- package/dist/core/telemetry.d.ts +32 -0
- package/dist/core/telemetry.js +38 -10
- package/dist/core/tool-profiles.d.ts +25 -0
- package/dist/core/tool-profiles.js +41 -0
- package/dist/installer/agent-config.d.ts +17 -4
- package/dist/installer/agent-config.js +22 -6
- package/dist/installer/agent-table.d.ts +3 -0
- package/dist/installer/agent-table.js +10 -7
- package/dist/installer/setup.d.ts +2 -0
- package/dist/installer/setup.js +9 -4
- package/dist/installer/version-check.d.ts +29 -9
- package/dist/installer/version-check.js +81 -28
- package/dist/mcp/command.js +7 -0
- package/dist/mcp/hosted-mount.d.ts +27 -2
- package/dist/mcp/hosted-mount.js +66 -24
- package/dist/mcp/legacy-toolset.d.ts +27 -0
- package/dist/mcp/legacy-toolset.js +43 -0
- package/dist/mcp/ops-surface.d.ts +59 -0
- package/dist/mcp/ops-surface.js +443 -0
- package/dist/mcp/server.d.ts +35 -11
- package/dist/mcp/server.js +236 -89
- package/dist/mcp/tool-results.d.ts +26 -0
- package/dist/mcp/tool-results.js +81 -0
- package/dist/mcp/tool-surface.d.ts +65 -0
- package/dist/mcp/tool-surface.js +317 -0
- package/dist/mcp/tools/app-tools.d.ts +2 -0
- package/dist/mcp/tools/app-tools.js +71 -0
- package/dist/mcp/tools/asset-tools.js +55 -53
- package/dist/mcp/tools/audit-tools.js +21 -21
- package/dist/mcp/tools/debug-tools.js +6 -6
- package/dist/mcp/tools/fabricate-tools.js +6 -6
- package/dist/mcp/tools/generate-tools.js +76 -70
- package/dist/mcp/tools/project-tools.d.ts +9 -4
- package/dist/mcp/tools/project-tools.js +16 -10
- package/dist/mcp/tools/scene-tools.js +12 -23
- package/dist/mcp/tools/script-tools.js +9 -5
- package/dist/mcp/tools/with-engine.d.ts +6 -0
- package/dist/mcp/tools/with-engine.js +19 -0
- package/gemini-extension.json +6 -12
- package/hooks/pre-commit-doctor.sh +5 -4
- package/hooks/session-start.sh +24 -28
- package/integrations/claude-desktop/README.md +1 -1
- package/integrations/copilot-jetbrains/README.md +1 -1
- package/integrations/junie/README.md +1 -1
- package/integrations/lm-studio/README.md +1 -1
- package/integrations/trae/README.md +1 -1
- package/integrations/visual-studio/README.md +1 -1
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +85 -35
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/references/product-map/resource.yaml +2 -2
- package/library/skills/3d-lighting/SKILL.md +53 -28
- package/library/skills/3d-lighting/resource.yaml +1 -1
- package/library/skills/README.md +126 -116
- package/library/skills/adaptive-music/SKILL.md +19 -23
- package/library/skills/adaptive-music/resource.yaml +1 -1
- package/library/skills/agent-playtesting/SKILL.md +1 -1
- package/library/skills/agent-playtesting/resource.yaml +1 -1
- package/library/skills/ai-characters-in-games/SKILL.md +1 -1
- package/library/skills/ai-characters-in-games/resource.yaml +1 -1
- package/library/skills/ambient-bed/SKILL.md +22 -13
- package/library/skills/ambient-bed/resource.yaml +1 -1
- package/library/skills/animated-loop/SKILL.md +41 -32
- package/library/skills/animated-loop/resource.yaml +1 -1
- package/library/skills/animation-tree/SKILL.md +1 -1
- package/library/skills/animation-tree/resource.yaml +1 -1
- package/library/skills/art-direction/SKILL.md +3 -3
- package/library/skills/art-direction/resource.yaml +1 -1
- package/library/skills/asset-strategy/SKILL.md +21 -4
- package/library/skills/asset-strategy/resource.yaml +2 -1
- package/library/skills/audio-direction/SKILL.md +10 -10
- package/library/skills/audio-direction/resource.yaml +1 -1
- package/library/skills/auto-fire-targeting/SKILL.md +1 -1
- package/library/skills/auto-fire-targeting/resource.yaml +1 -1
- package/library/skills/bounded-engine-runs/SKILL.md +1 -1
- package/library/skills/bounded-engine-runs/resource.yaml +1 -1
- package/library/skills/brainstorm-game/SKILL.md +1 -1
- package/library/skills/brainstorm-game/resource.yaml +1 -1
- package/library/skills/brainstorming/SKILL.md +1 -1
- package/library/skills/brainstorming/resource.yaml +1 -1
- package/library/skills/browse-templates/SKILL.md +1 -1
- package/library/skills/browse-templates/resource.yaml +1 -1
- package/library/skills/camera-rigs/SKILL.md +2 -2
- package/library/skills/camera-rigs/resource.yaml +1 -1
- package/library/skills/celeste-momentum-platforming/resource.yaml +1 -0
- package/library/skills/character-animation-wiring/SKILL.md +4 -4
- package/library/skills/character-animation-wiring/resource.yaml +1 -1
- package/library/skills/character-model/SKILL.md +55 -47
- package/library/skills/character-model/resource.yaml +1 -1
- package/library/skills/character-movement/SKILL.md +3 -3
- package/library/skills/character-movement/resource.yaml +1 -1
- package/library/skills/character-portrait/SKILL.md +24 -19
- package/library/skills/character-portrait/resource.yaml +1 -1
- package/library/skills/cinematic-cutscene/SKILL.md +58 -46
- package/library/skills/cinematic-cutscene/resource.yaml +1 -1
- package/library/skills/combat-basics/SKILL.md +1 -1
- package/library/skills/combat-basics/resource.yaml +1 -1
- package/library/skills/compatibility-renderer-traps/SKILL.md +1 -1
- package/library/skills/compatibility-renderer-traps/resource.yaml +1 -1
- package/library/skills/concept-art/SKILL.md +16 -12
- package/library/skills/concept-art/resource.yaml +1 -1
- package/library/skills/concept-to-level/SKILL.md +239 -0
- package/library/skills/concept-to-level/references/technical-rules.md +150 -0
- package/library/skills/concept-to-level/resource.yaml +44 -0
- package/library/skills/create-asset-sheet/SKILL.md +19 -13
- package/library/skills/create-asset-sheet/resource.yaml +1 -1
- package/library/skills/debug/SKILL.md +2 -2
- package/library/skills/debug/resource.yaml +1 -1
- package/library/skills/debugging-game-feel/SKILL.md +1 -1
- package/library/skills/debugging-game-feel/resource.yaml +1 -1
- package/library/skills/design-level/SKILL.md +23 -35
- package/library/skills/design-level/resource.yaml +1 -1
- package/library/skills/design-mechanic/SKILL.md +1 -1
- package/library/skills/design-mechanic/resource.yaml +1 -1
- package/library/skills/design-npc/SKILL.md +22 -24
- package/library/skills/design-npc/resource.yaml +1 -1
- package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
- package/library/skills/diagnosing-perf-regressions/resource.yaml +1 -1
- package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
- package/library/skills/driving-the-editor-ui/resource.yaml +1 -1
- package/library/skills/environment-kit/SKILL.md +20 -16
- package/library/skills/environment-kit/resource.yaml +1 -1
- package/library/skills/export-and-ship/SKILL.md +6 -6
- package/library/skills/export-and-ship/resource.yaml +1 -1
- package/library/skills/fabricating-assets/SKILL.md +7 -7
- package/library/skills/fabricating-assets/resource.yaml +3 -3
- package/library/skills/facial-and-lipsync/SKILL.md +14 -15
- package/library/skills/facial-and-lipsync/resource.yaml +1 -1
- package/library/skills/fps-controller/SKILL.md +33 -41
- package/library/skills/fps-controller/resource.yaml +1 -1
- package/library/skills/game-feel/SKILL.md +8 -8
- package/library/skills/game-feel/resource.yaml +1 -1
- package/library/skills/gameskill/SKILL.md +4 -4
- package/library/skills/gameskill/resource.yaml +1 -1
- package/library/skills/gdscript-patterns/SKILL.md +1 -1
- package/library/skills/gdscript-patterns/resource.yaml +1 -1
- package/library/skills/generate-motion/SKILL.md +30 -21
- package/library/skills/generate-motion/resource.yaml +1 -1
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
- package/library/skills/godogen-visual-proof-game-generation/resource.yaml +1 -0
- package/library/skills/grow-analytics/SKILL.md +3 -3
- package/library/skills/grow-analytics/resource.yaml +1 -1
- package/library/skills/headless-scripting/SKILL.md +1 -1
- package/library/skills/headless-scripting/resource.yaml +1 -1
- package/library/skills/in-game-purchases/SKILL.md +1 -1
- package/library/skills/in-game-purchases/resource.yaml +1 -1
- package/library/skills/instantiate-asset-pack/SKILL.md +2 -2
- package/library/skills/instantiate-asset-pack/resource.yaml +1 -1
- package/library/skills/lumera-single-image-scene-reconstruction/resource.yaml +1 -0
- package/library/skills/make-game/SKILL.md +4 -4
- package/library/skills/make-game/references/2d-platformer.md +1 -1
- package/library/skills/make-game/references/3d-fps.md +1 -1
- package/library/skills/make-game/references/3d-horror.md +1 -1
- package/library/skills/make-game/references/3d-third-person.md +2 -2
- package/library/skills/make-game/resource.yaml +1 -1
- package/library/skills/multiplayer/SKILL.md +1 -1
- package/library/skills/multiplayer/resource.yaml +1 -1
- package/library/skills/multiplayer-movement/SKILL.md +1 -1
- package/library/skills/multiplayer-movement/resource.yaml +1 -1
- package/library/skills/multiplayer-project/SKILL.md +1 -1
- package/library/skills/multiplayer-project/resource.yaml +1 -1
- package/library/skills/multiplayer-publish/SKILL.md +8 -7
- package/library/skills/multiplayer-publish/resource.yaml +3 -3
- package/library/skills/multiplayer-state/SKILL.md +1 -1
- package/library/skills/multiplayer-state/resource.yaml +1 -1
- package/library/skills/multiplayer-testing/SKILL.md +1 -1
- package/library/skills/multiplayer-testing/resource.yaml +1 -1
- package/library/skills/music-track/SKILL.md +22 -13
- package/library/skills/music-track/resource.yaml +1 -1
- package/library/skills/navigate-summer/SKILL.md +11 -9
- package/library/skills/navigate-summer/resource.yaml +1 -1
- package/library/skills/new-project/SKILL.md +1 -1
- package/library/skills/new-project/resource.yaml +1 -1
- package/library/skills/organic-model/SKILL.md +24 -18
- package/library/skills/organic-model/resource.yaml +1 -1
- package/library/skills/pixel-art/SKILL.md +27 -23
- package/library/skills/pixel-art/resource.yaml +1 -1
- package/library/skills/play/SKILL.md +1 -1
- package/library/skills/play/resource.yaml +1 -1
- package/library/skills/playtesting-a-feature/SKILL.md +1 -1
- package/library/skills/playtesting-a-feature/resource.yaml +1 -1
- package/library/skills/procedural-animation/SKILL.md +20 -16
- package/library/skills/procedural-animation/resource.yaml +1 -1
- package/library/skills/prop-model/SKILL.md +25 -19
- package/library/skills/prop-model/resource.yaml +1 -1
- package/library/skills/psx-retro-rendering/resource.yaml +1 -0
- package/library/skills/publish-your-game/SKILL.md +16 -6
- package/library/skills/publish-your-game/resource.yaml +3 -3
- package/library/skills/realtime-wet-surfaces/resource.yaml +1 -0
- package/library/skills/release-readiness/SKILL.md +1 -1
- package/library/skills/release-readiness/resource.yaml +1 -1
- package/library/skills/remote-deploy/SKILL.md +1 -1
- package/library/skills/remote-deploy/resource.yaml +1 -1
- package/library/skills/retarget/SKILL.md +23 -20
- package/library/skills/retarget/resource.yaml +1 -1
- package/library/skills/running-in-the-cloud/SKILL.md +1 -1
- package/library/skills/running-in-the-cloud/resource.yaml +1 -1
- package/library/skills/save-load/SKILL.md +1 -1
- package/library/skills/save-load/resource.yaml +1 -1
- package/library/skills/scene-composition/SKILL.md +1 -1
- package/library/skills/scene-composition/resource.yaml +1 -1
- package/library/skills/scene-hierarchy-design/SKILL.md +2 -2
- package/library/skills/scene-hierarchy-design/resource.yaml +1 -1
- package/library/skills/scene-scripting/SKILL.md +66 -636
- package/library/skills/scene-scripting/references/ctx-api.md +184 -0
- package/library/skills/scene-scripting/references/recipes-2d-ui.md +193 -0
- package/library/skills/scene-scripting/references/recipes-3d.md +280 -0
- package/library/skills/scene-scripting/resource.yaml +4 -4
- package/library/skills/scene-to-level/SKILL.md +2 -2
- package/library/skills/scene-to-level/resource.yaml +1 -1
- package/library/skills/skill-create/resource.yaml +1 -0
- package/library/skills/skill-improve/resource.yaml +1 -0
- package/library/skills/skill-test/SKILL.md +2 -2
- package/library/skills/skill-test/resource.yaml +1 -0
- package/library/skills/skintokens-auto-rigging/resource.yaml +1 -0
- package/library/skills/skybox-panorama/SKILL.md +27 -21
- package/library/skills/skybox-panorama/resource.yaml +1 -1
- package/library/skills/sound-effect/SKILL.md +31 -20
- package/library/skills/sound-effect/resource.yaml +1 -1
- package/library/skills/spatial-placement/SKILL.md +14 -9
- package/library/skills/spatial-placement/resource.yaml +1 -1
- package/library/skills/sprite-sheet/SKILL.md +32 -27
- package/library/skills/sprite-sheet/resource.yaml +1 -1
- package/library/skills/store-art/SKILL.md +3 -3
- package/library/skills/store-art/resource.yaml +2 -2
- package/library/skills/store-listing/SKILL.md +3 -3
- package/library/skills/store-listing/resource.yaml +2 -2
- package/library/skills/summer-analytics/SKILL.md +7 -5
- package/library/skills/summer-analytics/resource.yaml +2 -2
- package/library/skills/summer-apps/SKILL.md +168 -0
- package/library/skills/summer-apps/manifest.md +57 -0
- package/library/skills/summer-apps/minimal-app.md +183 -0
- package/library/skills/summer-apps/resource.yaml +36 -0
- package/library/skills/summer-apps/sdk-reference.md +135 -0
- package/library/skills/summer-apps-design/SKILL.md +197 -0
- package/library/skills/summer-apps-design/resource.yaml +23 -0
- package/library/skills/summer-assets/SKILL.md +56 -0
- package/library/skills/summer-assets/resource.yaml +34 -0
- package/library/skills/summer-store/SKILL.md +1 -1
- package/library/skills/text-to-motion/SKILL.md +30 -23
- package/library/skills/text-to-motion/prompts-and-controls.md +5 -5
- package/library/skills/text-to-motion/resource.yaml +1 -1
- package/library/skills/text-to-motion/rigging-for-text-motion.md +2 -2
- package/library/skills/tileable-texture/SKILL.md +19 -15
- package/library/skills/tileable-texture/resource.yaml +1 -1
- package/library/skills/trailer-shot/SKILL.md +28 -24
- package/library/skills/trailer-shot/resource.yaml +1 -1
- package/library/skills/tune-performance/SKILL.md +6 -6
- package/library/skills/tune-performance/resource.yaml +1 -1
- package/library/skills/ui-basics/SKILL.md +41 -36
- package/library/skills/ui-basics/resource.yaml +1 -1
- package/library/skills/ui-graphics/SKILL.md +47 -38
- package/library/skills/ui-graphics/resource.yaml +1 -1
- package/library/skills/use-widget-asset/SKILL.md +1 -1
- package/library/skills/use-widget-asset/resource.yaml +1 -1
- package/library/skills/using-summer/SKILL.md +7 -5
- package/library/skills/using-summer/resource.yaml +1 -1
- package/library/skills/vehicle-model/SKILL.md +65 -57
- package/library/skills/vehicle-model/resource.yaml +1 -1
- package/library/skills/verification-before-completion/SKILL.md +1 -1
- package/library/skills/verification-before-completion/resource.yaml +1 -1
- package/library/skills/verifying-scenes/SKILL.md +2 -2
- package/library/skills/verifying-scenes/resource.yaml +1 -1
- package/library/skills/vfx-dissolve/SKILL.md +2 -2
- package/library/skills/vfx-dissolve/resource.yaml +1 -1
- package/library/skills/vfx-fire/SKILL.md +15 -41
- package/library/skills/vfx-fire/resource.yaml +1 -1
- package/library/skills/vfx-hit-spark/SKILL.md +1 -1
- package/library/skills/vfx-hit-spark/resource.yaml +1 -1
- package/library/skills/vfx-lightning/SKILL.md +7 -16
- package/library/skills/vfx-lightning/resource.yaml +1 -1
- package/library/skills/vfx-magic-glow/SKILL.md +23 -32
- package/library/skills/vfx-magic-glow/resource.yaml +1 -1
- package/library/skills/vfx-muzzle-flash/SKILL.md +20 -35
- package/library/skills/vfx-muzzle-flash/resource.yaml +1 -1
- package/library/skills/vfx-smoke/SKILL.md +13 -31
- package/library/skills/vfx-smoke/resource.yaml +1 -1
- package/library/skills/vfx-water-ripple/SKILL.md +12 -31
- package/library/skills/vfx-water-ripple/resource.yaml +1 -1
- package/library/skills/voice-line/SKILL.md +71 -40
- package/library/skills/voice-line/resource.yaml +1 -1
- package/library/skills/web-and-touch-input/SKILL.md +1 -1
- package/library/skills/web-and-touch-input/resource.yaml +1 -1
- package/library/skills/web-compatibility-look/SKILL.md +1 -1
- package/library/skills/web-compatibility-look/resource.yaml +1 -1
- package/library/skills/world-building-3d/SKILL.md +1 -1
- package/library/skills/world-building-3d/resource.yaml +1 -1
- package/library/skills/writing-skills/resource.yaml +1 -0
- package/library/tools/add-node/GUIDE.md +14 -0
- package/library/tools/align-distribute-3d/GUIDE.md +7 -0
- package/library/tools/app-call/resource.yaml +59 -0
- package/library/tools/app-create/resource.yaml +67 -0
- package/library/tools/app-data/resource.yaml +74 -0
- package/library/tools/app-dock/resource.yaml +59 -0
- package/library/tools/app-events/resource.yaml +68 -0
- package/library/tools/app-get/resource.yaml +46 -0
- package/library/tools/app-guide/resource.yaml +55 -0
- package/library/tools/app-list/resource.yaml +48 -0
- package/library/tools/app-page/resource.yaml +74 -0
- package/library/tools/app-publish/resource.yaml +90 -0
- package/library/tools/app-report-gap/resource.yaml +58 -0
- package/library/tools/app-screenshot/resource.yaml +103 -0
- package/library/tools/app-tools/resource.yaml +46 -0
- package/library/tools/app-update/resource.yaml +68 -0
- package/library/tools/attach-to-surface/GUIDE.md +15 -0
- package/library/tools/batch/GUIDE.md +27 -0
- package/library/tools/camera-bookmark/GUIDE.md +12 -0
- package/library/tools/capture-gameplay/GUIDE.md +3 -0
- package/library/tools/capture-gameplay/resource.yaml +3 -3
- package/library/tools/check-job/resource.yaml +1 -1
- package/library/tools/clear-console/GUIDE.md +3 -0
- package/library/tools/connect-ports/GUIDE.md +9 -0
- package/library/tools/connect-signal/GUIDE.md +14 -0
- package/library/tools/create-debug-report/GUIDE.md +10 -0
- package/library/tools/create-scene/GUIDE.md +10 -0
- package/library/tools/debug-views/GUIDE.md +7 -0
- package/library/tools/enable-plugin/GUIDE.md +3 -0
- package/library/tools/enable-plugin/resource.yaml +53 -0
- package/library/tools/export-game/GUIDE.md +3 -0
- package/library/tools/export-game/resource.yaml +3 -3
- package/library/tools/export-templates/GUIDE.md +3 -0
- package/library/tools/fabricate-3d/GUIDE.md +19 -0
- package/library/tools/frame-nodes/GUIDE.md +9 -0
- package/library/tools/frame-shot/GUIDE.md +9 -0
- package/library/tools/game-control/GUIDE.md +9 -0
- package/library/tools/game-input/GUIDE.md +9 -0
- package/library/tools/game-probe/GUIDE.md +9 -0
- package/library/tools/generate-3d/resource.yaml +3 -3
- package/library/tools/generate-motion/resource.yaml +2 -2
- package/library/tools/get-console/GUIDE.md +9 -0
- package/library/tools/get-console/resource.yaml +5 -0
- package/library/tools/get-debugger-errors/GUIDE.md +7 -0
- package/library/tools/get-debugger-errors/resource.yaml +5 -0
- package/library/tools/get-debugger-warnings/GUIDE.md +7 -0
- package/library/tools/get-debugger-warnings/resource.yaml +5 -0
- package/library/tools/get-diagnostics/GUIDE.md +13 -0
- package/library/tools/get-project-context/GUIDE.md +25 -0
- package/library/tools/get-runtime-tree/GUIDE.md +7 -0
- package/library/tools/get-runtime-tree/resource.yaml +5 -0
- package/library/tools/get-scene-tree/GUIDE.md +11 -0
- package/library/tools/get-scene-tree/resource.yaml +5 -0
- package/library/tools/get-script-errors/GUIDE.md +5 -0
- package/library/tools/grep/GUIDE.md +11 -0
- package/library/tools/import-asset/GUIDE.md +8 -0
- package/library/tools/import-asset-by-id/GUIDE.md +12 -0
- package/library/tools/import-from-url/GUIDE.md +10 -0
- package/library/tools/import-from-url-batch/GUIDE.md +3 -0
- package/library/tools/import-hdri/GUIDE.md +16 -0
- package/library/tools/input-map-bind/GUIDE.md +11 -0
- package/library/tools/inspect-asset/GUIDE.md +14 -0
- package/library/tools/inspect-asset/resource.yaml +5 -0
- package/library/tools/inspect-node/GUIDE.md +11 -0
- package/library/tools/inspect-node/resource.yaml +5 -0
- package/library/tools/inspect-resource/GUIDE.md +7 -0
- package/library/tools/inspect-resource/resource.yaml +5 -0
- package/library/tools/inspect-runtime-node/GUIDE.md +7 -0
- package/library/tools/inspect-runtime-node/resource.yaml +5 -0
- package/library/tools/instantiate-scene/GUIDE.md +12 -0
- package/library/tools/is-running/GUIDE.md +3 -0
- package/library/tools/measure/GUIDE.md +8 -0
- package/library/tools/navigation-probe/GUIDE.md +9 -0
- package/library/tools/open/resource.yaml +2 -2
- package/library/tools/open-main-scene/GUIDE.md +6 -0
- package/library/tools/open-scene/GUIDE.md +8 -0
- package/library/tools/place-adjacent/GUIDE.md +7 -0
- package/library/tools/play/GUIDE.md +13 -0
- package/library/tools/project-setting/GUIDE.md +9 -0
- package/library/tools/publish-build/resource.yaml +6 -6
- package/library/tools/raycast/GUIDE.md +7 -0
- package/library/tools/read-file/GUIDE.md +10 -0
- package/library/tools/read-library/resource.yaml +5 -0
- package/library/tools/recent-events/GUIDE.md +7 -0
- package/library/tools/remove-node/GUIDE.md +3 -0
- package/library/tools/repeat-along/GUIDE.md +5 -0
- package/library/tools/replace-node/GUIDE.md +9 -0
- package/library/tools/replace-text/GUIDE.md +5 -0
- package/library/tools/run-editor-script/GUIDE.md +16 -0
- package/library/tools/run-script/GUIDE.md +30 -0
- package/library/tools/run-script/resource.yaml +6 -3
- package/library/tools/runtime-animate/GUIDE.md +7 -0
- package/library/tools/runtime-call/GUIDE.md +7 -0
- package/library/tools/runtime-set/GUIDE.md +9 -0
- package/library/tools/runtime-spawn/GUIDE.md +9 -0
- package/library/tools/save-scene/GUIDE.md +3 -0
- package/library/tools/scene-audit/GUIDE.md +29 -0
- package/library/tools/screenshot/GUIDE.md +17 -0
- package/library/tools/select-node/GUIDE.md +3 -0
- package/library/tools/set-prop/GUIDE.md +23 -0
- package/library/tools/set-resource-property/GUIDE.md +8 -0
- package/library/tools/shot-sheet/GUIDE.md +7 -0
- package/library/tools/snap-to-surface/GUIDE.md +17 -0
- package/library/tools/snapshot-diff/GUIDE.md +7 -0
- package/library/tools/starcast/GUIDE.md +12 -0
- package/library/tools/stop/GUIDE.md +3 -0
- package/library/tools/test-placement/GUIDE.md +7 -0
- package/library/tools/ui-actions/GUIDE.md +12 -0
- package/library/tools/ui-activate/GUIDE.md +11 -0
- package/library/tools/ui-screenshot/GUIDE.md +9 -0
- package/library/tools/ui-tree/GUIDE.md +10 -0
- package/library/tools/wait-for-event/GUIDE.md +11 -0
- package/library/tools/world-snapshot/GUIDE.md +9 -0
- package/library/tools/write-file/GUIDE.md +5 -0
- package/library/tools/zoom/GUIDE.md +5 -0
- package/package.json +6 -4
- package/registry/generated/aliases.json +15 -0
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +6 -12
- package/registry/generated/index.json +1155 -408
- package/registry/generated/marketplace.claude.json +2 -13
- package/registry/generated/plugin.claude.json +25 -22
- package/registry/generated/plugin.codex.json +8 -14
- package/registry/generated/plugin.cursor.json +7 -13
- package/registry/generated/plugin.factory.json +7 -13
- package/registry/generated/server.json +34 -0
- package/registry/generated/skills-index.md +126 -116
- package/registry/generated/skills-registry.json +178 -113
- package/registry/operations/fixtures/invalid-deprecated-without-replacement.json +60 -0
- package/registry/operations/fixtures/invalid-name.json +60 -0
- package/registry/operations/fixtures/invalid-publish-without-owner.json +82 -0
- package/registry/operations/fixtures/invalid-spend-without-estimate.json +42 -0
- package/registry/operations/fixtures/invalid-unknown-field.json +61 -0
- package/registry/operations/fixtures/valid-player-facing.json +82 -0
- package/registry/operations/fixtures/valid-read.json +60 -0
- package/registry/operations/fixtures/valid-spend.json +43 -0
- package/registry/operations/legacy-names.json +1206 -0
- package/registry/schemas/allowed-hosts.json +4 -2
- package/registry/schemas/operation.schema.json +318 -0
- package/registry/schemas/skill.schema.json +4 -0
- package/CLAUDE.md +0 -7
package/dist/mcp/server.js
CHANGED
|
@@ -16,6 +16,7 @@ import { registerEventTools } from "./tools/event-tools.js";
|
|
|
16
16
|
import { registerFabricateTools } from "./tools/fabricate-tools.js";
|
|
17
17
|
import { registerUiTools } from "./tools/ui-tools.js";
|
|
18
18
|
import { registerRuntimeTools } from "./tools/runtime-tools.js";
|
|
19
|
+
import { registerAppTools } from "./tools/app-tools.js";
|
|
19
20
|
import { recordToolCall, registrationHasInputSchema, trajectoryArgsFor, } from "../core/trajectory.js";
|
|
20
21
|
import { registerFileTools } from "./tools/file-tools.js";
|
|
21
22
|
import { registerAssetTools } from "./tools/asset-tools.js";
|
|
@@ -26,29 +27,49 @@ import { registerNavigationTools } from "./tools/navigation-tools.js";
|
|
|
26
27
|
import { registerLibraryTools } from "./tools/library-tools.js";
|
|
27
28
|
import { getCachedBootDriftNotice as getCachedNotice, setCachedBootDriftNotice, } from "./boot-notice.js";
|
|
28
29
|
import { appendMcpLogEvent } from "../core/mcp-log.js";
|
|
29
|
-
import { prepareHostedMount } from "./hosted-mount.js";
|
|
30
|
+
import { defaultHostedMountDependencies, prepareHostedMount } from "./hosted-mount.js";
|
|
31
|
+
import { applyOpsSurface, hostedFileTools, OPS_MCP_ASSETS_INSTRUCTIONS, OPS_MCP_INSTRUCTIONS, SUMMER_CALL, SUMMER_SEARCH } from "./ops-surface.js";
|
|
32
|
+
import { FileSaver } from "../core/ops/save-files.js";
|
|
33
|
+
import { opForToolCall } from "../core/ops/contract.js";
|
|
34
|
+
import { v4HostedUrl } from "../core/ops/cloud.js";
|
|
30
35
|
import { serveProviderSafeToolSchemas } from "./provider-safe-schema.js";
|
|
36
|
+
import { legacyHostedDescription, resolveLegacy, takeLegacyToolset } from "./legacy-toolset.js";
|
|
37
|
+
import { OUTPUT_CAPS, PROFILE_TOOL_LIMIT, PROFILES, TOOLSETS, annotationsFor, registryAuthorities, resolveToolSelection, selectionIncludes, withMaxCharactersArg, } from "./tool-surface.js";
|
|
38
|
+
import { shapeToolResult, singleEditCounter } from "./tool-results.js";
|
|
39
|
+
import { recordLocalToolCall, recordMcpSession } from "../core/telemetry.js";
|
|
40
|
+
import { currentToolContext, registerMcpClientSource, runWithToolContext } from "../core/agent-host.js";
|
|
31
41
|
import { buildBootDriftNotice, fetchLatestRegistryVersion, } from "../installer/version-check.js";
|
|
32
42
|
import { TOOLKIT_VERSION as version } from "../core/version.js";
|
|
43
|
+
import { ENGINE_FREE_NOTE, engineNotRunningFromConnectError } from "../core/error-codes.js";
|
|
44
|
+
import { resolveSurface } from "../core/tool-profiles.js";
|
|
45
|
+
import { OAuthError } from "../core/oauth.js";
|
|
33
46
|
let processDiagnosticsInstalled = false;
|
|
47
|
+
const FULL_SELECTION = { profile: "full", toolsets: null, ignored: [] };
|
|
34
48
|
export const getCachedBootDriftNotice = getCachedNotice;
|
|
35
49
|
/**
|
|
36
50
|
* Server `instructions` in the MCP initialize response (SDK ServerOptions,
|
|
37
51
|
* @modelcontextprotocol/sdk >= 1.x). Hosts hand this to the model once per
|
|
38
|
-
* session, before any tool call — the place for the
|
|
39
|
-
* showed an agent needs on the first
|
|
40
|
-
*
|
|
41
|
-
* it costs a few hundred tokens once; the
|
|
42
|
-
*
|
|
43
|
-
* sentence names the publishing path,
|
|
44
|
-
* review feedback is read.
|
|
52
|
+
* session, before any tool call — the place for the habits end-to-end runs
|
|
53
|
+
* showed an agent needs on the first turn and would otherwise learn the hard
|
|
54
|
+
* way, including scripting a run of scene edits instead of hundreds of single
|
|
55
|
+
* calls. Kept under 600 characters so it costs a few hundred tokens once; the
|
|
56
|
+
* full operating guide stays in the summer_agent_playbook prompt /
|
|
57
|
+
* summer_get_agent_playbook tool. The last sentence names the publishing path,
|
|
58
|
+
* the owner-approval rule and where review feedback is read.
|
|
45
59
|
*/
|
|
46
|
-
export const SUMMER_MCP_INSTRUCTIONS = "Summer Engine MCP. Call summer_get_project_context first: it binds the open project
|
|
47
|
-
"Before building or fixing
|
|
48
|
-
"
|
|
49
|
-
"
|
|
60
|
+
export const SUMMER_MCP_INSTRUCTIONS = "Summer Engine MCP. Call summer_get_project_context first: it binds the open project. " +
|
|
61
|
+
"Before building or fixing: summer_search_library, then summer_read_library the hit. " +
|
|
62
|
+
"More than 3 scene edits: one summer_run_script (snapshot, script, diff, screenshot). " +
|
|
63
|
+
"After play: summer_get_diagnostics, not only summer_get_console. " +
|
|
64
|
+
"All-black screenshot: no redraw yet, recapture. " +
|
|
50
65
|
"Report verified entries via summer_library_feedback. " +
|
|
51
|
-
"
|
|
66
|
+
"Publish: summer_export_game, summer_publish_build, summer_store_*; never alone: summer_store_submit returns the owner's approval link, summer_store_review the feedback.";
|
|
67
|
+
/** The same first-turn habits for a profile without engine tools (`--profile assets`). */
|
|
68
|
+
export const SUMMER_MCP_ASSETS_INSTRUCTIONS = "Summer MCP, assets profile: generation and the Summer asset library, no engine tools. " +
|
|
69
|
+
"Read skill/summer-assets, then the asset's skill (sound-effect, prop-model, ...): stop at the file, skip its engine steps. " +
|
|
70
|
+
"Generation costs credits: confirm first. A job returns a jobId: summer_check_job. " +
|
|
71
|
+
"Hand over files with summer_get_asset_download_url. " +
|
|
72
|
+
"Report verified entries via summer_library_feedback.";
|
|
52
73
|
/**
|
|
53
74
|
* Fire-and-forget probe of the npm registry on MCP boot. Caches the result for
|
|
54
75
|
* the session. We never await this in startup so a slow / offline registry
|
|
@@ -102,26 +123,20 @@ export async function getClient() {
|
|
|
102
123
|
const reason = error instanceof Error
|
|
103
124
|
? error.message
|
|
104
125
|
: "Summer Engine is not running.";
|
|
126
|
+
// Nothing reachable: a coded error withEngine renders as JSON
|
|
127
|
+
// (engine_not_running). Anything else (several editors open, …) already
|
|
128
|
+
// says how to pick one.
|
|
129
|
+
const notRunning = engineNotRunningFromConnectError(reason);
|
|
130
|
+
if (notRunning)
|
|
131
|
+
throw notRunning;
|
|
105
132
|
throw new Error(reason + "\n" +
|
|
106
|
-
"Open the intended project in Summer Engine, or run: npx -y summer-engine@latest run
|
|
107
|
-
"Note:
|
|
108
|
-
"(summer_generate_*, summer_search_assets, summer_list_my_assets, summer_get_asset, " +
|
|
109
|
-
"summer_check_job) work right now without it — they only need 'npx -y summer-engine@latest login'.");
|
|
133
|
+
"Open the intended project in Summer Engine, or run: npx -y summer-engine@latest run <project-path>\n" +
|
|
134
|
+
"Note: " + ENGINE_FREE_NOTE);
|
|
110
135
|
}
|
|
111
136
|
}
|
|
112
137
|
export function resetClient() {
|
|
113
138
|
cachedClient = null;
|
|
114
139
|
}
|
|
115
|
-
/**
|
|
116
|
-
* Passive result-size observability. Monkey-patches server.tool() so every
|
|
117
|
-
* registered handler's serialized text payload is measured and logged to
|
|
118
|
-
* stderr in the existing `[summer-mcp]` JSON shape. The result itself is
|
|
119
|
-
* never modified — external coding agents (Claude Code, Cursor, Codex)
|
|
120
|
-
* manage their own context budgets, and silently truncating their tool
|
|
121
|
-
* results is the wrong shape (see #102 revert). If a specific tool turns
|
|
122
|
-
* out to produce pathological payloads in practice, the right fix is
|
|
123
|
-
* adding range/depth/filter parameters to that tool — not a blanket cap.
|
|
124
|
-
*/
|
|
125
140
|
function errorDetails(error) {
|
|
126
141
|
if (error instanceof Error) {
|
|
127
142
|
return {
|
|
@@ -169,74 +184,115 @@ function installMcpProcessDiagnostics() {
|
|
|
169
184
|
appendMcpLogEvent("mcp:exit", { pid: process.pid, code });
|
|
170
185
|
});
|
|
171
186
|
}
|
|
172
|
-
|
|
173
|
-
|
|
187
|
+
/** Index of the zod raw shape among server.tool()'s middle arguments, or -1. */
|
|
188
|
+
function rawShapeIndex(args) {
|
|
189
|
+
for (let index = 1; index < args.length - 1; index++) {
|
|
190
|
+
const candidate = args[index];
|
|
191
|
+
if (!candidate || typeof candidate !== "object" || "_def" in candidate)
|
|
192
|
+
continue;
|
|
193
|
+
const values = Object.values(candidate);
|
|
194
|
+
if (values.length > 0 && values.every((value) => !!value && typeof value === "object" && "_def" in value))
|
|
195
|
+
return index;
|
|
196
|
+
}
|
|
197
|
+
return -1;
|
|
198
|
+
}
|
|
199
|
+
function installToolCallWrapper(server, surfaceMeta) {
|
|
200
|
+
const target = server;
|
|
201
|
+
const original = target.tool.bind(server);
|
|
202
|
+
const singleEdits = singleEditCounter();
|
|
203
|
+
const hostApp = () => server.server.getClientVersion()?.name;
|
|
174
204
|
let registeredToolCount = 0;
|
|
175
|
-
|
|
176
|
-
if (
|
|
177
|
-
return original(...
|
|
178
|
-
const name =
|
|
205
|
+
target.tool = function patchedTool(...registration) {
|
|
206
|
+
if (registration.length < 2)
|
|
207
|
+
return original(...registration);
|
|
208
|
+
const name = registration[0];
|
|
179
209
|
if (typeof name !== "string")
|
|
180
|
-
return original(...
|
|
181
|
-
const lastIdx =
|
|
182
|
-
const handler =
|
|
210
|
+
return original(...registration);
|
|
211
|
+
const lastIdx = registration.length - 1;
|
|
212
|
+
const handler = registration[lastIdx];
|
|
183
213
|
if (typeof handler !== "function")
|
|
184
|
-
return original(...
|
|
214
|
+
return original(...registration);
|
|
185
215
|
registeredToolCount += 1;
|
|
216
|
+
const args = [...registration];
|
|
217
|
+
const cap = OUTPUT_CAPS.get(name);
|
|
218
|
+
const shapeAt = cap === undefined ? -1 : rawShapeIndex(args);
|
|
219
|
+
if (shapeAt > 0)
|
|
220
|
+
args[shapeAt] = withMaxCharactersArg(name, args[shapeAt]);
|
|
186
221
|
// Schema-less tools receive only the SDK's `extra` — never record that as
|
|
187
222
|
// the tool's arguments (see registrationHasInputSchema).
|
|
188
223
|
const hasInputSchema = registrationHasInputSchema(args);
|
|
189
|
-
|
|
224
|
+
args[lastIdx] = async (...handlerArgs) => {
|
|
225
|
+
let maxCharacters = cap;
|
|
226
|
+
if (shapeAt > 0 && handlerArgs[0] && typeof handlerArgs[0] === "object") {
|
|
227
|
+
const { maxCharacters: requested, ...rest } = handlerArgs[0];
|
|
228
|
+
if (typeof requested === "number")
|
|
229
|
+
maxCharacters = requested;
|
|
230
|
+
handlerArgs = [rest, ...handlerArgs.slice(1)];
|
|
231
|
+
}
|
|
190
232
|
const startedAt = Date.now();
|
|
233
|
+
// A tool another tool runs (summer_call, a v4 operation over its 3.x
|
|
234
|
+
// tool) is part of that call: only the outer call sends a usage line.
|
|
235
|
+
const nested = currentToolContext() !== undefined;
|
|
236
|
+
const recordUsage = (ok, durationMs) => {
|
|
237
|
+
if (!nested)
|
|
238
|
+
recordLocalToolCall({ tool: name, op: opForToolCall(name, handlerArgs[0]), ...surfaceMeta, ok, durationMs, mcpClient: hostApp() });
|
|
239
|
+
};
|
|
191
240
|
let result;
|
|
192
241
|
try {
|
|
193
|
-
|
|
242
|
+
// Every Summer request the tool makes names it (core/agent-host.ts).
|
|
243
|
+
result = await runWithToolContext(name, "mcp", () => handler(...handlerArgs));
|
|
194
244
|
}
|
|
195
245
|
catch (error) {
|
|
196
246
|
// A handler THROW never produced a result to classify; record it as
|
|
197
247
|
// ok:false / exception so the stream does not silently skip failures,
|
|
198
248
|
// then let the SDK turn it into the protocol error it always did.
|
|
249
|
+
const durationMs = Date.now() - startedAt;
|
|
199
250
|
recordToolCall({
|
|
200
251
|
tool: name,
|
|
201
252
|
args: trajectoryArgsFor(hasInputSchema, handlerArgs),
|
|
202
253
|
exception: error instanceof Error ? error.message : String(error),
|
|
203
|
-
durationMs
|
|
254
|
+
durationMs,
|
|
204
255
|
});
|
|
256
|
+
recordUsage(false, durationMs);
|
|
205
257
|
throw error;
|
|
206
258
|
}
|
|
207
259
|
const durationMs = Date.now() - startedAt;
|
|
260
|
+
const record = result && typeof result === "object" ? result : null;
|
|
261
|
+
const isError = record?.isError === true;
|
|
262
|
+
// withEngine stamps failure classifiers + retried + bound hash on a
|
|
263
|
+
// non-enumerable symbol so we can log them here without every tool
|
|
264
|
+
// threading its own name through withEngine.
|
|
265
|
+
const meta = record ? record[WITH_ENGINE_META] : undefined;
|
|
208
266
|
try {
|
|
267
|
+
const hint = singleEdits(name, isError);
|
|
268
|
+
result = shapeToolResult(result, { maxCharacters, hint });
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
// Shaping must never break the tool call; the raw result goes out.
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
recordMcpSession();
|
|
275
|
+
recordUsage(!isError, durationMs);
|
|
209
276
|
// Opt-in local trajectory capture: one JSONL line per tool call when
|
|
210
277
|
// SUMMER_TRAJECTORY_DIR is set. recordToolCall never throws and is a
|
|
211
278
|
// no-op when the env var is unset.
|
|
212
|
-
{
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
durationMs,
|
|
225
|
-
// Read only under SUMMER_TRAJECTORY_EVAL=1 (bounded summary); the
|
|
226
|
-
// default redacted stream ignores it.
|
|
227
|
-
result,
|
|
228
|
-
});
|
|
229
|
-
}
|
|
279
|
+
recordToolCall({
|
|
280
|
+
tool: name,
|
|
281
|
+
args: trajectoryArgsFor(hasInputSchema, handlerArgs),
|
|
282
|
+
isError,
|
|
283
|
+
terminalState: meta?.terminalState,
|
|
284
|
+
errorClass: meta?.errorClass,
|
|
285
|
+
failureReason: meta?.failureReason,
|
|
286
|
+
durationMs,
|
|
287
|
+
// Read only under SUMMER_TRAJECTORY_EVAL=1 (bounded summary); the
|
|
288
|
+
// default redacted stream ignores it.
|
|
289
|
+
result,
|
|
290
|
+
});
|
|
230
291
|
if (result &&
|
|
231
292
|
typeof result === "object" &&
|
|
232
293
|
"content" in result &&
|
|
233
294
|
Array.isArray(result.content)) {
|
|
234
295
|
const debug = process.env.SUMMER_MCP_DEBUG === "1";
|
|
235
|
-
const isError = result.isError === true;
|
|
236
|
-
// withEngine stamps failure classifiers + retried + bound hash on a
|
|
237
|
-
// non-enumerable symbol so we can log them here without every tool
|
|
238
|
-
// threading its own name through withEngine.
|
|
239
|
-
const meta = result[WITH_ENGINE_META];
|
|
240
296
|
// Structured per-call line. Verbose behind SUMMER_MCP_DEBUG=1; when the
|
|
241
297
|
// flag is off, log ONLY failures — the success path stays quiet.
|
|
242
298
|
if (debug || isError) {
|
|
@@ -257,17 +313,11 @@ function installResultSizeLogger(server) {
|
|
|
257
313
|
process.stderr.write(`[summer-mcp] ${callLine}\n`);
|
|
258
314
|
}
|
|
259
315
|
if (debug) {
|
|
260
|
-
|
|
261
|
-
for (const entry of result
|
|
262
|
-
.content) {
|
|
263
|
-
if (entry && entry.type === "text" && typeof entry.text === "string") {
|
|
264
|
-
chars += entry.text.length;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
const bytes = Buffer.byteLength(result.content
|
|
316
|
+
const texts = result.content
|
|
268
317
|
.filter((e) => e && e.type === "text" && typeof e.text === "string")
|
|
269
|
-
.map((e) => e.text)
|
|
270
|
-
|
|
318
|
+
.map((e) => e.text);
|
|
319
|
+
const chars = texts.reduce((sum, text) => sum + text.length, 0);
|
|
320
|
+
const bytes = Buffer.byteLength(texts.join(""), "utf8");
|
|
271
321
|
const line = JSON.stringify({
|
|
272
322
|
event: "mcp:result_size",
|
|
273
323
|
tool_name: name,
|
|
@@ -288,31 +338,44 @@ function installResultSizeLogger(server) {
|
|
|
288
338
|
}
|
|
289
339
|
return result;
|
|
290
340
|
};
|
|
291
|
-
|
|
292
|
-
newArgs[lastIdx] = wrapped;
|
|
293
|
-
return original(...newArgs);
|
|
341
|
+
return original(...args);
|
|
294
342
|
};
|
|
295
343
|
return () => registeredToolCount;
|
|
296
344
|
}
|
|
297
345
|
/**
|
|
298
|
-
* Build the MCP server with every Summer tool
|
|
299
|
-
* a transport. startMcpServer() uses this;
|
|
300
|
-
* tool surface against
|
|
346
|
+
* Build the MCP server with every Summer tool of the selected profile
|
|
347
|
+
* registered, without connecting a transport. startMcpServer() uses this;
|
|
348
|
+
* tests use it to count the live tool surface against
|
|
349
|
+
* registry/generated/counts.json. Without a selection: the full profile.
|
|
301
350
|
*/
|
|
302
|
-
export
|
|
351
|
+
export { resolveSurface };
|
|
352
|
+
const NO_CLOUD = {
|
|
353
|
+
call: async () => {
|
|
354
|
+
throw new OAuthError("store_login_required", "The hosted Summer server is not connected.", 'Recovery: run "summer login".');
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
export function createMcpServer(selection = FULL_SELECTION, options = {}) {
|
|
358
|
+
const surface = options.surface ?? "v3";
|
|
359
|
+
// A profile without engine tools (assets) gets the no-engine instructions,
|
|
360
|
+
// playbook and task plan, so nothing points the agent at a tool it lacks.
|
|
361
|
+
const engine = !selection.toolsets || selection.toolsets.has("engine");
|
|
303
362
|
const server = new McpServer({
|
|
304
363
|
name: "summer-engine",
|
|
305
364
|
version,
|
|
306
|
-
}, {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
365
|
+
}, {
|
|
366
|
+
instructions: surface === "v4"
|
|
367
|
+
? engine ? OPS_MCP_INSTRUCTIONS : OPS_MCP_ASSETS_INSTRUCTIONS
|
|
368
|
+
: engine ? SUMMER_MCP_INSTRUCTIONS : SUMMER_MCP_ASSETS_INSTRUCTIONS,
|
|
369
|
+
});
|
|
370
|
+
const getWrappedToolCount = installToolCallWrapper(server, { surfaceVersion: surface, profile: selection.profile });
|
|
371
|
+
// Requests to Summer's servers name the agent app from the initialize handshake.
|
|
372
|
+
registerMcpClientSource(() => server.server.getClientVersion());
|
|
310
373
|
registerSceneTools(server);
|
|
311
374
|
registerDebugTools(server);
|
|
312
375
|
registerVisualTools(server);
|
|
313
376
|
registerSeeingTools(server);
|
|
314
377
|
registerAuditTools(server);
|
|
315
|
-
registerProjectTools(server);
|
|
378
|
+
registerProjectTools(server, { engine });
|
|
316
379
|
registerFileTools(server);
|
|
317
380
|
registerAssetTools(server);
|
|
318
381
|
registerGenerateTools(server);
|
|
@@ -328,12 +391,40 @@ export function createMcpServer() {
|
|
|
328
391
|
registerFabricateTools(server);
|
|
329
392
|
registerUiTools(server);
|
|
330
393
|
registerRuntimeTools(server);
|
|
394
|
+
registerAppTools(server);
|
|
331
395
|
// The playbook is also an MCP prompt so prompt-surfacing hosts get it
|
|
332
396
|
// natively (same content as the summer_get_agent_playbook tool).
|
|
333
|
-
registerPlaybookPrompt(server);
|
|
397
|
+
registerPlaybookPrompt(server, { engine });
|
|
334
398
|
// Strict providers (Kimi, OpenAI strict) reject tuple and $ref schemas.
|
|
335
399
|
serveProviderSafeToolSchemas(server);
|
|
336
|
-
|
|
400
|
+
// Effect hints from each tool's registry authority, then the profile:
|
|
401
|
+
// tools outside it are removed before any client lists them.
|
|
402
|
+
const registered = server._registeredTools;
|
|
403
|
+
const authorities = registryAuthorities();
|
|
404
|
+
let removed = 0;
|
|
405
|
+
for (const [name, tool] of Object.entries(registered)) {
|
|
406
|
+
if (!selectionIncludes(selection, name, true)) {
|
|
407
|
+
tool.remove();
|
|
408
|
+
removed += 1;
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
const authority = authorities.get(name);
|
|
412
|
+
if (authority)
|
|
413
|
+
tool.update({ annotations: annotationsFor(name, authority) });
|
|
414
|
+
}
|
|
415
|
+
// Without engine tools nothing imports a file into a project, so files save into it by default.
|
|
416
|
+
const files = new FileSaver({ saveByDefault: !engine });
|
|
417
|
+
if (surface === "v4")
|
|
418
|
+
applyOpsSurface(server, { engine, cloud: options.cloud ?? NO_CLOUD, legacy: options.legacy === true, files });
|
|
419
|
+
return { server, getRegisteredToolCount: () => getWrappedToolCount() - removed, files };
|
|
420
|
+
}
|
|
421
|
+
/** What the hosted tools a profile mounts are, for summer_store_tools. */
|
|
422
|
+
function hostedToolsLabel(toolsets) {
|
|
423
|
+
if (toolsets.has("ship"))
|
|
424
|
+
return "Summer store and publishing tools";
|
|
425
|
+
if (toolsets.has("tools"))
|
|
426
|
+
return "Tool Factory tools (summer_tool_*) and asset editing tools";
|
|
427
|
+
return undefined;
|
|
337
428
|
}
|
|
338
429
|
export async function startMcpServer(options = {}) {
|
|
339
430
|
configureMcpEngineSelection({
|
|
@@ -353,7 +444,22 @@ export async function startMcpServer(options = {}) {
|
|
|
353
444
|
cwd: options.cwd ?? process.cwd(),
|
|
354
445
|
},
|
|
355
446
|
});
|
|
356
|
-
const
|
|
447
|
+
const surface = resolveSurface(options.surface);
|
|
448
|
+
// `legacy` is not a toolset of its own: it lists the 3.x names on the v4 surface.
|
|
449
|
+
const toolsetList = takeLegacyToolset(options.toolsets ?? process.env.SUMMER_TOOLSETS);
|
|
450
|
+
const legacy = surface === "v4" ? resolveLegacy(toolsetList.requested) : { on: false, reason: "off" };
|
|
451
|
+
const selection = resolveToolSelection({ profile: options.profile, toolsets: toolsetList.toolsets });
|
|
452
|
+
if (selection.ignored.length > 0) {
|
|
453
|
+
writeMcpStderr("mcp:unknown_toolsets", {
|
|
454
|
+
ignored: selection.ignored,
|
|
455
|
+
profiles: Object.keys(PROFILES),
|
|
456
|
+
toolsets: TOOLSETS,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
// v4 runs cloud operations through the hosted mount below, once it exists.
|
|
460
|
+
let hostedCall = null;
|
|
461
|
+
const cloud = { call: (name, args) => (hostedCall ? hostedCall(name, args) : NO_CLOUD.call(name, args)) };
|
|
462
|
+
const { server, getRegisteredToolCount, files } = createMcpServer(selection, { surface, cloud, legacy: legacy.on });
|
|
357
463
|
// Fire-and-forget — never block tool registration on the npm registry.
|
|
358
464
|
void probeBootDrift().catch((error) => {
|
|
359
465
|
setCachedBootDriftNotice(null);
|
|
@@ -362,13 +468,54 @@ export async function startMcpServer(options = {}) {
|
|
|
362
468
|
// Hosted Summer Engine MCP tools (store, publishing, board, Grow): ready
|
|
363
469
|
// before connect, mounted after it. The first tools/list waits a few
|
|
364
470
|
// seconds for the mount (not under summer doctor, which times the list).
|
|
365
|
-
|
|
471
|
+
// A profile mounts only its hosted toolsets, and never more tools in total
|
|
472
|
+
// than PROFILE_TOOL_LIMIT.
|
|
473
|
+
// v4 mounts the hosted v4 surface (its direct tools for this profile;
|
|
474
|
+
// summer_search and summer_call stay local and forward to it).
|
|
475
|
+
// The legacy toolset (below) mounts after this mount, and again after a retry of it.
|
|
476
|
+
let legacyHosted = null;
|
|
477
|
+
const hosted = prepareHostedMount(server, surface === "v4" ? { ...defaultHostedMountDependencies, url: v4HostedUrl(selection.profile) } : undefined, {
|
|
478
|
+
...(process.env.SUMMER_MCP_DOCTOR === "1" ? { firstListWaitMs: 0 } : {}),
|
|
479
|
+
onMounted: () => void legacyHosted?.mount(),
|
|
480
|
+
...(surface === "v4"
|
|
481
|
+
? { includeTool: (name) => name !== SUMMER_SEARCH && name !== SUMMER_CALL, maxTools: PROFILE_TOOL_LIMIT, local: hostedFileTools(files) }
|
|
482
|
+
: selection.toolsets === null
|
|
483
|
+
? {}
|
|
484
|
+
: {
|
|
485
|
+
includeTool: (name) => selectionIncludes(selection, name, false),
|
|
486
|
+
maxTools: PROFILE_TOOL_LIMIT,
|
|
487
|
+
hostedToolsLabel: hostedToolsLabel(selection.toolsets),
|
|
488
|
+
}),
|
|
489
|
+
});
|
|
490
|
+
hostedCall = hosted.call;
|
|
491
|
+
// The legacy toolset also lists the hosted 3.x names this profile listed in
|
|
492
|
+
// 3.x, from the hosted 3.x surface, each running its 3.x tool, under the
|
|
493
|
+
// same limit as in 3.x. Its sign-in waits for the v4 mount's (a token
|
|
494
|
+
// refresh is not shared), so it starts at boot and the first tools/list
|
|
495
|
+
// still waits for it.
|
|
496
|
+
legacyHosted = legacy.on
|
|
497
|
+
? prepareHostedMount(server, {
|
|
498
|
+
...defaultHostedMountDependencies,
|
|
499
|
+
token: async () => {
|
|
500
|
+
await hosted.mount();
|
|
501
|
+
return defaultHostedMountDependencies.token();
|
|
502
|
+
},
|
|
503
|
+
}, {
|
|
504
|
+
...(process.env.SUMMER_MCP_DOCTOR === "1" ? { firstListWaitMs: 0 } : {}),
|
|
505
|
+
...(selection.toolsets === null ? {} : { includeTool: (name) => selectionIncludes(selection, name, false), maxTools: PROFILE_TOOL_LIMIT }),
|
|
506
|
+
describe: legacyHostedDescription,
|
|
507
|
+
})
|
|
508
|
+
: null;
|
|
366
509
|
const transport = new StdioServerTransport();
|
|
367
510
|
await server.connect(transport);
|
|
368
511
|
void hosted.mount();
|
|
512
|
+
void legacyHosted?.mount();
|
|
369
513
|
appendMcpLogEvent("mcp:ready", {
|
|
370
514
|
version,
|
|
371
515
|
pid: process.pid,
|
|
516
|
+
profile: selection.profile,
|
|
517
|
+
surface,
|
|
518
|
+
...(surface === "v4" ? { legacy: legacy.reason } : {}),
|
|
372
519
|
toolCount: getRegisteredToolCount(),
|
|
373
520
|
});
|
|
374
521
|
process.stderr.write(`[summer-mcp] MCP server running v${version}.\n`);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type Content = {
|
|
2
|
+
type?: string;
|
|
3
|
+
text?: unknown;
|
|
4
|
+
};
|
|
5
|
+
/** Pretty-printed JSON text as compact JSON; anything else unchanged. */
|
|
6
|
+
export declare function compactJsonText(text: string): string;
|
|
7
|
+
/** Cut text blocks to maxCharacters in total, with one note saying how to get the rest. */
|
|
8
|
+
export declare function capText(content: Content[], maxCharacters: number): Content[];
|
|
9
|
+
/**
|
|
10
|
+
* The text an agent gets: compact JSON, cut at maxCharacters when the tool
|
|
11
|
+
* is capped, plus an optional hint line. Images and error flags are kept.
|
|
12
|
+
*/
|
|
13
|
+
export declare function shapeToolResult(result: unknown, options: {
|
|
14
|
+
maxCharacters?: number;
|
|
15
|
+
hint?: string | null;
|
|
16
|
+
}): unknown;
|
|
17
|
+
/** The first single edit in a row that gets the hint, and how often it repeats after that. */
|
|
18
|
+
export declare const SINGLE_EDIT_HINT_AT = 4;
|
|
19
|
+
/**
|
|
20
|
+
* Counts successful single scene edits since the last batched edit
|
|
21
|
+
* (summer_run_script, summer_batch, summer_run_editor_script). Reads in
|
|
22
|
+
* between do not break the run. Returns the hint on the 4th edit in a row,
|
|
23
|
+
* then every 6th.
|
|
24
|
+
*/
|
|
25
|
+
export declare function singleEditCounter(): (tool: string, isError: boolean) => string | null;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { BATCH_EDIT_TOOLS, SINGLE_EDIT_TOOLS } from "./tool-surface.js";
|
|
2
|
+
/** Pretty-printed JSON text as compact JSON; anything else unchanged. */
|
|
3
|
+
export function compactJsonText(text) {
|
|
4
|
+
const first = text[0];
|
|
5
|
+
if ((first !== "{" && first !== "[") || !text.includes("\n"))
|
|
6
|
+
return text;
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(JSON.parse(text));
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return text;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** The library read's last line (the feedback footer) survives a cut. */
|
|
15
|
+
const KEEP_LAST_LINE = /\n(— entry_id: [^\n]*)\s*$/;
|
|
16
|
+
/** Cut text blocks to maxCharacters in total, with one note saying how to get the rest. */
|
|
17
|
+
export function capText(content, maxCharacters) {
|
|
18
|
+
const total = content.reduce((sum, part) => sum + (part.type === "text" && typeof part.text === "string" ? part.text.length : 0), 0);
|
|
19
|
+
if (total <= maxCharacters)
|
|
20
|
+
return content;
|
|
21
|
+
const note = `\n\n[Truncated: ${maxCharacters} of ${total} characters shown. Call again with maxCharacters: ${total} for all of it, or narrow the request.]`;
|
|
22
|
+
let budget = maxCharacters;
|
|
23
|
+
let cut = false;
|
|
24
|
+
const out = [];
|
|
25
|
+
for (const part of content) {
|
|
26
|
+
if (part.type !== "text" || typeof part.text !== "string") {
|
|
27
|
+
out.push(part);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (cut)
|
|
31
|
+
continue;
|
|
32
|
+
if (part.text.length <= budget) {
|
|
33
|
+
budget -= part.text.length;
|
|
34
|
+
out.push(part);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const footer = part.text.match(KEEP_LAST_LINE)?.[1];
|
|
38
|
+
out.push({ ...part, text: part.text.slice(0, budget) + note + (footer ? `\n\n${footer}` : "") });
|
|
39
|
+
cut = true;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The text an agent gets: compact JSON, cut at maxCharacters when the tool
|
|
45
|
+
* is capped, plus an optional hint line. Images and error flags are kept.
|
|
46
|
+
*/
|
|
47
|
+
export function shapeToolResult(result, options) {
|
|
48
|
+
if (!result || typeof result !== "object" || !Array.isArray(result.content))
|
|
49
|
+
return result;
|
|
50
|
+
const original = result;
|
|
51
|
+
let content = original.content.map((part) => part && part.type === "text" && typeof part.text === "string" ? { ...part, text: compactJsonText(part.text) } : part);
|
|
52
|
+
if (options.maxCharacters !== undefined)
|
|
53
|
+
content = capText(content, options.maxCharacters);
|
|
54
|
+
if (options.hint)
|
|
55
|
+
content = [...content, { type: "text", text: options.hint }];
|
|
56
|
+
return { ...original, content };
|
|
57
|
+
}
|
|
58
|
+
/** The first single edit in a row that gets the hint, and how often it repeats after that. */
|
|
59
|
+
export const SINGLE_EDIT_HINT_AT = 4;
|
|
60
|
+
const SINGLE_EDIT_HINT_EVERY = 6;
|
|
61
|
+
/**
|
|
62
|
+
* Counts successful single scene edits since the last batched edit
|
|
63
|
+
* (summer_run_script, summer_batch, summer_run_editor_script). Reads in
|
|
64
|
+
* between do not break the run. Returns the hint on the 4th edit in a row,
|
|
65
|
+
* then every 6th.
|
|
66
|
+
*/
|
|
67
|
+
export function singleEditCounter() {
|
|
68
|
+
let run = 0;
|
|
69
|
+
return (tool, isError) => {
|
|
70
|
+
if (BATCH_EDIT_TOOLS.has(tool)) {
|
|
71
|
+
run = 0;
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (isError || !SINGLE_EDIT_TOOLS.has(tool))
|
|
75
|
+
return null;
|
|
76
|
+
run += 1;
|
|
77
|
+
if (run < SINGLE_EDIT_HINT_AT || (run - SINGLE_EDIT_HINT_AT) % SINGLE_EDIT_HINT_EVERY !== 0)
|
|
78
|
+
return null;
|
|
79
|
+
return `Tip: ${run} single scene edits in a row. More than 3 edits: write one summer_run_script instead (snapshot, script, diff, screenshot).`;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { type ZodTypeAny } from "zod";
|
|
3
|
+
import { type Profile, type Toolset } from "../core/tool-profiles.js";
|
|
4
|
+
/**
|
|
5
|
+
* The shape of the MCP tool surface: which toolset each tool belongs to, each
|
|
6
|
+
* local tool's annotations, which results are capped, and which calls count
|
|
7
|
+
* as single scene edits. Read by server.ts (registration, results) and, with
|
|
8
|
+
* the profiles in core/tool-profiles.ts, by hosted-mount.ts (which hosted
|
|
9
|
+
* tools a profile mounts).
|
|
10
|
+
*
|
|
11
|
+
* Tool names never change here: a profile only leaves tools out.
|
|
12
|
+
*/
|
|
13
|
+
export { TOOLSETS, PROFILES, PROFILE_TOOL_LIMIT, type Toolset, type Profile } from "../core/tool-profiles.js";
|
|
14
|
+
/** The toolset a tool belongs to: local tools by the table above, hosted ones by name. */
|
|
15
|
+
export declare function toolsetOf(name: string, local: boolean): Toolset;
|
|
16
|
+
export interface ToolSelection {
|
|
17
|
+
/** "custom" = toolsets given without a profile. */
|
|
18
|
+
profile: Profile | "custom";
|
|
19
|
+
/** null = every toolset (the full profile). */
|
|
20
|
+
toolsets: ReadonlySet<Toolset> | null;
|
|
21
|
+
/** Unknown names given in flags or env, for one warning line. */
|
|
22
|
+
ignored: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* `summer mcp --profile <p> --toolsets <a,b>` (env SUMMER_PROFILE,
|
|
26
|
+
* SUMMER_TOOLSETS). Without either: the full profile. `--toolsets` alone
|
|
27
|
+
* selects those toolsets plus core; with a profile it adds to it. `all` is
|
|
28
|
+
* every toolset. Unknown names are ignored and reported, never fatal: a
|
|
29
|
+
* typo must not stop an agent's MCP server from starting.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveToolSelection(options?: {
|
|
32
|
+
profile?: string;
|
|
33
|
+
toolsets?: string;
|
|
34
|
+
}, env?: NodeJS.ProcessEnv): ToolSelection;
|
|
35
|
+
/** True when the selection keeps this tool. */
|
|
36
|
+
export declare function selectionIncludes(selection: ToolSelection, name: string, local: boolean): boolean;
|
|
37
|
+
/** Every name the refinement sets mention (a test checks each is a real tool). */
|
|
38
|
+
export declare const ANNOTATION_REFINEMENTS: ReadonlySet<string>;
|
|
39
|
+
export type Authority = Partial<Record<"filesystem" | "editor_mutation" | "network" | "credentials" | "publish", boolean>>;
|
|
40
|
+
/** MCP annotations for one local tool from its registry authority. */
|
|
41
|
+
export declare function annotationsFor(name: string, authority: Authority): ToolAnnotations;
|
|
42
|
+
/** Registry authority per MCP tool name (registry/generated/index.json). */
|
|
43
|
+
export declare function registryAuthorities(): Map<string, Authority>;
|
|
44
|
+
/** Default text cap for tools whose results can be large. */
|
|
45
|
+
export declare const DEFAULT_MAX_CHARACTERS = 4000;
|
|
46
|
+
/**
|
|
47
|
+
* Tools whose text results are capped by default, with their default cap.
|
|
48
|
+
* Scene and runtime trees, console and debugger reads, inspect reads and
|
|
49
|
+
* library reads. The scene tree and library reads get more room: a median
|
|
50
|
+
* skill is about 12K characters, and cutting every skill read would double
|
|
51
|
+
* the core search-then-read loop. Writes, job ids and file reads are never
|
|
52
|
+
* capped.
|
|
53
|
+
*/
|
|
54
|
+
export declare const OUTPUT_CAPS: ReadonlyMap<string, number>;
|
|
55
|
+
/**
|
|
56
|
+
* A capped tool's input shape plus `maxCharacters`. server.ts adds it at
|
|
57
|
+
* registration and strips it before the handler runs; the descriptor parity
|
|
58
|
+
* test applies the same function, so library/tools/<slug>/resource.yaml
|
|
59
|
+
* lists the argument too.
|
|
60
|
+
*/
|
|
61
|
+
export declare function withMaxCharactersArg<T extends Record<string, ZodTypeAny>>(name: string, shape: T): T;
|
|
62
|
+
/** One-change scene tools; a run of them is one summer_run_script. */
|
|
63
|
+
export declare const SINGLE_EDIT_TOOLS: ReadonlySet<string>;
|
|
64
|
+
/** Calls that already batch edits; they end a run of single edits. */
|
|
65
|
+
export declare const BATCH_EDIT_TOOLS: ReadonlySet<string>;
|