summer-engine 3.8.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.
Files changed (485) hide show
  1. package/.claude-plugin/marketplace.json +2 -13
  2. package/.claude-plugin/plugin.json +23 -22
  3. package/.codex-plugin/plugin.json +4 -12
  4. package/.cursor-plugin/plugin.json +4 -12
  5. package/.factory-plugin/plugin.json +4 -12
  6. package/AGENTS.md +19 -12
  7. package/CHANGELOG.md +96 -0
  8. package/GEMINI.md +3 -3
  9. package/README.md +103 -33
  10. package/assets/icon.png +0 -0
  11. package/commands/start.md +71 -0
  12. package/commands/summer.md +3 -2
  13. package/dist/cli/banner.js +3 -0
  14. package/dist/cli/commands/login.d.ts +27 -0
  15. package/dist/cli/commands/login.js +58 -12
  16. package/dist/cli/commands/ops.d.ts +47 -0
  17. package/dist/cli/commands/ops.js +301 -0
  18. package/dist/cli/commands/setup.d.ts +2 -0
  19. package/dist/cli/commands/setup.js +37 -12
  20. package/dist/cli/commands/skills.js +11 -7
  21. package/dist/cli/index.js +7 -0
  22. package/dist/core/agent-host.d.ts +65 -0
  23. package/dist/core/agent-host.js +193 -0
  24. package/dist/core/capabilities/agent-playbook.d.ts +3 -0
  25. package/dist/core/capabilities/agent-playbook.js +54 -2
  26. package/dist/core/capabilities/apps.d.ts +25 -2
  27. package/dist/core/capabilities/apps.js +25 -12
  28. package/dist/core/capabilities/doctor.d.ts +3 -0
  29. package/dist/core/capabilities/doctor.js +20 -15
  30. package/dist/core/capabilities/fabricate-mesh.d.ts +2 -2
  31. package/dist/core/capabilities/game-task-plan.d.ts +12 -6
  32. package/dist/core/capabilities/game-task-plan.js +80 -5
  33. package/dist/core/capabilities/motion-generation.js +2 -2
  34. package/dist/core/capabilities/navigation/open.d.ts +6 -2
  35. package/dist/core/capabilities/navigation/open.js +3 -0
  36. package/dist/core/capabilities/publish-build.js +2 -0
  37. package/dist/core/capabilities/runtime-control.d.ts +4 -4
  38. package/dist/core/capabilities/scene-script-target.d.ts +17 -0
  39. package/dist/core/capabilities/scene-script-target.js +70 -0
  40. package/dist/core/capabilities/sfx-choices.d.ts +4 -0
  41. package/dist/core/capabilities/sfx-choices.js +13 -6
  42. package/dist/core/capabilities/tool-dispatch.d.ts +12 -3
  43. package/dist/core/capabilities/tool-dispatch.js +81 -46
  44. package/dist/core/embeddings.d.ts +2 -0
  45. package/dist/core/embeddings.js +1 -1
  46. package/dist/core/error-codes.d.ts +62 -0
  47. package/dist/core/error-codes.js +97 -0
  48. package/dist/core/format.d.ts +2 -0
  49. package/dist/core/format.js +2 -1
  50. package/dist/core/hosted-mcp.d.ts +22 -0
  51. package/dist/core/hosted-mcp.js +56 -1
  52. package/dist/core/library-read.js +5 -0
  53. package/dist/core/library-search.js +2 -1
  54. package/dist/core/oauth.js +4 -0
  55. package/dist/core/ops/catalog.d.ts +41 -0
  56. package/dist/core/ops/catalog.js +145 -0
  57. package/dist/core/ops/cloud.d.ts +56 -0
  58. package/dist/core/ops/cloud.js +175 -0
  59. package/dist/core/ops/contract.d.ts +119 -0
  60. package/dist/core/ops/contract.js +142 -0
  61. package/dist/core/ops/engine-answer.d.ts +25 -0
  62. package/dist/core/ops/engine-answer.js +117 -0
  63. package/dist/core/ops/engine.d.ts +55 -0
  64. package/dist/core/ops/engine.js +649 -0
  65. package/dist/core/ops/save-files.d.ts +78 -0
  66. package/dist/core/ops/save-files.js +419 -0
  67. package/dist/core/ops/search.d.ts +9 -0
  68. package/dist/core/ops/search.js +55 -0
  69. package/dist/core/skills-registry.d.ts +16 -1
  70. package/dist/core/skills-registry.js +35 -2
  71. package/dist/core/telemetry.d.ts +32 -0
  72. package/dist/core/telemetry.js +38 -10
  73. package/dist/core/tool-profiles.d.ts +25 -0
  74. package/dist/core/tool-profiles.js +41 -0
  75. package/dist/installer/agent-config.d.ts +17 -4
  76. package/dist/installer/agent-config.js +22 -6
  77. package/dist/installer/agent-table.d.ts +3 -0
  78. package/dist/installer/agent-table.js +10 -7
  79. package/dist/installer/setup.d.ts +2 -0
  80. package/dist/installer/setup.js +9 -4
  81. package/dist/installer/version-check.d.ts +29 -9
  82. package/dist/installer/version-check.js +81 -28
  83. package/dist/mcp/command.js +7 -0
  84. package/dist/mcp/hosted-mount.d.ts +27 -2
  85. package/dist/mcp/hosted-mount.js +53 -23
  86. package/dist/mcp/legacy-toolset.d.ts +27 -0
  87. package/dist/mcp/legacy-toolset.js +43 -0
  88. package/dist/mcp/ops-surface.d.ts +59 -0
  89. package/dist/mcp/ops-surface.js +443 -0
  90. package/dist/mcp/server.d.ts +35 -11
  91. package/dist/mcp/server.js +234 -89
  92. package/dist/mcp/tool-results.d.ts +26 -0
  93. package/dist/mcp/tool-results.js +81 -0
  94. package/dist/mcp/tool-surface.d.ts +65 -0
  95. package/dist/mcp/tool-surface.js +317 -0
  96. package/dist/mcp/tools/app-tools.js +9 -2
  97. package/dist/mcp/tools/asset-tools.js +55 -53
  98. package/dist/mcp/tools/audit-tools.js +21 -21
  99. package/dist/mcp/tools/debug-tools.js +6 -6
  100. package/dist/mcp/tools/fabricate-tools.js +6 -6
  101. package/dist/mcp/tools/generate-tools.js +76 -70
  102. package/dist/mcp/tools/project-tools.d.ts +9 -4
  103. package/dist/mcp/tools/project-tools.js +16 -10
  104. package/dist/mcp/tools/scene-tools.js +12 -23
  105. package/dist/mcp/tools/script-tools.js +9 -5
  106. package/dist/mcp/tools/with-engine.d.ts +6 -0
  107. package/dist/mcp/tools/with-engine.js +19 -0
  108. package/gemini-extension.json +4 -12
  109. package/hooks/pre-commit-doctor.sh +5 -4
  110. package/hooks/session-start.sh +24 -28
  111. package/integrations/claude-desktop/README.md +1 -1
  112. package/integrations/copilot-jetbrains/README.md +1 -1
  113. package/integrations/junie/README.md +1 -1
  114. package/integrations/lm-studio/README.md +1 -1
  115. package/integrations/trae/README.md +1 -1
  116. package/integrations/visual-studio/README.md +1 -1
  117. package/library/references/mcp-tools-reference/mcp-tools-reference.md +79 -51
  118. package/library/references/mcp-tools-reference/resource.yaml +1 -1
  119. package/library/references/product-map/resource.yaml +2 -2
  120. package/library/skills/3d-lighting/SKILL.md +53 -28
  121. package/library/skills/3d-lighting/resource.yaml +1 -1
  122. package/library/skills/README.md +119 -117
  123. package/library/skills/adaptive-music/SKILL.md +19 -23
  124. package/library/skills/adaptive-music/resource.yaml +1 -1
  125. package/library/skills/agent-playtesting/SKILL.md +1 -1
  126. package/library/skills/agent-playtesting/resource.yaml +1 -1
  127. package/library/skills/ai-characters-in-games/SKILL.md +1 -1
  128. package/library/skills/ai-characters-in-games/resource.yaml +1 -1
  129. package/library/skills/ambient-bed/SKILL.md +22 -13
  130. package/library/skills/ambient-bed/resource.yaml +1 -1
  131. package/library/skills/animated-loop/SKILL.md +41 -32
  132. package/library/skills/animated-loop/resource.yaml +1 -1
  133. package/library/skills/animation-tree/SKILL.md +1 -1
  134. package/library/skills/animation-tree/resource.yaml +1 -1
  135. package/library/skills/art-direction/SKILL.md +3 -3
  136. package/library/skills/art-direction/resource.yaml +1 -1
  137. package/library/skills/asset-strategy/SKILL.md +21 -4
  138. package/library/skills/asset-strategy/resource.yaml +2 -1
  139. package/library/skills/audio-direction/SKILL.md +10 -10
  140. package/library/skills/audio-direction/resource.yaml +1 -1
  141. package/library/skills/auto-fire-targeting/SKILL.md +1 -1
  142. package/library/skills/auto-fire-targeting/resource.yaml +1 -1
  143. package/library/skills/bounded-engine-runs/SKILL.md +1 -1
  144. package/library/skills/bounded-engine-runs/resource.yaml +1 -1
  145. package/library/skills/brainstorm-game/SKILL.md +1 -1
  146. package/library/skills/brainstorm-game/resource.yaml +1 -1
  147. package/library/skills/brainstorming/SKILL.md +1 -1
  148. package/library/skills/brainstorming/resource.yaml +1 -1
  149. package/library/skills/browse-templates/SKILL.md +1 -1
  150. package/library/skills/browse-templates/resource.yaml +1 -1
  151. package/library/skills/camera-rigs/SKILL.md +2 -2
  152. package/library/skills/camera-rigs/resource.yaml +1 -1
  153. package/library/skills/celeste-momentum-platforming/resource.yaml +1 -0
  154. package/library/skills/character-animation-wiring/SKILL.md +4 -4
  155. package/library/skills/character-animation-wiring/resource.yaml +1 -1
  156. package/library/skills/character-model/SKILL.md +55 -47
  157. package/library/skills/character-model/resource.yaml +1 -1
  158. package/library/skills/character-movement/SKILL.md +3 -3
  159. package/library/skills/character-movement/resource.yaml +1 -1
  160. package/library/skills/character-portrait/SKILL.md +24 -19
  161. package/library/skills/character-portrait/resource.yaml +1 -1
  162. package/library/skills/cinematic-cutscene/SKILL.md +58 -46
  163. package/library/skills/cinematic-cutscene/resource.yaml +1 -1
  164. package/library/skills/combat-basics/SKILL.md +1 -1
  165. package/library/skills/combat-basics/resource.yaml +1 -1
  166. package/library/skills/compatibility-renderer-traps/SKILL.md +1 -1
  167. package/library/skills/compatibility-renderer-traps/resource.yaml +1 -1
  168. package/library/skills/concept-art/SKILL.md +16 -12
  169. package/library/skills/concept-art/resource.yaml +1 -1
  170. package/library/skills/concept-to-level/SKILL.md +239 -0
  171. package/library/skills/concept-to-level/references/technical-rules.md +150 -0
  172. package/library/skills/concept-to-level/resource.yaml +44 -0
  173. package/library/skills/create-asset-sheet/SKILL.md +19 -13
  174. package/library/skills/create-asset-sheet/resource.yaml +1 -1
  175. package/library/skills/debug/SKILL.md +2 -2
  176. package/library/skills/debug/resource.yaml +1 -1
  177. package/library/skills/debugging-game-feel/SKILL.md +1 -1
  178. package/library/skills/debugging-game-feel/resource.yaml +1 -1
  179. package/library/skills/design-level/SKILL.md +23 -35
  180. package/library/skills/design-level/resource.yaml +1 -1
  181. package/library/skills/design-mechanic/SKILL.md +1 -1
  182. package/library/skills/design-mechanic/resource.yaml +1 -1
  183. package/library/skills/design-npc/SKILL.md +22 -24
  184. package/library/skills/design-npc/resource.yaml +1 -1
  185. package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
  186. package/library/skills/diagnosing-perf-regressions/resource.yaml +1 -1
  187. package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
  188. package/library/skills/driving-the-editor-ui/resource.yaml +1 -1
  189. package/library/skills/environment-kit/SKILL.md +20 -16
  190. package/library/skills/environment-kit/resource.yaml +1 -1
  191. package/library/skills/export-and-ship/SKILL.md +6 -6
  192. package/library/skills/export-and-ship/resource.yaml +1 -1
  193. package/library/skills/fabricating-assets/SKILL.md +7 -7
  194. package/library/skills/fabricating-assets/resource.yaml +3 -3
  195. package/library/skills/facial-and-lipsync/SKILL.md +14 -15
  196. package/library/skills/facial-and-lipsync/resource.yaml +1 -1
  197. package/library/skills/fps-controller/SKILL.md +33 -41
  198. package/library/skills/fps-controller/resource.yaml +1 -1
  199. package/library/skills/game-feel/SKILL.md +8 -8
  200. package/library/skills/game-feel/resource.yaml +1 -1
  201. package/library/skills/gameskill/SKILL.md +4 -4
  202. package/library/skills/gameskill/resource.yaml +1 -1
  203. package/library/skills/gdscript-patterns/SKILL.md +1 -1
  204. package/library/skills/gdscript-patterns/resource.yaml +1 -1
  205. package/library/skills/generate-motion/SKILL.md +30 -21
  206. package/library/skills/generate-motion/resource.yaml +1 -1
  207. package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
  208. package/library/skills/godogen-visual-proof-game-generation/resource.yaml +1 -0
  209. package/library/skills/grow-analytics/SKILL.md +3 -3
  210. package/library/skills/grow-analytics/resource.yaml +1 -1
  211. package/library/skills/headless-scripting/SKILL.md +1 -1
  212. package/library/skills/headless-scripting/resource.yaml +1 -1
  213. package/library/skills/in-game-purchases/SKILL.md +1 -1
  214. package/library/skills/in-game-purchases/resource.yaml +1 -1
  215. package/library/skills/instantiate-asset-pack/SKILL.md +2 -2
  216. package/library/skills/instantiate-asset-pack/resource.yaml +1 -1
  217. package/library/skills/lumera-single-image-scene-reconstruction/resource.yaml +1 -0
  218. package/library/skills/make-game/SKILL.md +4 -4
  219. package/library/skills/make-game/references/2d-platformer.md +1 -1
  220. package/library/skills/make-game/references/3d-fps.md +1 -1
  221. package/library/skills/make-game/references/3d-horror.md +1 -1
  222. package/library/skills/make-game/references/3d-third-person.md +2 -2
  223. package/library/skills/make-game/resource.yaml +1 -1
  224. package/library/skills/multiplayer/SKILL.md +1 -1
  225. package/library/skills/multiplayer/resource.yaml +1 -1
  226. package/library/skills/multiplayer-movement/SKILL.md +1 -1
  227. package/library/skills/multiplayer-movement/resource.yaml +1 -1
  228. package/library/skills/multiplayer-project/SKILL.md +1 -1
  229. package/library/skills/multiplayer-project/resource.yaml +1 -1
  230. package/library/skills/multiplayer-publish/SKILL.md +8 -7
  231. package/library/skills/multiplayer-publish/resource.yaml +3 -3
  232. package/library/skills/multiplayer-state/SKILL.md +1 -1
  233. package/library/skills/multiplayer-state/resource.yaml +1 -1
  234. package/library/skills/multiplayer-testing/SKILL.md +1 -1
  235. package/library/skills/multiplayer-testing/resource.yaml +1 -1
  236. package/library/skills/music-track/SKILL.md +22 -13
  237. package/library/skills/music-track/resource.yaml +1 -1
  238. package/library/skills/navigate-summer/SKILL.md +11 -9
  239. package/library/skills/navigate-summer/resource.yaml +1 -1
  240. package/library/skills/new-project/SKILL.md +1 -1
  241. package/library/skills/new-project/resource.yaml +1 -1
  242. package/library/skills/organic-model/SKILL.md +24 -18
  243. package/library/skills/organic-model/resource.yaml +1 -1
  244. package/library/skills/pixel-art/SKILL.md +27 -23
  245. package/library/skills/pixel-art/resource.yaml +1 -1
  246. package/library/skills/play/SKILL.md +1 -1
  247. package/library/skills/play/resource.yaml +1 -1
  248. package/library/skills/playtesting-a-feature/SKILL.md +1 -1
  249. package/library/skills/playtesting-a-feature/resource.yaml +1 -1
  250. package/library/skills/procedural-animation/SKILL.md +20 -16
  251. package/library/skills/procedural-animation/resource.yaml +1 -1
  252. package/library/skills/prop-model/SKILL.md +25 -19
  253. package/library/skills/prop-model/resource.yaml +1 -1
  254. package/library/skills/psx-retro-rendering/resource.yaml +1 -0
  255. package/library/skills/publish-your-game/SKILL.md +16 -6
  256. package/library/skills/publish-your-game/resource.yaml +3 -3
  257. package/library/skills/realtime-wet-surfaces/resource.yaml +1 -0
  258. package/library/skills/release-readiness/SKILL.md +1 -1
  259. package/library/skills/release-readiness/resource.yaml +1 -1
  260. package/library/skills/remote-deploy/SKILL.md +1 -1
  261. package/library/skills/remote-deploy/resource.yaml +1 -1
  262. package/library/skills/retarget/SKILL.md +23 -20
  263. package/library/skills/retarget/resource.yaml +1 -1
  264. package/library/skills/running-in-the-cloud/SKILL.md +1 -1
  265. package/library/skills/running-in-the-cloud/resource.yaml +1 -1
  266. package/library/skills/save-load/SKILL.md +1 -1
  267. package/library/skills/save-load/resource.yaml +1 -1
  268. package/library/skills/scene-composition/SKILL.md +1 -1
  269. package/library/skills/scene-composition/resource.yaml +1 -1
  270. package/library/skills/scene-hierarchy-design/SKILL.md +2 -2
  271. package/library/skills/scene-hierarchy-design/resource.yaml +1 -1
  272. package/library/skills/scene-scripting/SKILL.md +66 -636
  273. package/library/skills/scene-scripting/references/ctx-api.md +184 -0
  274. package/library/skills/scene-scripting/references/recipes-2d-ui.md +193 -0
  275. package/library/skills/scene-scripting/references/recipes-3d.md +280 -0
  276. package/library/skills/scene-scripting/resource.yaml +4 -4
  277. package/library/skills/scene-to-level/SKILL.md +2 -2
  278. package/library/skills/scene-to-level/resource.yaml +1 -1
  279. package/library/skills/skill-create/resource.yaml +1 -0
  280. package/library/skills/skill-improve/resource.yaml +1 -0
  281. package/library/skills/skill-test/SKILL.md +2 -2
  282. package/library/skills/skill-test/resource.yaml +1 -0
  283. package/library/skills/skintokens-auto-rigging/resource.yaml +1 -0
  284. package/library/skills/skybox-panorama/SKILL.md +27 -21
  285. package/library/skills/skybox-panorama/resource.yaml +1 -1
  286. package/library/skills/sound-effect/SKILL.md +29 -20
  287. package/library/skills/sound-effect/resource.yaml +1 -1
  288. package/library/skills/spatial-placement/SKILL.md +14 -9
  289. package/library/skills/spatial-placement/resource.yaml +1 -1
  290. package/library/skills/sprite-sheet/SKILL.md +32 -27
  291. package/library/skills/sprite-sheet/resource.yaml +1 -1
  292. package/library/skills/store-art/SKILL.md +3 -3
  293. package/library/skills/store-art/resource.yaml +2 -2
  294. package/library/skills/store-listing/SKILL.md +3 -3
  295. package/library/skills/store-listing/resource.yaml +2 -2
  296. package/library/skills/summer-analytics/SKILL.md +7 -5
  297. package/library/skills/summer-analytics/resource.yaml +2 -2
  298. package/library/skills/summer-apps/SKILL.md +48 -32
  299. package/library/skills/summer-apps/manifest.md +1 -1
  300. package/library/skills/summer-apps/minimal-app.md +7 -7
  301. package/library/skills/summer-apps/resource.yaml +1 -1
  302. package/library/skills/summer-apps/sdk-reference.md +5 -5
  303. package/library/skills/summer-apps-design/SKILL.md +1 -1
  304. package/library/skills/summer-apps-design/resource.yaml +1 -1
  305. package/library/skills/summer-assets/SKILL.md +56 -0
  306. package/library/skills/summer-assets/resource.yaml +34 -0
  307. package/library/skills/summer-store/SKILL.md +1 -1
  308. package/library/skills/text-to-motion/SKILL.md +30 -23
  309. package/library/skills/text-to-motion/prompts-and-controls.md +5 -5
  310. package/library/skills/text-to-motion/resource.yaml +1 -1
  311. package/library/skills/text-to-motion/rigging-for-text-motion.md +2 -2
  312. package/library/skills/tileable-texture/SKILL.md +19 -15
  313. package/library/skills/tileable-texture/resource.yaml +1 -1
  314. package/library/skills/trailer-shot/SKILL.md +28 -24
  315. package/library/skills/trailer-shot/resource.yaml +1 -1
  316. package/library/skills/tune-performance/SKILL.md +6 -6
  317. package/library/skills/tune-performance/resource.yaml +1 -1
  318. package/library/skills/ui-basics/SKILL.md +41 -36
  319. package/library/skills/ui-basics/resource.yaml +1 -1
  320. package/library/skills/ui-graphics/SKILL.md +47 -38
  321. package/library/skills/ui-graphics/resource.yaml +1 -1
  322. package/library/skills/use-widget-asset/SKILL.md +1 -1
  323. package/library/skills/use-widget-asset/resource.yaml +1 -1
  324. package/library/skills/using-summer/SKILL.md +6 -5
  325. package/library/skills/using-summer/resource.yaml +1 -1
  326. package/library/skills/vehicle-model/SKILL.md +65 -57
  327. package/library/skills/vehicle-model/resource.yaml +1 -1
  328. package/library/skills/verification-before-completion/SKILL.md +1 -1
  329. package/library/skills/verification-before-completion/resource.yaml +1 -1
  330. package/library/skills/verifying-scenes/SKILL.md +2 -2
  331. package/library/skills/verifying-scenes/resource.yaml +1 -1
  332. package/library/skills/vfx-dissolve/SKILL.md +2 -2
  333. package/library/skills/vfx-dissolve/resource.yaml +1 -1
  334. package/library/skills/vfx-fire/SKILL.md +15 -41
  335. package/library/skills/vfx-fire/resource.yaml +1 -1
  336. package/library/skills/vfx-hit-spark/SKILL.md +1 -1
  337. package/library/skills/vfx-hit-spark/resource.yaml +1 -1
  338. package/library/skills/vfx-lightning/SKILL.md +7 -16
  339. package/library/skills/vfx-lightning/resource.yaml +1 -1
  340. package/library/skills/vfx-magic-glow/SKILL.md +23 -32
  341. package/library/skills/vfx-magic-glow/resource.yaml +1 -1
  342. package/library/skills/vfx-muzzle-flash/SKILL.md +20 -35
  343. package/library/skills/vfx-muzzle-flash/resource.yaml +1 -1
  344. package/library/skills/vfx-smoke/SKILL.md +13 -31
  345. package/library/skills/vfx-smoke/resource.yaml +1 -1
  346. package/library/skills/vfx-water-ripple/SKILL.md +12 -31
  347. package/library/skills/vfx-water-ripple/resource.yaml +1 -1
  348. package/library/skills/voice-line/SKILL.md +71 -40
  349. package/library/skills/voice-line/resource.yaml +1 -1
  350. package/library/skills/web-and-touch-input/SKILL.md +1 -1
  351. package/library/skills/web-and-touch-input/resource.yaml +1 -1
  352. package/library/skills/web-compatibility-look/SKILL.md +1 -1
  353. package/library/skills/web-compatibility-look/resource.yaml +1 -1
  354. package/library/skills/world-building-3d/SKILL.md +1 -1
  355. package/library/skills/world-building-3d/resource.yaml +1 -1
  356. package/library/skills/writing-skills/resource.yaml +1 -0
  357. package/library/tools/add-node/GUIDE.md +14 -0
  358. package/library/tools/align-distribute-3d/GUIDE.md +7 -0
  359. package/library/tools/app-call/resource.yaml +1 -1
  360. package/library/tools/app-guide/resource.yaml +2 -2
  361. package/library/tools/app-page/resource.yaml +1 -1
  362. package/library/tools/app-screenshot/resource.yaml +19 -1
  363. package/library/tools/app-tools/resource.yaml +1 -1
  364. package/library/tools/attach-to-surface/GUIDE.md +15 -0
  365. package/library/tools/batch/GUIDE.md +27 -0
  366. package/library/tools/camera-bookmark/GUIDE.md +12 -0
  367. package/library/tools/capture-gameplay/GUIDE.md +3 -0
  368. package/library/tools/capture-gameplay/resource.yaml +3 -3
  369. package/library/tools/check-job/resource.yaml +1 -1
  370. package/library/tools/clear-console/GUIDE.md +3 -0
  371. package/library/tools/connect-ports/GUIDE.md +9 -0
  372. package/library/tools/connect-signal/GUIDE.md +14 -0
  373. package/library/tools/create-debug-report/GUIDE.md +10 -0
  374. package/library/tools/create-scene/GUIDE.md +10 -0
  375. package/library/tools/debug-views/GUIDE.md +7 -0
  376. package/library/tools/enable-plugin/GUIDE.md +3 -0
  377. package/library/tools/export-game/GUIDE.md +3 -0
  378. package/library/tools/export-game/resource.yaml +3 -3
  379. package/library/tools/export-templates/GUIDE.md +3 -0
  380. package/library/tools/fabricate-3d/GUIDE.md +19 -0
  381. package/library/tools/frame-nodes/GUIDE.md +9 -0
  382. package/library/tools/frame-shot/GUIDE.md +9 -0
  383. package/library/tools/game-control/GUIDE.md +9 -0
  384. package/library/tools/game-input/GUIDE.md +9 -0
  385. package/library/tools/game-probe/GUIDE.md +9 -0
  386. package/library/tools/generate-3d/resource.yaml +3 -3
  387. package/library/tools/generate-motion/resource.yaml +2 -2
  388. package/library/tools/get-console/GUIDE.md +9 -0
  389. package/library/tools/get-console/resource.yaml +5 -0
  390. package/library/tools/get-debugger-errors/GUIDE.md +7 -0
  391. package/library/tools/get-debugger-errors/resource.yaml +5 -0
  392. package/library/tools/get-debugger-warnings/GUIDE.md +7 -0
  393. package/library/tools/get-debugger-warnings/resource.yaml +5 -0
  394. package/library/tools/get-diagnostics/GUIDE.md +13 -0
  395. package/library/tools/get-project-context/GUIDE.md +25 -0
  396. package/library/tools/get-runtime-tree/GUIDE.md +7 -0
  397. package/library/tools/get-runtime-tree/resource.yaml +5 -0
  398. package/library/tools/get-scene-tree/GUIDE.md +11 -0
  399. package/library/tools/get-scene-tree/resource.yaml +5 -0
  400. package/library/tools/get-script-errors/GUIDE.md +5 -0
  401. package/library/tools/grep/GUIDE.md +11 -0
  402. package/library/tools/import-asset/GUIDE.md +8 -0
  403. package/library/tools/import-asset-by-id/GUIDE.md +12 -0
  404. package/library/tools/import-from-url/GUIDE.md +10 -0
  405. package/library/tools/import-from-url-batch/GUIDE.md +3 -0
  406. package/library/tools/import-hdri/GUIDE.md +16 -0
  407. package/library/tools/input-map-bind/GUIDE.md +11 -0
  408. package/library/tools/inspect-asset/GUIDE.md +14 -0
  409. package/library/tools/inspect-asset/resource.yaml +5 -0
  410. package/library/tools/inspect-node/GUIDE.md +11 -0
  411. package/library/tools/inspect-node/resource.yaml +5 -0
  412. package/library/tools/inspect-resource/GUIDE.md +7 -0
  413. package/library/tools/inspect-resource/resource.yaml +5 -0
  414. package/library/tools/inspect-runtime-node/GUIDE.md +7 -0
  415. package/library/tools/inspect-runtime-node/resource.yaml +5 -0
  416. package/library/tools/instantiate-scene/GUIDE.md +12 -0
  417. package/library/tools/is-running/GUIDE.md +3 -0
  418. package/library/tools/measure/GUIDE.md +8 -0
  419. package/library/tools/navigation-probe/GUIDE.md +9 -0
  420. package/library/tools/open/resource.yaml +2 -2
  421. package/library/tools/open-main-scene/GUIDE.md +6 -0
  422. package/library/tools/open-scene/GUIDE.md +8 -0
  423. package/library/tools/place-adjacent/GUIDE.md +7 -0
  424. package/library/tools/play/GUIDE.md +13 -0
  425. package/library/tools/project-setting/GUIDE.md +9 -0
  426. package/library/tools/publish-build/resource.yaml +6 -6
  427. package/library/tools/raycast/GUIDE.md +7 -0
  428. package/library/tools/read-file/GUIDE.md +10 -0
  429. package/library/tools/read-library/resource.yaml +5 -0
  430. package/library/tools/recent-events/GUIDE.md +7 -0
  431. package/library/tools/remove-node/GUIDE.md +3 -0
  432. package/library/tools/repeat-along/GUIDE.md +5 -0
  433. package/library/tools/replace-node/GUIDE.md +9 -0
  434. package/library/tools/replace-text/GUIDE.md +5 -0
  435. package/library/tools/run-editor-script/GUIDE.md +16 -0
  436. package/library/tools/run-script/GUIDE.md +30 -0
  437. package/library/tools/run-script/resource.yaml +6 -3
  438. package/library/tools/runtime-animate/GUIDE.md +7 -0
  439. package/library/tools/runtime-call/GUIDE.md +7 -0
  440. package/library/tools/runtime-set/GUIDE.md +9 -0
  441. package/library/tools/runtime-spawn/GUIDE.md +9 -0
  442. package/library/tools/save-scene/GUIDE.md +3 -0
  443. package/library/tools/scene-audit/GUIDE.md +29 -0
  444. package/library/tools/screenshot/GUIDE.md +17 -0
  445. package/library/tools/select-node/GUIDE.md +3 -0
  446. package/library/tools/set-prop/GUIDE.md +23 -0
  447. package/library/tools/set-resource-property/GUIDE.md +8 -0
  448. package/library/tools/shot-sheet/GUIDE.md +7 -0
  449. package/library/tools/snap-to-surface/GUIDE.md +17 -0
  450. package/library/tools/snapshot-diff/GUIDE.md +7 -0
  451. package/library/tools/starcast/GUIDE.md +12 -0
  452. package/library/tools/stop/GUIDE.md +3 -0
  453. package/library/tools/test-placement/GUIDE.md +7 -0
  454. package/library/tools/ui-actions/GUIDE.md +12 -0
  455. package/library/tools/ui-activate/GUIDE.md +11 -0
  456. package/library/tools/ui-screenshot/GUIDE.md +9 -0
  457. package/library/tools/ui-tree/GUIDE.md +10 -0
  458. package/library/tools/wait-for-event/GUIDE.md +11 -0
  459. package/library/tools/world-snapshot/GUIDE.md +9 -0
  460. package/library/tools/write-file/GUIDE.md +5 -0
  461. package/library/tools/zoom/GUIDE.md +5 -0
  462. package/package.json +6 -4
  463. package/registry/generated/counts.json +2 -2
  464. package/registry/generated/gemini-extension.json +4 -12
  465. package/registry/generated/index.json +433 -339
  466. package/registry/generated/marketplace.claude.json +2 -13
  467. package/registry/generated/plugin.claude.json +23 -22
  468. package/registry/generated/plugin.codex.json +4 -12
  469. package/registry/generated/plugin.cursor.json +4 -12
  470. package/registry/generated/plugin.factory.json +4 -12
  471. package/registry/generated/server.json +34 -0
  472. package/registry/generated/skills-index.md +119 -117
  473. package/registry/generated/skills-registry.json +153 -115
  474. package/registry/operations/fixtures/invalid-deprecated-without-replacement.json +60 -0
  475. package/registry/operations/fixtures/invalid-name.json +60 -0
  476. package/registry/operations/fixtures/invalid-publish-without-owner.json +82 -0
  477. package/registry/operations/fixtures/invalid-spend-without-estimate.json +42 -0
  478. package/registry/operations/fixtures/invalid-unknown-field.json +61 -0
  479. package/registry/operations/fixtures/valid-player-facing.json +82 -0
  480. package/registry/operations/fixtures/valid-read.json +60 -0
  481. package/registry/operations/fixtures/valid-spend.json +43 -0
  482. package/registry/operations/legacy-names.json +1206 -0
  483. package/registry/schemas/operation.schema.json +318 -0
  484. package/registry/schemas/skill.schema.json +4 -0
  485. package/CLAUDE.md +0 -7
@@ -27,29 +27,49 @@ import { registerNavigationTools } from "./tools/navigation-tools.js";
27
27
  import { registerLibraryTools } from "./tools/library-tools.js";
28
28
  import { getCachedBootDriftNotice as getCachedNotice, setCachedBootDriftNotice, } from "./boot-notice.js";
29
29
  import { appendMcpLogEvent } from "../core/mcp-log.js";
30
- 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";
31
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";
32
41
  import { buildBootDriftNotice, fetchLatestRegistryVersion, } from "../installer/version-check.js";
33
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";
34
46
  let processDiagnosticsInstalled = false;
47
+ const FULL_SELECTION = { profile: "full", toolsets: null, ignored: [] };
35
48
  export const getCachedBootDriftNotice = getCachedNotice;
36
49
  /**
37
50
  * Server `instructions` in the MCP initialize response (SDK ServerOptions,
38
51
  * @modelcontextprotocol/sdk >= 1.x). Hosts hand this to the model once per
39
- * session, before any tool call — the place for the five habits an end-to-end run
40
- * showed an agent needs on the first
41
- * turn and would otherwise learn the hard way. Kept under 600 characters so
42
- * it costs a few hundred tokens once; the full operating guide stays in the
43
- * summer_agent_playbook prompt / summer_get_agent_playbook tool. The last
44
- * sentence names the publishing path, the owner-approval rule and where
45
- * 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.
46
59
  */
47
- export const SUMMER_MCP_INSTRUCTIONS = "Summer Engine MCP. Call summer_get_project_context first: it binds the open project, returns mainScene, projectMemory, any capabilitySkewWarning. " +
48
- "Before building or fixing, summer_search_library then summer_read_library the hit. " +
49
- "After play, read summer_get_diagnostics, not summer_get_console alone. " +
50
- "An all-black screenshot means no redraw yet: recapture. " +
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. " +
51
65
  "Report verified entries via summer_library_feedback. " +
52
- "Publishing: summer_export_game, summer_publish_build, summer_store_*; agents never publish alone: summer_store_submit returns the owner's approval link; summer_store_review, feedback to fix.";
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.";
53
73
  /**
54
74
  * Fire-and-forget probe of the npm registry on MCP boot. Caches the result for
55
75
  * the session. We never await this in startup so a slow / offline registry
@@ -103,26 +123,20 @@ export async function getClient() {
103
123
  const reason = error instanceof Error
104
124
  ? error.message
105
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;
106
132
  throw new Error(reason + "\n" +
107
- "Open the intended project in Summer Engine, or run: npx -y summer-engine@latest run\n" +
108
- "Note: only tools that touch the local project need the engine. Cloud tools " +
109
- "(summer_generate_*, summer_search_assets, summer_list_my_assets, summer_get_asset, " +
110
- "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);
111
135
  }
112
136
  }
113
137
  export function resetClient() {
114
138
  cachedClient = null;
115
139
  }
116
- /**
117
- * Passive result-size observability. Monkey-patches server.tool() so every
118
- * registered handler's serialized text payload is measured and logged to
119
- * stderr in the existing `[summer-mcp]` JSON shape. The result itself is
120
- * never modified — external coding agents (Claude Code, Cursor, Codex)
121
- * manage their own context budgets, and silently truncating their tool
122
- * results is the wrong shape (see #102 revert). If a specific tool turns
123
- * out to produce pathological payloads in practice, the right fix is
124
- * adding range/depth/filter parameters to that tool — not a blanket cap.
125
- */
126
140
  function errorDetails(error) {
127
141
  if (error instanceof Error) {
128
142
  return {
@@ -170,74 +184,115 @@ function installMcpProcessDiagnostics() {
170
184
  appendMcpLogEvent("mcp:exit", { pid: process.pid, code });
171
185
  });
172
186
  }
173
- function installResultSizeLogger(server) {
174
- const original = server.tool.bind(server);
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;
175
204
  let registeredToolCount = 0;
176
- server.tool = function patchedTool(...args) {
177
- if (args.length < 2)
178
- return original(...args);
179
- const name = args[0];
205
+ target.tool = function patchedTool(...registration) {
206
+ if (registration.length < 2)
207
+ return original(...registration);
208
+ const name = registration[0];
180
209
  if (typeof name !== "string")
181
- return original(...args);
182
- const lastIdx = args.length - 1;
183
- const handler = args[lastIdx];
210
+ return original(...registration);
211
+ const lastIdx = registration.length - 1;
212
+ const handler = registration[lastIdx];
184
213
  if (typeof handler !== "function")
185
- return original(...args);
214
+ return original(...registration);
186
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]);
187
221
  // Schema-less tools receive only the SDK's `extra` — never record that as
188
222
  // the tool's arguments (see registrationHasInputSchema).
189
223
  const hasInputSchema = registrationHasInputSchema(args);
190
- const wrapped = async (...handlerArgs) => {
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
+ }
191
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
+ };
192
240
  let result;
193
241
  try {
194
- result = await handler(...handlerArgs);
242
+ // Every Summer request the tool makes names it (core/agent-host.ts).
243
+ result = await runWithToolContext(name, "mcp", () => handler(...handlerArgs));
195
244
  }
196
245
  catch (error) {
197
246
  // A handler THROW never produced a result to classify; record it as
198
247
  // ok:false / exception so the stream does not silently skip failures,
199
248
  // then let the SDK turn it into the protocol error it always did.
249
+ const durationMs = Date.now() - startedAt;
200
250
  recordToolCall({
201
251
  tool: name,
202
252
  args: trajectoryArgsFor(hasInputSchema, handlerArgs),
203
253
  exception: error instanceof Error ? error.message : String(error),
204
- durationMs: Date.now() - startedAt,
254
+ durationMs,
205
255
  });
256
+ recordUsage(false, durationMs);
206
257
  throw error;
207
258
  }
208
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;
209
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);
210
276
  // Opt-in local trajectory capture: one JSONL line per tool call when
211
277
  // SUMMER_TRAJECTORY_DIR is set. recordToolCall never throws and is a
212
278
  // no-op when the env var is unset.
213
- {
214
- const record = result;
215
- const callMeta = record && typeof record === "object"
216
- ? record[WITH_ENGINE_META]
217
- : undefined;
218
- recordToolCall({
219
- tool: name,
220
- args: trajectoryArgsFor(hasInputSchema, handlerArgs),
221
- isError: record?.isError === true,
222
- terminalState: callMeta?.terminalState,
223
- errorClass: callMeta?.errorClass,
224
- failureReason: callMeta?.failureReason,
225
- durationMs,
226
- // Read only under SUMMER_TRAJECTORY_EVAL=1 (bounded summary); the
227
- // default redacted stream ignores it.
228
- result,
229
- });
230
- }
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
+ });
231
291
  if (result &&
232
292
  typeof result === "object" &&
233
293
  "content" in result &&
234
294
  Array.isArray(result.content)) {
235
295
  const debug = process.env.SUMMER_MCP_DEBUG === "1";
236
- const isError = result.isError === true;
237
- // withEngine stamps failure classifiers + retried + bound hash on a
238
- // non-enumerable symbol so we can log them here without every tool
239
- // threading its own name through withEngine.
240
- const meta = result[WITH_ENGINE_META];
241
296
  // Structured per-call line. Verbose behind SUMMER_MCP_DEBUG=1; when the
242
297
  // flag is off, log ONLY failures — the success path stays quiet.
243
298
  if (debug || isError) {
@@ -258,17 +313,11 @@ function installResultSizeLogger(server) {
258
313
  process.stderr.write(`[summer-mcp] ${callLine}\n`);
259
314
  }
260
315
  if (debug) {
261
- let chars = 0;
262
- for (const entry of result
263
- .content) {
264
- if (entry && entry.type === "text" && typeof entry.text === "string") {
265
- chars += entry.text.length;
266
- }
267
- }
268
- const bytes = Buffer.byteLength(result.content
316
+ const texts = result.content
269
317
  .filter((e) => e && e.type === "text" && typeof e.text === "string")
270
- .map((e) => e.text)
271
- .join(""), "utf8");
318
+ .map((e) => e.text);
319
+ const chars = texts.reduce((sum, text) => sum + text.length, 0);
320
+ const bytes = Buffer.byteLength(texts.join(""), "utf8");
272
321
  const line = JSON.stringify({
273
322
  event: "mcp:result_size",
274
323
  tool_name: name,
@@ -289,31 +338,44 @@ function installResultSizeLogger(server) {
289
338
  }
290
339
  return result;
291
340
  };
292
- const newArgs = [...args];
293
- newArgs[lastIdx] = wrapped;
294
- return original(...newArgs);
341
+ return original(...args);
295
342
  };
296
343
  return () => registeredToolCount;
297
344
  }
298
345
  /**
299
- * Build the MCP server with every Summer tool registered, without connecting
300
- * a transport. startMcpServer() uses this; tests use it to count the live
301
- * tool surface against registry/generated/counts.json.
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.
302
350
  */
303
- export function createMcpServer() {
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");
304
362
  const server = new McpServer({
305
363
  name: "summer-engine",
306
364
  version,
307
- }, { instructions: SUMMER_MCP_INSTRUCTIONS });
308
- // Passive observability: log result-size to stderr but do not modify
309
- // results. See installResultSizeLogger above.
310
- const getRegisteredToolCount = installResultSizeLogger(server);
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());
311
373
  registerSceneTools(server);
312
374
  registerDebugTools(server);
313
375
  registerVisualTools(server);
314
376
  registerSeeingTools(server);
315
377
  registerAuditTools(server);
316
- registerProjectTools(server);
378
+ registerProjectTools(server, { engine });
317
379
  registerFileTools(server);
318
380
  registerAssetTools(server);
319
381
  registerGenerateTools(server);
@@ -332,10 +394,37 @@ export function createMcpServer() {
332
394
  registerAppTools(server);
333
395
  // The playbook is also an MCP prompt so prompt-surfacing hosts get it
334
396
  // natively (same content as the summer_get_agent_playbook tool).
335
- registerPlaybookPrompt(server);
397
+ registerPlaybookPrompt(server, { engine });
336
398
  // Strict providers (Kimi, OpenAI strict) reject tuple and $ref schemas.
337
399
  serveProviderSafeToolSchemas(server);
338
- return { server, getRegisteredToolCount };
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;
339
428
  }
340
429
  export async function startMcpServer(options = {}) {
341
430
  configureMcpEngineSelection({
@@ -355,7 +444,22 @@ export async function startMcpServer(options = {}) {
355
444
  cwd: options.cwd ?? process.cwd(),
356
445
  },
357
446
  });
358
- const { server, getRegisteredToolCount } = createMcpServer();
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 });
359
463
  // Fire-and-forget — never block tool registration on the npm registry.
360
464
  void probeBootDrift().catch((error) => {
361
465
  setCachedBootDriftNotice(null);
@@ -364,13 +468,54 @@ export async function startMcpServer(options = {}) {
364
468
  // Hosted Summer Engine MCP tools (store, publishing, board, Grow): ready
365
469
  // before connect, mounted after it. The first tools/list waits a few
366
470
  // seconds for the mount (not under summer doctor, which times the list).
367
- const hosted = prepareHostedMount(server, undefined, process.env.SUMMER_MCP_DOCTOR === "1" ? { firstListWaitMs: 0 } : {});
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;
368
509
  const transport = new StdioServerTransport();
369
510
  await server.connect(transport);
370
511
  void hosted.mount();
512
+ void legacyHosted?.mount();
371
513
  appendMcpLogEvent("mcp:ready", {
372
514
  version,
373
515
  pid: process.pid,
516
+ profile: selection.profile,
517
+ surface,
518
+ ...(surface === "v4" ? { legacy: legacy.reason } : {}),
374
519
  toolCount: getRegisteredToolCount(),
375
520
  });
376
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>;