sbox-mcp-server 1.13.0 → 1.15.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/dist/index.js CHANGED
@@ -45,6 +45,8 @@ import { registerGameplayTools } from "./tools/gameplay.js";
45
45
  import { registerNpcTools } from "./tools/npc.js";
46
46
  import { registerInspectionTools } from "./tools/inspection.js";
47
47
  import { registerInputTools } from "./tools/inputs.js";
48
+ import { registerDebugVizTools } from "./tools/debugviz.js";
49
+ import { registerDebugDrawTools } from "./tools/debugdraw.js";
48
50
  // ── CLI flags ──────────────────────────────────────────────────────
49
51
  const args = process.argv.slice(2);
50
52
  /** Read the package version from package.json, or return "unknown" on failure. */
@@ -193,6 +195,8 @@ registerGameplayTools(server, bridge);
193
195
  registerNpcTools(server, bridge);
194
196
  registerInspectionTools(server, bridge);
195
197
  registerInputTools(server, bridge);
198
+ registerDebugVizTools(server, bridge);
199
+ registerDebugDrawTools(server, bridge);
196
200
  /** Start the MCP server on stdio and attempt initial Bridge connection. */
197
201
  async function main() {
198
202
  const transport = new StdioServerTransport();
@@ -0,0 +1,18 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BridgeClient } from "../transport/bridge-client.js";
3
+ /**
4
+ * debug_draw_* / debug_clear — visualize debug primitives in the scene
5
+ * (ported from the Claude Bridge for Unity's debug_draw family).
6
+ *
7
+ * Renders in BOTH modes via one ClaudeDebugDraw holder component:
8
+ * • edit scene → Gizmo.Draw.* — visible in the live editor viewport, but NOT
9
+ * in take_screenshot/screenshot_from (the editor gizmo pass isn't in that
10
+ * camera render). Confirm edit-mode draws with your own eyes in the editor.
11
+ * • play scene → Scene.DebugOverlay.* — visible in-game AND through the bridge
12
+ * via capture_view (which renders the running scene).
13
+ *
14
+ * Coords are world-space "x,y,z" strings; colors are "r,g,b" or "r,g,b,a"
15
+ * floats 0–1. Primitives accumulate until debug_clear.
16
+ */
17
+ export declare function registerDebugDrawTools(server: McpServer, bridge: BridgeClient): void;
18
+ //# sourceMappingURL=debugdraw.d.ts.map
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * debug_draw_* / debug_clear — visualize debug primitives in the scene
4
+ * (ported from the Claude Bridge for Unity's debug_draw family).
5
+ *
6
+ * Renders in BOTH modes via one ClaudeDebugDraw holder component:
7
+ * • edit scene → Gizmo.Draw.* — visible in the live editor viewport, but NOT
8
+ * in take_screenshot/screenshot_from (the editor gizmo pass isn't in that
9
+ * camera render). Confirm edit-mode draws with your own eyes in the editor.
10
+ * • play scene → Scene.DebugOverlay.* — visible in-game AND through the bridge
11
+ * via capture_view (which renders the running scene).
12
+ *
13
+ * Coords are world-space "x,y,z" strings; colors are "r,g,b" or "r,g,b,a"
14
+ * floats 0–1. Primitives accumulate until debug_clear.
15
+ */
16
+ export function registerDebugDrawTools(server, bridge) {
17
+ const reply = (res) => res.success
18
+ ? { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] }
19
+ : { content: [{ type: "text", text: `Error: ${res.error}` }] };
20
+ const color = z
21
+ .string()
22
+ .optional()
23
+ .describe('Color as "r,g,b" or "r,g,b,a" floats 0–1 (default varies per shape)');
24
+ const thickness = z.number().optional().describe("Line thickness for edit-mode gizmos (default 2)");
25
+ server.tool("debug_draw_line", "Draw a debug line between two world points. Renders in the editor viewport (Gizmo) AND in play mode (DebugOverlay), accumulating until debug_clear. NB: edit-mode gizmos show in the live editor but NOT in take_screenshot/screenshot_from — use capture_view in play mode to see debug draws through the bridge.", {
26
+ from: z.string().describe('Start point, world-space "x,y,z"'),
27
+ to: z.string().describe('End point, world-space "x,y,z"'),
28
+ color,
29
+ thickness,
30
+ }, async (p) => reply(await bridge.send("debug_draw_line", p)));
31
+ server.tool("debug_draw_ray", "Draw a debug ray (drawn as an arrow) from an origin along a direction for a given length. Renders in editor and play. Ideal for visualizing a raycast result or a facing/normal direction. Accumulates until debug_clear.", {
32
+ origin: z.string().describe('Ray origin, world-space "x,y,z"'),
33
+ direction: z.string().describe('Direction vector "x,y,z" (normalized internally)'),
34
+ length: z.number().optional().describe("Ray length in units (default 64)"),
35
+ color,
36
+ thickness,
37
+ }, async (p) => reply(await bridge.send("debug_draw_ray", p)));
38
+ server.tool("debug_draw_box", "Draw a wireframe debug box centered at a point. Renders in editor and play. Ideal for visualizing a trigger_zone's bounds or a physics_overlap box volume. Accumulates until debug_clear.", {
39
+ center: z.string().describe('Box center, world-space "x,y,z"'),
40
+ size: z.string().optional().describe('Full size "x,y,z" in units (default "32,32,32")'),
41
+ color,
42
+ thickness,
43
+ }, async (p) => reply(await bridge.send("debug_draw_box", p)));
44
+ server.tool("debug_draw_sphere", "Draw a wireframe debug sphere at a point. Renders in editor and play. Ideal for visualizing a physics_overlap radius or an NPC's hearing/sight range. Accumulates until debug_clear.", {
45
+ center: z.string().describe('Sphere center, world-space "x,y,z"'),
46
+ radius: z.number().optional().describe("Radius in units (default 32)"),
47
+ color,
48
+ thickness,
49
+ }, async (p) => reply(await bridge.send("debug_draw_sphere", p)));
50
+ server.tool("debug_clear", "Remove all debug-draw primitives by destroying the debug holder for the current scene (edit or play). Call before redrawing a fresh frame of debug shapes.", {}, async (p) => reply(await bridge.send("debug_clear", p)));
51
+ }
52
+ //# sourceMappingURL=debugdraw.js.map
@@ -0,0 +1,12 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BridgeClient } from "../transport/bridge-client.js";
3
+ /**
4
+ * Debug-visualization & playtest meta-tools ported from the Unity bridge's
5
+ * engine/workflow layer (see docs/plans/2026-06-17-unity-carryover-meta-tools.md).
6
+ *
7
+ * Currently: set_time_scale + get_profiler_stats (Unity carry-over wave, 2 of 4).
8
+ * Planned next: debug_draw_* + debug_clear (Gizmo.Draw edit-mode + DebugOverlay
9
+ * play-mode) and run_tests (dotnet test spike).
10
+ */
11
+ export declare function registerDebugVizTools(server: McpServer, bridge: BridgeClient): void;
12
+ //# sourceMappingURL=debugviz.d.ts.map
@@ -0,0 +1,45 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Debug-visualization & playtest meta-tools ported from the Unity bridge's
4
+ * engine/workflow layer (see docs/plans/2026-06-17-unity-carryover-meta-tools.md).
5
+ *
6
+ * Currently: set_time_scale + get_profiler_stats (Unity carry-over wave, 2 of 4).
7
+ * Planned next: debug_draw_* + debug_clear (Gizmo.Draw edit-mode + DebugOverlay
8
+ * play-mode) and run_tests (dotnet test spike).
9
+ */
10
+ export function registerDebugVizTools(server, bridge) {
11
+ // ── set_time_scale ───────────────────────────────────────────────
12
+ server.tool("set_time_scale", "Set the running game's time scale DURING PLAY MODE (ported from Unity's playtest_set_time_scale). 0 = pause, 1 = normal, 0.1 = slow-mo to watch a fast interaction frame-by-frame, 2+ = fast-forward idle/economy ticks. Requires start_play first — the edit scene doesn't tick, so this no-ops outside play mode and returns an error. Sets Game.ActiveScene.TimeScale (clamped to 0–100). Returns the applied and previous values.", {
13
+ scale: z
14
+ .number()
15
+ .min(0)
16
+ .describe("Time multiplier: 0 = pause, 1 = normal speed, 0.1 = slow-mo, 2 = double speed. Clamped to 0–100"),
17
+ }, async (params) => {
18
+ const res = await bridge.send("set_time_scale", params);
19
+ if (!res.success) {
20
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
21
+ }
22
+ return {
23
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
24
+ };
25
+ });
26
+ // ── get_profiler_stats ───────────────────────────────────────────
27
+ server.tool("get_profiler_stats", "Read live engine performance counters (ported from Unity's get_profiler_stats): FPS, frame ms, GPU ms, bytes allocated, process memory, exception count, and per-category timings (update/physics/ui/render/network/gcPause) averaged over `frames`. Reads Sandbox.Diagnostics.PerformanceStats. Most meaningful during play (call start_play first) but populated in the editor too. Read-only.", {
28
+ frames: z
29
+ .number()
30
+ .int()
31
+ .min(1)
32
+ .max(1000)
33
+ .optional()
34
+ .describe("Averaging window (frames) for the per-category timings. Default 60"),
35
+ }, async (params) => {
36
+ const res = await bridge.send("get_profiler_stats", params);
37
+ if (!res.success) {
38
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
39
+ }
40
+ return {
41
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
42
+ };
43
+ });
44
+ }
45
+ //# sourceMappingURL=debugviz.js.map
package/package.json CHANGED
@@ -1,55 +1,55 @@
1
- {
2
- "name": "sbox-mcp-server",
3
- "version": "1.13.0",
4
- "description": "MCP Server for s&box game engine — enables Claude to build games through conversation",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "sbox-mcp-server": "dist/index.js",
9
- "sbox-mcp": "dist/index.js"
10
- },
11
- "files": [
12
- "dist/**/*.js",
13
- "dist/**/*.d.ts",
14
- "README.md",
15
- "LICENSE"
16
- ],
17
- "scripts": {
18
- "build": "tsc",
19
- "test": "npm run build && node --test",
20
- "start": "node dist/index.js",
21
- "dev": "tsc --watch",
22
- "prepublishOnly": "npm run build"
23
- },
24
- "keywords": [
25
- "mcp",
26
- "sbox",
27
- "s&box",
28
- "game-engine",
29
- "claude",
30
- "ai",
31
- "source2",
32
- "model-context-protocol"
33
- ],
34
- "repository": {
35
- "type": "git",
36
- "url": "git+https://github.com/LouSputthole/Sbox-Claude.git"
37
- },
38
- "author": "sboxskins.gg (https://sboxskins.gg)",
39
- "homepage": "https://sboxskins.gg",
40
- "bugs": {
41
- "url": "https://github.com/LouSputthole/Sbox-Claude/issues"
42
- },
43
- "dependencies": {
44
- "@modelcontextprotocol/sdk": "^1.12.1",
45
- "zod": "^3.24.0"
46
- },
47
- "devDependencies": {
48
- "@types/node": "^22.0.0",
49
- "typescript": "^5.7.0"
50
- },
51
- "engines": {
52
- "node": ">=18.0.0"
53
- },
54
- "license": "AGPL-3.0-or-later"
55
- }
1
+ {
2
+ "name": "sbox-mcp-server",
3
+ "version": "1.15.0",
4
+ "description": "MCP Server for s&box game engine — enables Claude to build games through conversation",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "sbox-mcp-server": "dist/index.js",
9
+ "sbox-mcp": "dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist/**/*.js",
13
+ "dist/**/*.d.ts",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "test": "npm run build && node --test",
20
+ "start": "node dist/index.js",
21
+ "dev": "tsc --watch",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "mcp",
26
+ "sbox",
27
+ "s&box",
28
+ "game-engine",
29
+ "claude",
30
+ "ai",
31
+ "source2",
32
+ "model-context-protocol"
33
+ ],
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/LouSputthole/Sbox-Claude.git"
37
+ },
38
+ "author": "sboxskins.gg (https://sboxskins.gg)",
39
+ "homepage": "https://sboxskins.gg",
40
+ "bugs": {
41
+ "url": "https://github.com/LouSputthole/Sbox-Claude/issues"
42
+ },
43
+ "dependencies": {
44
+ "@modelcontextprotocol/sdk": "^1.12.1",
45
+ "zod": "^3.24.0"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^22.0.0",
49
+ "typescript": "^5.7.0"
50
+ },
51
+ "engines": {
52
+ "node": ">=18.0.0"
53
+ },
54
+ "license": "AGPL-3.0-or-later"
55
+ }