summer-engine 4.5.0 → 4.8.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 +1 -1
- package/.claude-plugin/plugin.json +3 -2
- package/.codex-plugin/plugin.json +5 -4
- package/.cursor-plugin/plugin.json +4 -3
- package/.factory-plugin/plugin.json +4 -3
- package/CHANGELOG.md +50 -0
- package/README.md +3 -3
- package/commands/start.md +1 -1
- package/dist/cli/commands/api.d.ts +43 -0
- package/dist/cli/commands/api.js +191 -0
- package/dist/cli/commands/login.d.ts +2 -5
- package/dist/cli/commands/login.js +10 -81
- package/dist/cli/commands/setup.js +175 -32
- package/dist/cli/commands/token.d.ts +17 -0
- package/dist/cli/commands/token.js +25 -0
- package/dist/cli/index.js +4 -0
- package/dist/core/api-client.d.ts +5 -1
- package/dist/core/api-client.js +21 -0
- package/dist/core/capabilities/doctor.d.ts +1 -1
- package/dist/core/capabilities/doctor.js +1 -1
- package/dist/core/capabilities/game-task-plan.d.ts +2 -2
- package/dist/core/capabilities/navigation/open.d.ts +3 -0
- package/dist/core/capabilities/navigation/open.js +53 -0
- package/dist/core/capabilities/projects-local.js +2 -1
- package/dist/core/capabilities/runtime-control.d.ts +2 -2
- package/dist/core/capabilities/seeing/args.d.ts +4 -4
- package/dist/core/capabilities/tool-dispatch.js +37 -0
- package/dist/core/capabilities/ui-control.d.ts +2 -2
- package/dist/core/capabilities/view-set.d.ts +11 -0
- package/dist/core/capabilities/view-set.js +15 -0
- package/dist/core/capability-skew.d.ts +8 -0
- package/dist/core/capability-skew.js +18 -0
- package/dist/core/cli-session.d.ts +25 -0
- package/dist/core/cli-session.js +97 -0
- package/dist/core/engine-self-start.d.ts +20 -0
- package/dist/core/engine-self-start.js +108 -5
- package/dist/core/oauth.d.ts +15 -2
- package/dist/core/oauth.js +26 -3
- package/dist/core/ops/areas.d.ts +1 -1
- package/dist/core/ops/areas.js +5 -3
- package/dist/core/ops/engine-answer.js +5 -2
- package/dist/core/ops/engine.js +6 -0
- package/dist/core/ops/save-files.d.ts +2 -0
- package/dist/core/ops/save-files.js +13 -0
- package/dist/core/ops/studio-page.d.ts +22 -0
- package/dist/core/ops/studio-page.js +63 -0
- package/dist/core/sign-in-link.d.ts +38 -0
- package/dist/core/sign-in-link.js +106 -0
- package/dist/core/store.js +19 -1
- package/dist/core/summer-api.d.ts +114 -0
- package/dist/core/summer-api.js +281 -0
- package/dist/installer/agent-config.d.ts +29 -0
- package/dist/installer/agent-config.js +75 -11
- package/dist/installer/agent-detect.d.ts +44 -0
- package/dist/installer/agent-detect.js +166 -0
- package/dist/installer/agent-table.d.ts +19 -0
- package/dist/installer/agent-table.js +130 -0
- package/dist/installer/setup-error.d.ts +19 -0
- package/dist/installer/setup-error.js +34 -0
- package/dist/installer/version-check.d.ts +5 -0
- package/dist/installer/version-check.js +21 -0
- package/dist/mcp/ops-surface.d.ts +10 -0
- package/dist/mcp/ops-surface.js +18 -1
- package/dist/mcp/server.js +16 -4
- package/dist/mcp/tool-results.d.ts +9 -0
- package/dist/mcp/tool-results.js +64 -0
- package/dist/mcp/tool-surface.js +7 -1
- package/dist/mcp/tools/api-tools.d.ts +50 -0
- package/dist/mcp/tools/api-tools.js +65 -0
- package/dist/mcp/tools/local-project-tools.d.ts +14 -0
- package/dist/mcp/tools/local-project-tools.js +13 -2
- package/dist/mcp/tools/navigation-tools.js +1 -0
- package/dist/mcp/tools/scene-tools.js +7 -0
- package/dist/project-memory/agent-instructions.js +11 -3
- package/gemini-extension.json +3 -2
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +15 -2
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/skills/README.md +6 -5
- package/library/skills/design-npc/SKILL.md +1 -1
- package/library/skills/design-npc/resource.yaml +2 -1
- package/library/skills/make-game/SKILL.md +4 -4
- package/library/skills/navigate-summer/SKILL.md +23 -2
- package/library/skills/navigate-summer/resource.yaml +5 -3
- package/library/skills/summer-api/SKILL.md +198 -0
- package/library/skills/summer-api/resource.yaml +38 -0
- package/library/skills/summer-assets/SKILL.md +1 -1
- package/library/skills/summer-assets/resource.yaml +3 -2
- package/library/skills/summer-router/SKILL.md +251 -0
- package/library/skills/summer-router/resource.yaml +35 -0
- package/library/tools/api-batch/resource.yaml +82 -0
- package/library/tools/api-estimate/resource.yaml +52 -0
- package/library/tools/api-job/resource.yaml +58 -0
- package/library/tools/api-models/resource.yaml +57 -0
- package/library/tools/api-run/resource.yaml +70 -0
- package/library/tools/view-set/GUIDE.md +3 -0
- package/library/tools/view-set/resource.yaml +78 -0
- package/package.json +3 -3
- package/registry/generated/aliases.json +7 -0
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +3 -2
- package/registry/generated/index.json +317 -52
- package/registry/generated/marketplace.claude.json +1 -1
- package/registry/generated/plugin.claude-directory.json +4 -3
- package/registry/generated/plugin.claude.json +3 -2
- package/registry/generated/plugin.codex.json +5 -4
- package/registry/generated/plugin.cursor.json +4 -3
- package/registry/generated/plugin.factory.json +4 -3
- package/registry/generated/server.json +2 -2
- package/registry/generated/skills-index.md +6 -5
- package/registry/generated/skills-registry.json +29 -15
- package/registry/operations/legacy-names.json +30 -0
- package/registry/operations/public-catalog.json +9169 -4926
- package/library/skills/ai-characters-in-games/SKILL.md +0 -235
- package/library/skills/ai-characters-in-games/resource.yaml +0 -30
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { type ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { type Answer } from "../core/ops/contract.js";
|
|
3
4
|
import { type FileSaver } from "../core/ops/save-files.js";
|
|
4
5
|
import type { HostedLocalHook } from "./hosted-mount.js";
|
|
5
6
|
/**
|
|
@@ -23,6 +24,13 @@ import type { HostedLocalHook } from "./hosted-mount.js";
|
|
|
23
24
|
*/
|
|
24
25
|
export declare const SUMMER_SEARCH = "summer_search";
|
|
25
26
|
export declare const SUMMER_CALL = "summer_call";
|
|
27
|
+
/**
|
|
28
|
+
* The first-game look rule. It opens the engine instructions because clients
|
|
29
|
+
* keep only the start of long server instructions (Codex: the first 512
|
|
30
|
+
* characters), and a project's first frame decides whether the person keeps
|
|
31
|
+
* going. The same rule is in the AGENTS.md block (project-memory/agent-instructions.ts).
|
|
32
|
+
*/
|
|
33
|
+
export declare const FIRST_GAME_LOOK_RULE: string;
|
|
26
34
|
export declare const OPS_MCP_INSTRUCTIONS: string;
|
|
27
35
|
/** The assets profile's version: no engine tools, so it names none. */
|
|
28
36
|
export declare const OPS_MCP_ASSETS_INSTRUCTIONS: string;
|
|
@@ -38,6 +46,8 @@ export interface OpsSurfaceOptions {
|
|
|
38
46
|
legacy?: boolean;
|
|
39
47
|
/** Saves generated files on this machine (`out`, localPath); shared with the mounted hosted tools. */
|
|
40
48
|
files: FileSaver;
|
|
49
|
+
/** A Studio page op in the running app's own Studio tab (core/ops/studio-page.ts); null sends it to Summer's server. */
|
|
50
|
+
studio?: (op: string, input: Record<string, unknown>) => Promise<Answer | null>;
|
|
41
51
|
}
|
|
42
52
|
/** Its v4 description, within the 300-character summary rule; the full text stays on the 3.x surface. */
|
|
43
53
|
export declare const ENGINE_REFERENCE_SUMMARY = "Look up an engine class offline before writing script code: inherits, properties, methods, signals and constants, or one member. Lists only members declared on that class (walk inherits). No engine needed. Next: summer_run_script.";
|
package/dist/mcp/ops-surface.js
CHANGED
|
@@ -29,7 +29,18 @@ import { FOOTER_SUFFIX } from "../core/library-read.js";
|
|
|
29
29
|
*/
|
|
30
30
|
export const SUMMER_SEARCH = "summer_search";
|
|
31
31
|
export const SUMMER_CALL = "summer_call";
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
|
+
* The first-game look rule. It opens the engine instructions because clients
|
|
34
|
+
* keep only the start of long server instructions (Codex: the first 512
|
|
35
|
+
* characters), and a project's first frame decides whether the person keeps
|
|
36
|
+
* going. The same rule is in the AGENTS.md block (project-memory/agent-instructions.ts).
|
|
37
|
+
*/
|
|
38
|
+
export const FIRST_GAME_LOOK_RULE = "First game in a new project: make it look finished, even if they asked for a quick prototype, because the first frame decides if they keep going. " +
|
|
39
|
+
"Keep their features and raise the look: sky and sun with shadows, fog, a texture on every surface, real models for player, characters and props (starter project and summer_assets_search first, never capsules or boxes as final art), one palette, a styled UI font. " +
|
|
40
|
+
"Before you say it is ready, play it and check a screenshot of the running game.";
|
|
41
|
+
export const OPS_MCP_INSTRUCTIONS = "Summer Engine MCP. " +
|
|
42
|
+
FIRST_GAME_LOOK_RULE +
|
|
43
|
+
" Write GDScript files directly; create scenes and import assets through Summer while the project is open. summer_get_project_context tells you which project you are connected to. " +
|
|
33
44
|
"Listed tools are the common jobs; for anything else, summer_search describes the job in words and returns the operation and its exact input, then summer_call runs it. " +
|
|
34
45
|
"More than 3 scene edits: one summer_run_script with scenePath. Each engine tool's full guide: summer_docs_read. Long work answers with a job: jobs.wait. " +
|
|
35
46
|
"Going live: skill/release-checklist, then store.go_live with the person's yes; a game is live once Summer's automated checks pass, so never tell anyone to wait for a review. Prices and other live changes may answer needs_approval with a link: give it to the person. " +
|
|
@@ -409,6 +420,12 @@ export function applyOpsSurface(server, options) {
|
|
|
409
420
|
return toolResult(errorAnswer("not_in_profile", `${resolved} is not served by this profile.`, { next: { say: "Run the MCP with --profile engine." } }));
|
|
410
421
|
return toolResult(await runLocal(resolved, call, extra, dryRun === true, args));
|
|
411
422
|
}
|
|
423
|
+
// The running Summer app answers its own Studio tab's ops itself; else Summer's server does.
|
|
424
|
+
if (options.studio && dryRun !== true) {
|
|
425
|
+
const inApp = await options.studio(resolved, args);
|
|
426
|
+
if (inApp)
|
|
427
|
+
return toolResult(inApp);
|
|
428
|
+
}
|
|
412
429
|
// `out` stays here: this package saves the files (core/ops/save-files.ts).
|
|
413
430
|
const { input: sent, out } = options.files.take(resolved, args);
|
|
414
431
|
let raw;
|
package/dist/mcp/server.js
CHANGED
|
@@ -24,6 +24,7 @@ import { registerAssetTools } from "./tools/asset-tools.js";
|
|
|
24
24
|
import { registerGenerateTools } from "./tools/generate-tools.js";
|
|
25
25
|
import { registerCreatorTools } from "./tools/creator-tools.js";
|
|
26
26
|
import { registerFeedbackTools } from "./tools/feedback-tools.js";
|
|
27
|
+
import { registerApiTools } from "./tools/api-tools.js";
|
|
27
28
|
import { registerNavigationTools } from "./tools/navigation-tools.js";
|
|
28
29
|
import { registerLibraryTools } from "./tools/library-tools.js";
|
|
29
30
|
import { getCachedBootDriftNotice as getCachedNotice, setCachedBootDriftNotice, } from "./boot-notice.js";
|
|
@@ -31,6 +32,7 @@ import { appendMcpLogEvent } from "../core/mcp-log.js";
|
|
|
31
32
|
import { defaultHostedMountDependencies, prepareHostedMount } from "./hosted-mount.js";
|
|
32
33
|
import { applyOpsSurface, hostedFileTools, OPS_MCP_ASSETS_INSTRUCTIONS, OPS_MCP_INSTRUCTIONS, SUMMER_CALL, SUMMER_SEARCH } from "./ops-surface.js";
|
|
33
34
|
import { FileSaver } from "../core/ops/save-files.js";
|
|
35
|
+
import { runInAppStudio } from "../core/ops/studio-page.js";
|
|
34
36
|
import { opForToolCall } from "../core/ops/contract.js";
|
|
35
37
|
import { knownOp } from "../core/ops/catalog.js";
|
|
36
38
|
import { v4HostedUrl } from "../core/ops/cloud.js";
|
|
@@ -38,7 +40,8 @@ import { serveProviderSafeToolSchemas } from "./provider-safe-schema.js";
|
|
|
38
40
|
import { legacyHostedDescription, resolveLegacy, takeLegacyToolset } from "./legacy-toolset.js";
|
|
39
41
|
import { refreshInstalledSkills, refreshNotice } from "../installer/skills-refresh.js";
|
|
40
42
|
import { OUTPUT_CAPS, PROFILE_TOOL_LIMIT, PROFILES, TOOLSETS, annotationsFor, registryAuthorities, resolveToolSelection, selectionIncludes, withMaxCharactersArg, } from "./tool-surface.js";
|
|
41
|
-
import { shapeToolResult, singleEditCounter } from "./tool-results.js";
|
|
43
|
+
import { shapeToolResult, singleEditCounter, withSignInLink } from "./tool-results.js";
|
|
44
|
+
import { SignInLinks } from "../core/sign-in-link.js";
|
|
42
45
|
import { recordLocalToolCall, recordMcpSession, toolErrorCode } from "../core/telemetry.js";
|
|
43
46
|
import { boundProject } from "../core/usage-fields.js";
|
|
44
47
|
import { currentToolContext, registerMcpClientSource, runWithToolContext } from "../core/agent-host.js";
|
|
@@ -224,7 +227,7 @@ function rawShapeIndex(args) {
|
|
|
224
227
|
}
|
|
225
228
|
return -1;
|
|
226
229
|
}
|
|
227
|
-
function installToolCallWrapper(server, surfaceMeta) {
|
|
230
|
+
function installToolCallWrapper(server, surfaceMeta, signInLinks = new SignInLinks()) {
|
|
228
231
|
const target = server;
|
|
229
232
|
const original = target.tool.bind(server);
|
|
230
233
|
const singleEdits = singleEditCounter();
|
|
@@ -305,6 +308,11 @@ function installToolCallWrapper(server, surfaceMeta) {
|
|
|
305
308
|
catch {
|
|
306
309
|
// Shaping must never break the tool call; the raw result goes out.
|
|
307
310
|
}
|
|
311
|
+
if (isError && !nested) {
|
|
312
|
+
// A cloud tool that needs a sign-in answers with a link the agent can
|
|
313
|
+
// show; the sign-in it starts turns the tool on without a restart.
|
|
314
|
+
result = await withSignInLink(result, toolErrorCode(result, meta?.failureReason ?? meta?.errorClass), signInLinks);
|
|
315
|
+
}
|
|
308
316
|
try {
|
|
309
317
|
recordMcpSession();
|
|
310
318
|
recordUsage(!isError, durationMs, isError ? toolErrorCode(result, meta?.failureReason ?? meta?.errorClass) : null);
|
|
@@ -418,6 +426,7 @@ export function createMcpServer(selection = FULL_SELECTION, options = {}) {
|
|
|
418
426
|
registerGenerateTools(server);
|
|
419
427
|
registerCreatorTools(server);
|
|
420
428
|
registerFeedbackTools(server);
|
|
429
|
+
registerApiTools(server);
|
|
421
430
|
registerScriptTools(server);
|
|
422
431
|
registerPerceptionTools(server);
|
|
423
432
|
registerSpatialTools(server);
|
|
@@ -451,8 +460,11 @@ export function createMcpServer(selection = FULL_SELECTION, options = {}) {
|
|
|
451
460
|
}
|
|
452
461
|
// Without engine tools nothing imports a file into a project, so files save into it by default.
|
|
453
462
|
const files = new FileSaver({ saveByDefault: !engine });
|
|
454
|
-
if (surface === "v4")
|
|
455
|
-
|
|
463
|
+
if (surface === "v4") {
|
|
464
|
+
// Studio page ops go to the running app's own Studio tab when it offers them (no engine launch).
|
|
465
|
+
const studio = (op, input) => runInAppStudio(op, input, () => getClient({ launch: false }));
|
|
466
|
+
applyOpsSurface(server, { engine, cloud: options.cloud ?? NO_CLOUD, legacy: options.legacy === true, files, studio });
|
|
467
|
+
}
|
|
456
468
|
return { server, getRegisteredToolCount: () => getWrappedToolCount() - removed, files };
|
|
457
469
|
}
|
|
458
470
|
/** What the hosted tools a profile mounts are, for summer_store_tools. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SignInKind } from "../core/sign-in-link.js";
|
|
1
2
|
type Content = {
|
|
2
3
|
type?: string;
|
|
3
4
|
text?: unknown;
|
|
@@ -23,4 +24,12 @@ export declare const SINGLE_EDIT_HINT_AT = 4;
|
|
|
23
24
|
* then every 6th.
|
|
24
25
|
*/
|
|
25
26
|
export declare function singleEditCounter(): (tool: string, isError: boolean) => string | null;
|
|
27
|
+
/**
|
|
28
|
+
* A `not_signed_in` / `store_login_required` answer gets one more text block:
|
|
29
|
+
* the sign-in link for the person (core/sign-in-link.ts). Anything else, or
|
|
30
|
+
* no link, leaves the result as it is. Never throws.
|
|
31
|
+
*/
|
|
32
|
+
export declare function withSignInLink(result: unknown, code: string | null, links: {
|
|
33
|
+
link: (kind: SignInKind) => Promise<string | null>;
|
|
34
|
+
}): Promise<unknown>;
|
|
26
35
|
export {};
|
package/dist/mcp/tool-results.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BATCH_EDIT_TOOLS, SINGLE_EDIT_TOOLS } from "./tool-surface.js";
|
|
2
|
+
import { signInKindForCode, signInLinkText } from "../core/sign-in-link.js";
|
|
2
3
|
/** Pretty-printed JSON text as compact JSON; anything else unchanged. */
|
|
3
4
|
export function compactJsonText(text) {
|
|
4
5
|
const first = text[0];
|
|
@@ -79,3 +80,66 @@ export function singleEditCounter() {
|
|
|
79
80
|
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
|
};
|
|
81
82
|
}
|
|
83
|
+
/** The store sign-ins a v4 answer names in error.details.was (core/ops/cloud.ts hostedCallFailure). */
|
|
84
|
+
const STORE_SIGN_IN_WAS = new Set(["store_login_required", "store_login_expired"]);
|
|
85
|
+
/**
|
|
86
|
+
* A v4 cloud answer `not_signed_in` whose cause is the store sign-in (the
|
|
87
|
+
* hosted server's OAuth grant), not the Summer account: the Summer app, for
|
|
88
|
+
* one, is signed in to the account, so only the store approval link helps.
|
|
89
|
+
*/
|
|
90
|
+
function storeSignInAnswer(result) {
|
|
91
|
+
const first = result.content[0];
|
|
92
|
+
if (!first || first.type !== "text" || typeof first.text !== "string")
|
|
93
|
+
return false;
|
|
94
|
+
try {
|
|
95
|
+
const parsed = JSON.parse(first.text);
|
|
96
|
+
const error = parsed?.error;
|
|
97
|
+
return error?.code === "not_signed_in" && typeof error.details?.was === "string" && STORE_SIGN_IN_WAS.has(error.details.was);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* A `not_signed_in` / `store_login_required` answer gets one more text block:
|
|
105
|
+
* the sign-in link for the person (core/sign-in-link.ts). Anything else, or
|
|
106
|
+
* no link, leaves the result as it is. Never throws.
|
|
107
|
+
*/
|
|
108
|
+
export async function withSignInLink(result, code, links) {
|
|
109
|
+
if (!result || typeof result !== "object" || !Array.isArray(result.content))
|
|
110
|
+
return result;
|
|
111
|
+
const kind = storeSignInAnswer(result) ? "store" : signInKindForCode(code);
|
|
112
|
+
if (!kind)
|
|
113
|
+
return result;
|
|
114
|
+
try {
|
|
115
|
+
const url = await links.link(kind);
|
|
116
|
+
if (!url)
|
|
117
|
+
return result;
|
|
118
|
+
const original = result;
|
|
119
|
+
const text = signInLinkText(kind, url);
|
|
120
|
+
// A JSON answer gets the link inside it (signInUrl, and recovery says what
|
|
121
|
+
// to do), so a caller that parses it (the v4 operation layer runs 3.x
|
|
122
|
+
// tools and reads their JSON) keeps the code and passes the link on.
|
|
123
|
+
const first = original.content[0];
|
|
124
|
+
if (first && first.type === "text" && typeof first.text === "string") {
|
|
125
|
+
try {
|
|
126
|
+
const parsed = JSON.parse(first.text);
|
|
127
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
128
|
+
const answer = parsed;
|
|
129
|
+
const nested = answer.error && typeof answer.error === "object" ? answer.error : null;
|
|
130
|
+
const target = nested && typeof nested.code === "string" ? nested : answer;
|
|
131
|
+
target.signInUrl = url;
|
|
132
|
+
target.recovery = text;
|
|
133
|
+
return { ...original, content: [{ ...first, text: JSON.stringify(answer) }, ...original.content.slice(1)] };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// plain text: the link goes in its own block below
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return { ...original, content: [...original.content, { type: "text", text }] };
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
}
|
package/dist/mcp/tool-surface.js
CHANGED
|
@@ -37,10 +37,14 @@ const LOCAL_TOOLSETS = {
|
|
|
37
37
|
"summer_get_asset_download_url",
|
|
38
38
|
],
|
|
39
39
|
ship: ["summer_export_game", "summer_export_templates", "summer_publish_build", "summer_go_live", "summer_store_set_details", "summer_capture_gameplay"],
|
|
40
|
-
|
|
40
|
+
// summer_view_set is in the catalog (engine.view_set, summer_call) for every profile.
|
|
41
|
+
ui: ["summer_ui_actions", "summer_ui_activate", "summer_ui_screenshot", "summer_ui_tree", "summer_view_set"],
|
|
41
42
|
// Create and open a project on this computer with no shell (the full profile;
|
|
42
43
|
// the engine profile's clients have a shell, `summer dev`, and a tool cap).
|
|
43
44
|
projects: ["summer_projects_create_local", "summer_projects_open_local"],
|
|
45
|
+
// The Summer API (the assets and full profiles; the engine profile's clients
|
|
46
|
+
// have a shell, `summer login` and `summer api`, and a tool cap).
|
|
47
|
+
tools: ["summer_api_models", "summer_api_estimate", "summer_api_run", "summer_api_batch", "summer_api_job"],
|
|
44
48
|
};
|
|
45
49
|
const localToolset = new Map(Object.entries(LOCAL_TOOLSETS).flatMap(([set, names]) => names.map((name) => [name, set])));
|
|
46
50
|
/** Hosted tool names by pattern, first match wins. Unknown names land in `other` (full only). */
|
|
@@ -185,6 +189,7 @@ const ADDITIVE_OR_TRANSIENT = new Set([
|
|
|
185
189
|
"summer_open_scene",
|
|
186
190
|
"summer_open_main_scene",
|
|
187
191
|
"summer_select_node",
|
|
192
|
+
"summer_view_set",
|
|
188
193
|
"summer_clear_console",
|
|
189
194
|
"summer_play",
|
|
190
195
|
"summer_stop",
|
|
@@ -208,6 +213,7 @@ const IDEMPOTENT_WRITES = new Set([
|
|
|
208
213
|
"summer_open_scene",
|
|
209
214
|
"summer_open_main_scene",
|
|
210
215
|
"summer_select_node",
|
|
216
|
+
"summer_view_set",
|
|
211
217
|
"summer_clear_console",
|
|
212
218
|
"summer_stop",
|
|
213
219
|
"summer_enable_plugin",
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* summer_api_models, summer_api_estimate, summer_api_run, summer_api_batch,
|
|
3
|
+
* summer_api_job — the Summer API (core/summer-api.ts), the same calls as
|
|
4
|
+
* `summer api models|estimate|run|run --batch|jobs`. MCP adapter only: schemas and descriptions here.
|
|
5
|
+
* Runs and jobs use the Summer sign-in on this computer (summer login: Supabase OAuth, refreshed by itself).
|
|
6
|
+
*/
|
|
7
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
export declare const apiModelsInputShape: {
|
|
10
|
+
model: z.ZodOptional<z.ZodString>;
|
|
11
|
+
capability: z.ZodOptional<z.ZodEnum<["image", "3d", "video", "voice", "dialogue", "sound", "music"]>>;
|
|
12
|
+
};
|
|
13
|
+
export declare const apiEstimateInputShape: {
|
|
14
|
+
model: z.ZodString;
|
|
15
|
+
input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
16
|
+
};
|
|
17
|
+
export declare const apiRunInputShape: {
|
|
18
|
+
model: z.ZodString;
|
|
19
|
+
input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
20
|
+
quoteId: z.ZodOptional<z.ZodString>;
|
|
21
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
22
|
+
wait: z.ZodOptional<z.ZodBoolean>;
|
|
23
|
+
out: z.ZodOptional<z.ZodString>;
|
|
24
|
+
};
|
|
25
|
+
export declare const apiBatchInputShape: {
|
|
26
|
+
jobs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
27
|
+
model: z.ZodString;
|
|
28
|
+
input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
29
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
30
|
+
}, "strip", z.ZodTypeAny, {
|
|
31
|
+
model: string;
|
|
32
|
+
input?: Record<string, unknown> | undefined;
|
|
33
|
+
idempotencyKey?: string | undefined;
|
|
34
|
+
}, {
|
|
35
|
+
model: string;
|
|
36
|
+
input?: Record<string, unknown> | undefined;
|
|
37
|
+
idempotencyKey?: string | undefined;
|
|
38
|
+
}>, "many">>;
|
|
39
|
+
batchId: z.ZodOptional<z.ZodString>;
|
|
40
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
41
|
+
wait: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
out: z.ZodOptional<z.ZodString>;
|
|
43
|
+
};
|
|
44
|
+
export declare const apiJobInputShape: {
|
|
45
|
+
jobId: z.ZodString;
|
|
46
|
+
wait: z.ZodOptional<z.ZodBoolean>;
|
|
47
|
+
out: z.ZodOptional<z.ZodString>;
|
|
48
|
+
cancel: z.ZodOptional<z.ZodBoolean>;
|
|
49
|
+
};
|
|
50
|
+
export declare function registerApiTools(server: McpServer): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { batchToolResult, cancelJob, checkBatch, createBatch, estimateJob, getBatch, getJob, jobToolResult, listModels, runJob, summerApiToolAnswer, } from "../../core/summer-api.js";
|
|
3
|
+
import { textJson } from "./text-json.js";
|
|
4
|
+
const modelId = z.string().min(1).max(120).describe("A Summer API model id or alias from summer_api_models, e.g. 3d/default.");
|
|
5
|
+
const modelInput = z.record(z.string(), z.unknown()).optional().describe("The model's input, matching its inputSchema from summer_api_models.");
|
|
6
|
+
const out = z.string().min(1).optional().describe("A folder on this computer: save the finished job's files there (implies wait).");
|
|
7
|
+
export const apiModelsInputShape = {
|
|
8
|
+
model: modelId.optional().describe("One model id or alias; without it, every model."),
|
|
9
|
+
capability: z.enum(["image", "3d", "video", "voice", "dialogue", "sound", "music"]).optional().describe("Only this kind."),
|
|
10
|
+
};
|
|
11
|
+
export const apiEstimateInputShape = { model: modelId, input: modelInput };
|
|
12
|
+
export const apiRunInputShape = {
|
|
13
|
+
model: modelId,
|
|
14
|
+
input: modelInput,
|
|
15
|
+
quoteId: z.string().min(1).max(600).optional().describe("From summer_api_estimate: refuse to charge more than it quoted."),
|
|
16
|
+
idempotencyKey: z.string().min(1).max(200).optional().describe("Reuse to retry the same run without running it twice."),
|
|
17
|
+
wait: z.boolean().optional().describe("Follow the job until it finishes (up to about a minute in this call)."),
|
|
18
|
+
out,
|
|
19
|
+
};
|
|
20
|
+
export const apiBatchInputShape = {
|
|
21
|
+
jobs: z
|
|
22
|
+
.array(z.object({
|
|
23
|
+
model: modelId,
|
|
24
|
+
input: modelInput,
|
|
25
|
+
idempotencyKey: z.string().min(1).max(200).optional().describe("This job's own key; by default the batch key and the job's position."),
|
|
26
|
+
}))
|
|
27
|
+
.min(1)
|
|
28
|
+
.max(500)
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Up to 500 jobs, all or none. Leave out with batchId."),
|
|
31
|
+
batchId: z.string().min(1).max(200).optional().describe("Read a batch summer_api_batch answered, instead of starting one."),
|
|
32
|
+
idempotencyKey: z.string().min(1).max(200).optional().describe("Reuse to retry the same batch without queuing it twice."),
|
|
33
|
+
wait: z.boolean().optional().describe("Follow every job until it finishes (up to about a minute in this call)."),
|
|
34
|
+
out,
|
|
35
|
+
};
|
|
36
|
+
export const apiJobInputShape = {
|
|
37
|
+
jobId: z.string().min(1).max(200).describe("The job id summer_api_run answered."),
|
|
38
|
+
wait: z.boolean().optional().describe("Follow the job until it finishes (up to about a minute in this call)."),
|
|
39
|
+
out,
|
|
40
|
+
cancel: z.boolean().optional().describe("Ask to stop the job instead. Summer API jobs, queued or running, run to the end: the answer is unsupported."),
|
|
41
|
+
};
|
|
42
|
+
const answer = async (work) => {
|
|
43
|
+
const result = await summerApiToolAnswer(work);
|
|
44
|
+
return textJson(result, result.ok === false);
|
|
45
|
+
};
|
|
46
|
+
export function registerApiTools(server) {
|
|
47
|
+
server.tool("summer_api_models", "The Summer API's curated game-dev models: id, capability, input schema, output formats, typical time and price in USD. No sign-in needed. Next: summer_api_estimate for one exact request.", apiModelsInputShape, async (args) => answer(() => listModels(args)));
|
|
48
|
+
server.tool("summer_api_estimate", "The exact USD price of one Summer API job before it runs, what makes it up, and a quoteId that holds the price for 15 minutes. Charges nothing; no sign-in needed. Next: summer_api_run with the quoteId.", apiEstimateInputShape, async (args) => answer(() => estimateJob(args.model, args.input ?? {})));
|
|
49
|
+
server.tool("summer_api_run", "Run one Summer API job into the person's Summer assets with the Summer sign-in on this computer (the person runs summer login first). Spends their paid credits within this app's limit (Connected apps): say what you will make and estimate it first. Short jobs come back done; past the account's running slots a job answers queued at a held price and starts in order. wait follows it, out saves its files on this computer. no_credits (the paid balance) or over_limit (this app's limit): show the person the message and its link.", apiRunInputShape, async (args) => answer(async () => {
|
|
50
|
+
const follow = args.wait === true || typeof args.out === "string";
|
|
51
|
+
const job = await runJob(args.model, args.input ?? {}, {
|
|
52
|
+
...(args.quoteId ? { quoteId: args.quoteId } : {}),
|
|
53
|
+
...(args.idempotencyKey ? { idempotencyKey: args.idempotencyKey } : {}),
|
|
54
|
+
...(follow ? { waitSeconds: 30 } : {}),
|
|
55
|
+
});
|
|
56
|
+
return jobToolResult(job, args);
|
|
57
|
+
}));
|
|
58
|
+
server.tool("summer_api_batch", "Run up to 500 Summer API jobs at once with the Summer sign-in on this computer, all or none: when the person's paid credits and this app's limit (Connected apps) cover every job, all are queued at their held prices and run in order; if not, nothing runs and the error (no_credits or over_limit) says how many fit and how much more is needed (show the person its link). Say what you will make and what it costs first. batchId reads a batch; wait follows it, out saves the finished files on this computer.", apiBatchInputShape, async (args) => answer(async () => {
|
|
59
|
+
if (args.batchId)
|
|
60
|
+
return batchToolResult(await getBatch(args.batchId), args);
|
|
61
|
+
const batch = await createBatch(checkBatch(args.jobs ?? []), args.idempotencyKey ? { idempotencyKey: args.idempotencyKey } : {});
|
|
62
|
+
return batchToolResult(batch, args);
|
|
63
|
+
}));
|
|
64
|
+
server.tool("summer_api_job", "Read a Summer API job: its state (queued, running, done, failed, ...), price and, when done, its assets and Summer file URLs. wait follows it, out saves its files on this computer.", apiJobInputShape, async (args) => answer(async () => (args.cancel ? { job: await cancelJob(args.jobId) } : jobToolResult(await getJob(args.jobId), args))));
|
|
65
|
+
}
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/** The tool call's progress line (notifications/progress), when the client asked for progress. */
|
|
3
|
+
export declare function progressReporter(extra: {
|
|
4
|
+
_meta?: {
|
|
5
|
+
progressToken?: string | number;
|
|
6
|
+
};
|
|
7
|
+
sendNotification?: (notification: {
|
|
8
|
+
method: "notifications/progress";
|
|
9
|
+
params: {
|
|
10
|
+
progressToken: string | number;
|
|
11
|
+
progress: number;
|
|
12
|
+
message?: string;
|
|
13
|
+
};
|
|
14
|
+
}) => Promise<void>;
|
|
15
|
+
} | undefined): ((message: string) => void) | undefined;
|
|
2
16
|
/**
|
|
3
17
|
* projects.create_local and projects.open_local: what `summer dev` does, for
|
|
4
18
|
* agents with no shell (core/capabilities/projects-local.ts).
|
|
@@ -16,6 +16,17 @@ async function localProjectResult(operation) {
|
|
|
16
16
|
throw error;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
/** The tool call's progress line (notifications/progress), when the client asked for progress. */
|
|
20
|
+
export function progressReporter(extra) {
|
|
21
|
+
const token = extra?._meta?.progressToken;
|
|
22
|
+
const send = extra?.sendNotification;
|
|
23
|
+
if (token === undefined || !send)
|
|
24
|
+
return undefined;
|
|
25
|
+
let step = 0;
|
|
26
|
+
return (message) => {
|
|
27
|
+
void send({ method: "notifications/progress", params: { progressToken: token, progress: ++step, message } }).catch(() => undefined);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
19
30
|
/**
|
|
20
31
|
* projects.create_local and projects.open_local: what `summer dev` does, for
|
|
21
32
|
* agents with no shell (core/capabilities/projects-local.ts).
|
|
@@ -26,8 +37,8 @@ export function registerLocalProjectTools(server) {
|
|
|
26
37
|
name: z.string().max(80).optional().describe("The project's name and folder name. Default my-game (or the template's name)."),
|
|
27
38
|
dir: z.string().max(1000).optional().describe("The project folder: a new or empty folder, not inside another project; ~ is home. Default <name> next to the session's project, in the session's folder, or in ~/Documents/Summer."),
|
|
28
39
|
}, async (args) => localProjectResult(() => createLocalProject(args, currentMcpEngineSelection()?.cwd)));
|
|
29
|
-
server.tool("summer_projects_open_local", "Open a project on this computer in Summer Engine, in the background, and wait until it connects (an editor that has it open is used as it is); this session's engine tools then work on it. When Summer Engine is not installed it answers engine_not_running: ask the person, and only with their yes call again with install: true (about 660 MB, free). A first open can take a few minutes: the answer says to call again. It adds summer-preview to the session folder's .claude/launch.json (Claude Code Desktop's Browser pane), and preview.url is where the game shows. Next: summer_get_project_context.", {
|
|
40
|
+
server.tool("summer_projects_open_local", "Open a project on this computer in Summer Engine, in the background, and wait until it connects (an editor that has it open is used as it is; an editor with another project open switches to it in the same window); this session's engine tools then work on it. When Summer Engine is not installed it answers engine_not_running: ask the person, and only with their yes call again with install: true (about 660 MB, free). A first open can take a few minutes: the answer says to call again. It adds summer-preview to the session folder's .claude/launch.json (Claude Code Desktop's Browser pane), and preview.url is where the game shows. Next: summer_get_project_context.", {
|
|
30
41
|
path: z.string().max(1000).optional().describe("The project folder (holds project.godot), e.g. projectPath from summer_projects_create_local. Default this session's project."),
|
|
31
42
|
install: z.boolean().default(false).describe("Install Summer Engine first when it is missing. Set true only after the person said yes."),
|
|
32
|
-
}, async (args) => localProjectResult(() => openLocalProject(args, currentMcpEngineSelection(), { log: logEngineSelfStart }, (root, client) => bindMcpProject(root, client))));
|
|
43
|
+
}, async (args, extra) => localProjectResult(() => openLocalProject(args, currentMcpEngineSelection(), { log: logEngineSelfStart, progress: progressReporter(extra) }, (root, client) => bindMcpProject(root, client))));
|
|
33
44
|
}
|
|
@@ -18,6 +18,7 @@ params: slot values — gameId + section (builds, releases, store-page, analytic
|
|
|
18
18
|
open: false resolves only and returns url (+ login_url when the page needs login) or op; nothing opens, no engine needed.
|
|
19
19
|
|
|
20
20
|
Result: { ok, action: opened | printed | listed | ambiguous | unsupported | engine_not_running | engine_error | not_found | invalid_params | open_failed | blocked_origin, target (with availability for editor ids), url, login_url, logged_in, opened_url, op, engine, failure_reason, matches, hint }.
|
|
21
|
+
- Studio pages (/studio...) open in the Summer app's own Studio tab when the running engine advertises the studio destination (op Navigate target studio; result hint says so); otherwise in the browser.
|
|
21
22
|
- Web targets that require login open through /login?returnUrl=<path> when this machine holds no Summer login token (logged_in:false) — the destination loads after sign-in.
|
|
22
23
|
- Editor targets need Summer Engine running with the project open; otherwise action engine_not_running with the op that would have been sent and a 'summer run' hint. Nothing was opened.
|
|
23
24
|
- Editor destinations are forwarded to the engine's own navigation table (op Navigate; ids advertised in /api/health capabilities.navigation). On an engine that predates it, scene/node/script/file and the three docks still work through their original ops; anything else answers action unsupported with failure_reason engine_lacks_op and an update hint. Never claim those opened. Listing (no target) shows each editor id's availability from the connected engine.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { viewSetOp } from "../../core/capabilities/view-set.js";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { withEngine, ToolInputError } from "./with-engine.js";
|
|
3
4
|
import { executeSceneMutation } from "../../core/capabilities/engine-ops.js";
|
|
@@ -245,6 +246,12 @@ PERSISTENCE IS VERIFIED: the engine's ConnectSignal op connects without CONNECT_
|
|
|
245
246
|
op.scenePath = scenePath;
|
|
246
247
|
return client.executeOps([op]);
|
|
247
248
|
}));
|
|
249
|
+
server.tool("summer_view_set", "Show the person what you are working on: the editor's view (home, chat, 3d, 2d, script, game, studio), its right rail (files, scene, inspector, output, none), what to focus (a res:// script or scene, or a node path) and the nodes to frame the camera on. Changes only what is on screen. The navigate-summer skill says which view fits which moment.", {
|
|
250
|
+
view: z.enum(["home", "chat", "3d", "2d", "script", "game", "studio"]).describe("The view to show"),
|
|
251
|
+
rail: z.enum(["files", "scene", "inspector", "output", "none"]).optional().describe("The right rail; none hides it"),
|
|
252
|
+
focus: z.string().optional().describe("A res:// script or scene, or a node path"),
|
|
253
|
+
frame: z.array(z.string()).optional().describe("Node paths to frame the camera on"),
|
|
254
|
+
}, async ({ view, rail, focus, frame }) => withEngine(async (client) => client.executeOps([viewSetOp({ view, rail, focus, frame })])));
|
|
248
255
|
server.tool("summer_replace_node", `Replace a node with a different scene/model or node type, keeping its parent, sibling index, name, transform and property overrides, and the children the scene added under it. Use it to swap a kit piece for another (a wall host for a door host), a placeholder for a prefab, or a StaticBody3D for a RigidBody3D.
|
|
249
256
|
|
|
250
257
|
Give exactly one of scene or type. The scenePath must be a .tscn.
|
|
@@ -36,10 +36,18 @@ export function renderAgentsBlock(commands = projectCommands()) {
|
|
|
36
36
|
"",
|
|
37
37
|
"This is a game made with Summer Engine, the game engine built for AI. Game code is GDScript (`.gd`), scenes are `.tscn`, resources are `.tres`, and `project.godot` is the project file.",
|
|
38
38
|
"",
|
|
39
|
+
"## First game: make it look finished",
|
|
40
|
+
"",
|
|
41
|
+
"People judge Summer by the first frame of their first game, so make it look finished even when they ask for a quick prototype. Keep the features they asked for and raise the look:",
|
|
42
|
+
"- sky and sun with shadows, tonemapping, a little fog;",
|
|
43
|
+
"- a texture on every surface, and real models for the player, characters and main props (the starter project and the Summer asset library first), never capsules or boxes as final art;",
|
|
44
|
+
"- one colour palette and a styled UI font.",
|
|
45
|
+
"Before you say it is ready, play it and look at a screenshot of the running game, not the editor: the editor shows a preview sky and sun that the game does not have.",
|
|
46
|
+
"",
|
|
39
47
|
"## How to work on it",
|
|
40
48
|
"",
|
|
41
|
-
"-
|
|
42
|
-
"- With Summer's MCP server,
|
|
49
|
+
"- Write GDScript (`.gd`) files directly. Create and change scenes and import assets through Summer while Summer Engine has the project open: it imports new files, and the editor rewrites `.tscn` files when it saves, so hand edits to an open scene get lost.",
|
|
50
|
+
"- With Summer's MCP server, use the `summer_*` tools; `summer_get_project_context` tells you which project you are connected to. Without it, run the same operations as `summer` commands in the shell (the `summer-cli` skill). If `summer` is missing or older than 4.0, use `npx -y summer-engine@latest` in its place.",
|
|
43
51
|
"- Summer's skills teach each part of a game. `npx -y summer-engine@latest setup <agent> --yes` installs them for your agent (add `--cli` for no MCP server). Start with `using-summer`, and find the right one with `summer docs search --query \"<the task>\"`.",
|
|
44
52
|
"- `.summer/` is the project's memory: `GameSoul.md` says what the game is, `memory/` holds the decisions to keep. Read them before you change the game's look, sound or story.",
|
|
45
53
|
"- Check your own work: script errors, a screenshot, a play run. Ask the person to play only for feel and fun.",
|
|
@@ -50,7 +58,7 @@ export function renderAgentsBlock(commands = projectCommands()) {
|
|
|
50
58
|
"",
|
|
51
59
|
"## Publishing",
|
|
52
60
|
"",
|
|
53
|
-
"The `publish-your-game` skill has the steps; `summer ops search \"publish my game\"` finds each operation.
|
|
61
|
+
"The `publish-your-game` skill has the steps; `summer ops search \"publish my game\"` finds each operation. Going live needs the game owner's yes. A game goes live as soon as Summer's automated checks pass; Summer's staff review it after it is live, so never tell anyone to wait for a review.",
|
|
54
62
|
SUMMER_BLOCK_END,
|
|
55
63
|
].join("\n");
|
|
56
64
|
}
|
package/gemini-extension.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_generated": "GENERATED from integrations/gemini — do not edit; npm run generate:registry",
|
|
3
3
|
"name": "summer",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.8.0",
|
|
5
5
|
"description": "The game engine built for AI. Any agent makes a multiplayer game and publishes it. The Summer Engine MCP server, context primer and game-dev skills.",
|
|
6
6
|
"contextFileName": "GEMINI.md",
|
|
7
7
|
"mcpServers": {
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
"./library/skills/3d-lighting/",
|
|
28
28
|
"./library/skills/adaptive-music/",
|
|
29
29
|
"./library/skills/agent-playtesting/",
|
|
30
|
-
"./library/skills/ai-characters-in-games/",
|
|
31
30
|
"./library/skills/ambient-bed/",
|
|
32
31
|
"./library/skills/animated-loop/",
|
|
33
32
|
"./library/skills/animation-tree/",
|
|
@@ -107,6 +106,7 @@
|
|
|
107
106
|
"./library/skills/store-art/",
|
|
108
107
|
"./library/skills/store-listing/",
|
|
109
108
|
"./library/skills/summer-analytics/",
|
|
109
|
+
"./library/skills/summer-api/",
|
|
110
110
|
"./library/skills/summer-apps/",
|
|
111
111
|
"./library/skills/summer-apps-design/",
|
|
112
112
|
"./library/skills/summer-assets/",
|
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"./library/skills/summer-matchmaking/",
|
|
118
118
|
"./library/skills/summer-parties/",
|
|
119
119
|
"./library/skills/summer-player-data/",
|
|
120
|
+
"./library/skills/summer-router/",
|
|
120
121
|
"./library/skills/summer-store/",
|
|
121
122
|
"./library/skills/summer-world-chat/",
|
|
122
123
|
"./library/skills/summer-world-saves/",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
**Rule of thumb:** project reads/writes go through Summer; live hierarchy/inspector changes use scene tools; process-level work remains with the host.
|
|
21
21
|
|
|
22
|
-
## Tool surface (
|
|
22
|
+
## Tool surface (131 tools)
|
|
23
23
|
|
|
24
24
|
### Local projects (2)
|
|
25
25
|
|
|
@@ -93,7 +93,7 @@ No shell needed (Claude Desktop, chat apps); the `summer dev` command does both
|
|
|
93
93
|
|---|---|
|
|
94
94
|
| `summer_fabricate_3d` | Run a Blender Python (bpy) script in the user's OWN installed Blender — headless, engine-supervised — then import the exported `.glb` into `res://` and optionally instantiate it with `target_size`. For modular kits with exact dimensions, VFX meshes (shatter, sweeps, LOD chains), and post-processing generated models (decimate/UV/bake); generic props go to the library and characters to generation. Requires Blender on the machine (never bundled); `blender_not_found` carries the fix. The `fabricating-assets` skill has the bpy rules that survive glTF export. |
|
|
95
95
|
|
|
96
|
-
### Editor UI control (
|
|
96
|
+
### Editor UI control (5)
|
|
97
97
|
|
|
98
98
|
Preview: needs Summer Engine 0.5.66 or newer; older engines return `engine_lacks_op`. Scene work never goes through the editor UI (use the scene, scripting, and perception tools). UI ops are for editor-workflow steps a human does with the mouse — open Project Settings, switch the main screen, clear a blocking dialog, read a dock. Ladder: dedicated tool → named action → tree + activate → screenshot (pixels last, never for coordinates). Quit / project-reload / delete-without-confirm actions are denied by the engine. The `driving-the-editor-ui` skill carries the patterns.
|
|
99
99
|
|
|
@@ -103,6 +103,7 @@ Preview: needs Summer Engine 0.5.66 or newer; older engines return `engine_lacks
|
|
|
103
103
|
| `summer_ui_tree` | Structured Control tree of the live editor UI (class, path, rect, text/tooltip, `checked`/`enabled`/`tabs`/`current_tab`/`value`) from `root:"main" \| "window" \| "dock:<title\|id>" \| "dialog:<title>" \| "path:<node path>"`; `root:"dialogs"` lists every visible dialog/popup with `blocking`, `blocking_dialog`, and its `buttons`. The token-cheap alternative to a screenshot; its paths are what `summer_ui_activate` takes. |
|
|
104
104
|
| `summer_ui_activate` | Activate one control by tree path through its own input path — `press`, `toggle`, `focus`, `select_tab` (incl. `path:"main_screen" value:"3D"`), `set_text` (+`submit`), `set_value` — and `action:"dismiss_dialog"` (by `path` or `title`, `button` cancel/ok/text) to clear a blocking dialog. `state` / `visible_after` are read back after the action, never echoed. |
|
|
105
105
|
| `summer_ui_screenshot` | PNG of the editor window or one dock/dialog/control (`root`, `max_size`) returned as an image — the pixels-last fallback for LOOKING at the editor UI. Not for scene verification (`summer_screenshot`) and never for picking click coordinates. Honest `no_renderer` under a headless editor. |
|
|
106
|
+
| `summer_view_set` (`engine.view_set`) | Show the person what you work on: the frame's view (home, chat, 3D, 2D, script, game, Studio), the right rail, the focus and the nodes to frame. Use it when you start editing a scene or script, play the game, or finish on the best view of the result; not for reading a node (`summer_inspect_node`) or opening a web page (`studio.open`). Needs Summer Engine 4.6 or newer. |
|
|
106
107
|
|
|
107
108
|
### Perception (4)
|
|
108
109
|
|
|
@@ -291,6 +292,18 @@ These come from the hosted Summer server (the one ChatGPT and Claude connect to)
|
|
|
291
292
|
| `summer_docs_search` | Search the library (skills, tools, templates, references, examples, collections) by describing the task in plain words; ranked ids with `matched_by` (lexical / semantic). The first move for any task; works without the engine. |
|
|
292
293
|
| `summer_docs_read` | Load one entry by id: a skill's SKILL.md plus metadata, a tool's call recipe, a template's pin, a reference's body. A body ends with its relative links and the id that loads each; a linked file loads by `<entry id>/<link as written>` (e.g. `skill/spatial-placement/references/kit-placement-tools.md`). The last line is the `entry_id` footer to report through `docs.feedback`. |
|
|
293
294
|
|
|
295
|
+
### Summer API (5)
|
|
296
|
+
|
|
297
|
+
Signed in with `summer login` (one browser sign-in on this computer, renewed by itself; `summer token` prints a one-hour token for the person's own HTTP code). Each app spends the person's paid credits up to the limit they set in Connected apps. No rate limits on paid usage: jobs past the account's running slots (10 at once, up to 40 as it buys credits) answer `queued` and start in order. Money is the only refusal: `no_credits` (the paid balance) or `over_limit` (the app's own limit). The `summer-api` skill has the workflow.
|
|
298
|
+
|
|
299
|
+
| Tool | Use |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `summer_api_models` (`models.list`) | The Summer API's curated game-dev models: id, capability, input schema, output formats, typical time and USD price; `model` for one, `capability` to filter. No sign-in. Shell: `summer api models`. |
|
|
302
|
+
| `summer_api_estimate` (`models.estimate`) | The exact USD price of one job, its breakdown and a `quoteId` that holds it 15 minutes. Charges nothing. Shell: `summer api estimate`. |
|
|
303
|
+
| `summer_api_run` (`models.run`) | Run one job into the person's Summer assets with the Summer sign-in on this computer; spends paid credits within the app's limit. `wait` follows it, `out` saves its files, `quoteId` caps the charge. Shell: `summer api run --wait --download`. |
|
|
304
|
+
| `summer_api_batch` (`POST /v1/batches`) | Run up to 500 jobs at once, all or none: queued at held prices when paid credits and the app's limit cover them all; otherwise nothing runs and the error says how many fit. `batchId` reads a batch; `wait` and `out` as for one job. Shell: `summer api run --batch jobs.jsonl --wait --download`. |
|
|
305
|
+
| `summer_api_job` (`jobs.get`, `jobs.cancel`) | Read a job (state, price, assets and file URLs); `wait`, `out` or `cancel`. Shell: `summer api jobs`. |
|
|
306
|
+
|
|
294
307
|
### Library feedback (1)
|
|
295
308
|
|
|
296
309
|
| Tool | Use |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
id: reference/mcp-tools-reference
|
|
2
2
|
kind: reference
|
|
3
|
-
version: 1.4.
|
|
3
|
+
version: 1.4.3
|
|
4
4
|
summary: Canonical reference for which Summer MCP tool to call — skills should reference tool names exactly as written here.
|
|
5
5
|
use_when:
|
|
6
6
|
- choosing between Summer MCP tools and host tools for an operation
|