sbox-mcp-server 1.2.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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -0
  3. package/dist/index.d.ts +13 -0
  4. package/dist/index.js +155 -0
  5. package/dist/tools/assets.d.ts +8 -0
  6. package/dist/tools/assets.js +80 -0
  7. package/dist/tools/audio.d.ts +8 -0
  8. package/dist/tools/audio.js +101 -0
  9. package/dist/tools/components.d.ts +11 -0
  10. package/dist/tools/components.js +78 -0
  11. package/dist/tools/console.d.ts +8 -0
  12. package/dist/tools/console.js +59 -0
  13. package/dist/tools/discovery.d.ts +13 -0
  14. package/dist/tools/discovery.js +58 -0
  15. package/dist/tools/gameobjects.d.ts +4 -0
  16. package/dist/tools/gameobjects.js +197 -0
  17. package/dist/tools/materials.d.ts +8 -0
  18. package/dist/tools/materials.js +82 -0
  19. package/dist/tools/networking.d.ts +11 -0
  20. package/dist/tools/networking.js +227 -0
  21. package/dist/tools/physics.d.ts +8 -0
  22. package/dist/tools/physics.js +130 -0
  23. package/dist/tools/playmode.d.ts +11 -0
  24. package/dist/tools/playmode.js +140 -0
  25. package/dist/tools/prefabs.d.ts +8 -0
  26. package/dist/tools/prefabs.js +94 -0
  27. package/dist/tools/project.d.ts +12 -0
  28. package/dist/tools/project.js +90 -0
  29. package/dist/tools/publishing.d.ts +11 -0
  30. package/dist/tools/publishing.js +168 -0
  31. package/dist/tools/scenes.d.ts +8 -0
  32. package/dist/tools/scenes.js +75 -0
  33. package/dist/tools/scripts.d.ts +9 -0
  34. package/dist/tools/scripts.js +132 -0
  35. package/dist/tools/status.d.ts +8 -0
  36. package/dist/tools/status.js +49 -0
  37. package/dist/tools/templates.d.ts +11 -0
  38. package/dist/tools/templates.js +135 -0
  39. package/dist/tools/ui.d.ts +8 -0
  40. package/dist/tools/ui.js +116 -0
  41. package/dist/tools/world.d.ts +20 -0
  42. package/dist/tools/world.js +272 -0
  43. package/dist/transport/bridge-client.d.ts +60 -0
  44. package/dist/transport/bridge-client.js +239 -0
  45. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sbox-Claude Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # sbox-mcp-server
2
+
3
+ MCP Server for the s&box game engine. Lets Claude Code build s&box games through conversation — 78 working tools for scenes, scripts, GameObjects, components, assets, materials, audio, physics, UI, networking, publishing, and more.
4
+
5
+ ## Quick Start
6
+
7
+ ### 1. Install the Bridge Addon in s&box
8
+
9
+ The Bridge Addon runs inside the s&box editor and receives commands from this MCP server.
10
+
11
+ **From source:**
12
+ ```bash
13
+ git clone https://github.com/lousputthole/sbox-claude.git
14
+ ```
15
+
16
+ Then in s&box:
17
+ 1. Open your project in the s&box editor
18
+ 2. Go to **Library Manager** and create a new library called **"claudebridge"**
19
+ 3. Copy `sbox-bridge-addon/Editor/MyEditorMenu.cs` into the library's `Editor/` folder
20
+ 4. Restart s&box
21
+
22
+ ### 2. Build the MCP Server
23
+
24
+ ```bash
25
+ cd sbox-claude/sbox-mcp-server
26
+ npm install
27
+ npm run build
28
+ ```
29
+
30
+ ### 3. Connect to Claude Code
31
+
32
+ ```bash
33
+ claude mcp add sbox -- node /path/to/sbox-mcp-server/dist/index.js
34
+ ```
35
+
36
+ ### 4. Open the Bridge Dock
37
+
38
+ In s&box, go to **View > Claude Bridge** to open the dock panel. The dock **must be visible** for commands to be processed.
39
+
40
+ That's it. Start Claude Code and start building.
41
+
42
+ ## How It Works
43
+
44
+ ```
45
+ Claude Code --> (stdio) --> sbox-mcp-server --> (file IPC) --> Bridge Addon --> s&box Editor
46
+ ```
47
+
48
+ Communication uses **file-based IPC** through `%TEMP%/sbox-bridge-ipc/`. The MCP server writes request JSON files, the Bridge Addon (running inside s&box) polls for them, processes on the main editor thread, and writes response files back.
49
+
50
+ WebSocket is not used — s&box's sandboxed C# environment does not allow `System.Net`.
51
+
52
+ ## Tools (78 working, 89 defined)
53
+
54
+ | Category | Tools |
55
+ |----------|-------|
56
+ | **Project** | get_project_info, list_project_files, read_file, write_file |
57
+ | **Scripts** | create_script, edit_script, delete_script, trigger_hotload |
58
+ | **Scenes** | list_scenes, load_scene, save_scene, create_scene |
59
+ | **GameObjects** | create/delete/duplicate/rename, set_parent/enabled/transform |
60
+ | **Components** | get/set_property, get_all_properties, list_available, add_component |
61
+ | **Hierarchy** | get_scene_hierarchy, get/select/focus_object |
62
+ | **Assets** | search_assets, list_asset_library, install_asset, get_asset_info |
63
+ | **Materials** | assign_model, create/assign_material, set_material_property |
64
+ | **Audio** | list_sounds, create_sound_event, assign_sound, play_sound_preview |
65
+ | **Play Mode** | start/stop_play, is_playing |
66
+ | **Runtime** | get/set_runtime_property, take_screenshot |
67
+ | **Editor** | undo, redo |
68
+ | **Prefabs** | create/instantiate_prefab, list_prefabs, get_prefab_info |
69
+ | **Physics** | add_physics, add_collider, add_joint, raycast |
70
+ | **UI** | create_razor_ui, add_screen_panel, add_world_panel |
71
+ | **Templates** | create_player/npc_controller, create_game_manager, create_trigger_zone |
72
+ | **Networking** | network_helper, configure/status, spawn, ownership, sync, RPCs, templates |
73
+ | **Publishing** | project_config, validate, thumbnail, package_details, install_asset |
74
+ | **Status** | get_bridge_status |
75
+
76
+ ### Not implementable (no s&box API)
77
+
78
+ pause_play, resume_play, get_console_output, get_compile_errors, clear_console, build_project, get_build_status, clean_build, export_project, prepare_publish
79
+
80
+ ## Requirements
81
+
82
+ - **Node.js 18+**
83
+ - **s&box** with the Bridge Addon installed
84
+ - **Claude Code**
85
+
86
+ ## License
87
+
88
+ **GPL-3.0** — see [LICENSE](../LICENSE) for details.
89
+
90
+ Copyright (c) 2026 [sboxskins.gg](https://sboxskins.gg)
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Entry point for the sbox-mcp MCP server.
4
+ *
5
+ * Creates an MCP server (stdio transport), connects to the s&box Bridge Addon
6
+ * via WebSocket, and registers all tool handlers. Each tool domain (project,
7
+ * scripts, console, scenes, etc.) has its own register function in src/tools/.
8
+ *
9
+ * CLI flags: --version / -v, --help / -h
10
+ * Environment: SBOX_BRIDGE_HOST, SBOX_BRIDGE_PORT
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Entry point for the sbox-mcp MCP server.
4
+ *
5
+ * Creates an MCP server (stdio transport), connects to the s&box Bridge Addon
6
+ * via WebSocket, and registers all tool handlers. Each tool domain (project,
7
+ * scripts, console, scenes, etc.) has its own register function in src/tools/.
8
+ *
9
+ * CLI flags: --version / -v, --help / -h
10
+ * Environment: SBOX_BRIDGE_HOST, SBOX_BRIDGE_PORT
11
+ */
12
+ import { readFileSync } from "fs";
13
+ import { fileURLToPath } from "url";
14
+ import { dirname, join } from "path";
15
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
16
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
17
+ import { BridgeClient } from "./transport/bridge-client.js";
18
+ import { registerProjectTools } from "./tools/project.js";
19
+ import { registerScriptTools } from "./tools/scripts.js";
20
+ import { registerConsoleTools } from "./tools/console.js";
21
+ import { registerSceneTools } from "./tools/scenes.js";
22
+ import { registerGameObjectTools } from "./tools/gameobjects.js";
23
+ import { registerComponentTools } from "./tools/components.js";
24
+ import { registerAssetTools } from "./tools/assets.js";
25
+ import { registerMaterialTools } from "./tools/materials.js";
26
+ import { registerAudioTools } from "./tools/audio.js";
27
+ import { registerStatusTools } from "./tools/status.js";
28
+ import { registerPlayModeTools } from "./tools/playmode.js";
29
+ import { registerPrefabTools } from "./tools/prefabs.js";
30
+ import { registerPhysicsTools } from "./tools/physics.js";
31
+ import { registerUITools } from "./tools/ui.js";
32
+ import { registerTemplateTools } from "./tools/templates.js";
33
+ import { registerNetworkingTools } from "./tools/networking.js";
34
+ import { registerPublishingTools } from "./tools/publishing.js";
35
+ import { registerWorldTools } from "./tools/world.js";
36
+ import { registerDiscoveryTools } from "./tools/discovery.js";
37
+ // ── CLI flags ──────────────────────────────────────────────────────
38
+ const args = process.argv.slice(2);
39
+ /** Read the package version from package.json, or return "unknown" on failure. */
40
+ function getVersion() {
41
+ try {
42
+ const __filename = fileURLToPath(import.meta.url);
43
+ const __dirname = dirname(__filename);
44
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
45
+ return pkg.version ?? "unknown";
46
+ }
47
+ catch {
48
+ return "unknown";
49
+ }
50
+ }
51
+ if (args.includes("--version") || args.includes("-v")) {
52
+ console.log(`sbox-mcp ${getVersion()}`);
53
+ process.exit(0);
54
+ }
55
+ if (args.includes("--help") || args.includes("-h")) {
56
+ console.log(`sbox-mcp ${getVersion()} — MCP Server for s&box game engine
57
+
58
+ USAGE
59
+ node dist/index.js Start the MCP server (stdio transport)
60
+ node dist/index.js --help Show this help
61
+ node dist/index.js --version Show version
62
+
63
+ ENVIRONMENT VARIABLES
64
+ SBOX_BRIDGE_HOST Bridge WebSocket host (default: 127.0.0.1)
65
+ SBOX_BRIDGE_PORT Bridge WebSocket port (default: 29015)
66
+
67
+ CONNECT TO CLAUDE CODE
68
+ claude mcp add sbox -- node /path/to/sbox-mcp-server/dist/index.js
69
+
70
+ TOOLS (109 total)
71
+ Project: get_project_info, list_project_files, read_file, write_file
72
+ Scripts: create_script, edit_script, delete_script, trigger_hotload
73
+ Console: get_console_output, get_compile_errors, clear_console
74
+ Scenes: list_scenes, load_scene, save_scene, create_scene
75
+ GameObjects: create/delete/duplicate/rename_gameobject, set_parent/enabled/transform
76
+ Components: get/set_property, get_all_properties, list_available_components, add_component_with_properties, set_prefab_ref
77
+ Hierarchy: get_scene_hierarchy, get_selected_objects, select_object, focus_object
78
+ Assets: search_assets, list_asset_library, install_asset, get_asset_info
79
+ Materials: assign_model, create_material, assign_material, set_material_property
80
+ Audio: list_sounds, create_sound_event, assign_sound, play_sound_preview
81
+ Play Mode: start/stop/pause/resume_play, is_playing
82
+ Runtime: get/set_runtime_property, take_screenshot
83
+ Editor: undo, redo
84
+ Prefabs: create_prefab, instantiate_prefab, list_prefabs, get_prefab_info
85
+ Physics: add_physics, add_collider, add_joint, raycast
86
+ UI: create_razor_ui, add_screen_panel, add_world_panel
87
+ Templates: create_player_controller, create_npc_controller, create_game_manager, create_trigger_zone
88
+ Networking: add_network_helper, configure_network, get_network_status, network_spawn, set_ownership
89
+ Net Scripts: add_sync_property, add_rpc_method, create_networked_player, create_lobby_manager, create_network_events
90
+ Publishing: get_project_config, set_project_config, validate_project, build_project, get_build_status, clean_build
91
+ Export: export_project, set_project_thumbnail, get_package_details, prepare_publish
92
+ World Gen: invoke_button, list_component_buttons, raycast_terrain, build_terrain_mesh
93
+ Map Edit: add_terrain_hill/clearing/trail, clear_terrain_features, sculpt_terrain
94
+ Caves: add_cave_waypoint, clear_cave_path
95
+ Forest: add_forest_poi/trail, set_forest_seed, clear_forest_pois, paint_forest_density
96
+ Placement: place_along_path
97
+ Discovery: describe_type, search_types, get_method_signature, find_in_project
98
+ Status: get_bridge_status
99
+ `);
100
+ process.exit(0);
101
+ }
102
+ // ── Server setup ───────────────────────────────────────────────────
103
+ const server = new McpServer({
104
+ name: "sbox-mcp",
105
+ version: getVersion(),
106
+ });
107
+ // Bridge client connects to s&box editor via WebSocket
108
+ const bridge = new BridgeClient(process.env.SBOX_BRIDGE_HOST ?? "127.0.0.1", parseInt(process.env.SBOX_BRIDGE_PORT ?? "29015", 10));
109
+ // Register all tools
110
+ registerProjectTools(server, bridge);
111
+ registerScriptTools(server, bridge);
112
+ registerConsoleTools(server, bridge);
113
+ registerSceneTools(server, bridge);
114
+ registerGameObjectTools(server, bridge);
115
+ registerComponentTools(server, bridge);
116
+ registerAssetTools(server, bridge);
117
+ registerMaterialTools(server, bridge);
118
+ registerAudioTools(server, bridge);
119
+ registerStatusTools(server, bridge);
120
+ registerPlayModeTools(server, bridge);
121
+ registerPrefabTools(server, bridge);
122
+ registerPhysicsTools(server, bridge);
123
+ registerUITools(server, bridge);
124
+ registerTemplateTools(server, bridge);
125
+ registerNetworkingTools(server, bridge);
126
+ registerPublishingTools(server, bridge);
127
+ registerWorldTools(server, bridge);
128
+ registerDiscoveryTools(server, bridge);
129
+ /** Start the MCP server on stdio and attempt initial Bridge connection. */
130
+ async function main() {
131
+ const transport = new StdioServerTransport();
132
+ await server.connect(transport);
133
+ console.error("");
134
+ console.error(" ╔═══════════════════════════════════════════════════╗");
135
+ console.error(" ║ s&box Claude Bridge — MCP Server ║");
136
+ console.error(" ║ Build s&box games through conversation ║");
137
+ console.error(" ║ ║");
138
+ console.error(" ║ A project by sboxskins.gg ║");
139
+ console.error(" ║ https://sboxskins.gg ║");
140
+ console.error(" ╚═══════════════════════════════════════════════════╝");
141
+ console.error("");
142
+ // Attempt initial connection to s&box (non-fatal if it fails)
143
+ try {
144
+ await bridge.connect();
145
+ console.error("[sbox-mcp] Connected to s&box Bridge");
146
+ }
147
+ catch {
148
+ console.error("[sbox-mcp] Warning: Could not connect to s&box Bridge. Will retry on first tool call.");
149
+ }
150
+ }
151
+ main().catch((err) => {
152
+ console.error("[sbox-mcp] Fatal error:", err);
153
+ process.exit(1);
154
+ });
155
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,8 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BridgeClient } from "../transport/bridge-client.js";
3
+ /**
4
+ * Asset browser tools: search_assets, list_asset_library, install_asset, get_asset_info.
5
+ * Provides access to both project-local assets and the s&box community asset library.
6
+ */
7
+ export declare function registerAssetTools(server: McpServer, bridge: BridgeClient): void;
8
+ //# sourceMappingURL=assets.d.ts.map
@@ -0,0 +1,80 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Asset browser tools: search_assets, list_asset_library, install_asset, get_asset_info.
4
+ * Provides access to both project-local assets and the s&box community asset library.
5
+ */
6
+ export function registerAssetTools(server, bridge) {
7
+ // ── search_assets ────────────────────────────────────────────────
8
+ server.tool("search_assets", "Search for assets in the project by name, type, or keyword. Returns models, materials, sounds, textures, prefabs, etc.", {
9
+ query: z
10
+ .string()
11
+ .optional()
12
+ .describe("Search term to match against asset name or path"),
13
+ type: z
14
+ .string()
15
+ .optional()
16
+ .describe("Asset type filter (e.g. 'model', 'material', 'sound', 'texture', 'prefab')"),
17
+ maxResults: z
18
+ .number()
19
+ .optional()
20
+ .describe("Maximum results to return. Defaults to 50"),
21
+ }, async (params) => {
22
+ const res = await bridge.send("search_assets", params);
23
+ if (!res.success) {
24
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
25
+ }
26
+ return {
27
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
28
+ };
29
+ });
30
+ // ── list_asset_library ───────────────────────────────────────────
31
+ server.tool("list_asset_library", "Browse the s&box community asset library. Search for packages by name, description, or type to find models, maps, and tools to install", {
32
+ query: z
33
+ .string()
34
+ .optional()
35
+ .describe("Search term for packages"),
36
+ type: z
37
+ .string()
38
+ .optional()
39
+ .describe("Package type filter (e.g. 'model', 'map', 'library')"),
40
+ maxResults: z
41
+ .number()
42
+ .optional()
43
+ .describe("Maximum results. Defaults to 25"),
44
+ }, async (params) => {
45
+ const res = await bridge.send("list_asset_library", params);
46
+ if (!res.success) {
47
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
48
+ }
49
+ return {
50
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
51
+ };
52
+ });
53
+ // ── install_asset ────────────────────────────────────────────────
54
+ server.tool("install_asset", "Install a community asset package into the project by its ident (e.g. 'facepunch.flatgrass'). Adds it as a project dependency", {
55
+ ident: z
56
+ .string()
57
+ .describe("Package identifier (e.g. 'facepunch.flatgrass', 'author.package_name')"),
58
+ }, async (params) => {
59
+ const res = await bridge.send("install_asset", params);
60
+ if (!res.success) {
61
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
62
+ }
63
+ return {
64
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
65
+ };
66
+ });
67
+ // ── get_asset_info ───────────────────────────────────────────────
68
+ server.tool("get_asset_info", "Get detailed metadata about a specific asset — type, path, tags, package source", {
69
+ path: z.string().describe("Asset path (e.g. 'models/citizen/citizen.vmdl')"),
70
+ }, async (params) => {
71
+ const res = await bridge.send("get_asset_info", params);
72
+ if (!res.success) {
73
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
74
+ }
75
+ return {
76
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
77
+ };
78
+ });
79
+ }
80
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1,8 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BridgeClient } from "../transport/bridge-client.js";
3
+ /**
4
+ * Audio tools: list_sounds, create_sound_event, assign_sound, play_sound_preview.
5
+ * Manages sound assets, .sound event files, and SoundPointComponent attachment.
6
+ */
7
+ export declare function registerAudioTools(server: McpServer, bridge: BridgeClient): void;
8
+ //# sourceMappingURL=audio.d.ts.map
@@ -0,0 +1,101 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Audio tools: list_sounds, create_sound_event, assign_sound, play_sound_preview.
4
+ * Manages sound assets, .sound event files, and SoundPointComponent attachment.
5
+ */
6
+ export function registerAudioTools(server, bridge) {
7
+ // ── list_sounds ──────────────────────────────────────────────────
8
+ server.tool("list_sounds", "List available sound assets in the project and installed packages. Filter by name", {
9
+ filter: z
10
+ .string()
11
+ .optional()
12
+ .describe("Search filter for sound name or path"),
13
+ maxResults: z
14
+ .number()
15
+ .optional()
16
+ .describe("Maximum results. Defaults to 50"),
17
+ }, async (params) => {
18
+ const res = await bridge.send("list_sounds", 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
+ // ── create_sound_event ───────────────────────────────────────────
27
+ server.tool("create_sound_event", "Create a new sound event file (.sound) with volume, pitch, distance falloff, and looping settings", {
28
+ path: z
29
+ .string()
30
+ .describe("Path for the sound event file (e.g. 'sounds/footstep.sound')"),
31
+ sound: z
32
+ .string()
33
+ .describe("Path to the source sound asset (.vsnd)"),
34
+ volume: z
35
+ .number()
36
+ .optional()
37
+ .describe("Volume multiplier (0-1). Defaults to 1.0"),
38
+ pitch: z
39
+ .number()
40
+ .optional()
41
+ .describe("Pitch multiplier. Defaults to 1.0"),
42
+ minDistance: z
43
+ .number()
44
+ .optional()
45
+ .describe("Minimum distance before falloff starts (units). Defaults to 100"),
46
+ maxDistance: z
47
+ .number()
48
+ .optional()
49
+ .describe("Maximum audible distance (units). Defaults to 2000"),
50
+ loop: z
51
+ .boolean()
52
+ .optional()
53
+ .describe("Whether the sound should loop. Defaults to false"),
54
+ }, async (params) => {
55
+ const res = await bridge.send("create_sound_event", params);
56
+ if (!res.success) {
57
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
58
+ }
59
+ return {
60
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
61
+ };
62
+ });
63
+ // ── assign_sound ─────────────────────────────────────────────────
64
+ server.tool("assign_sound", "Attach a sound event to a GameObject via SoundPointComponent. Creates the component if needed", {
65
+ id: z.string().describe("GUID of the GameObject"),
66
+ sound: z
67
+ .string()
68
+ .describe("Sound event path (e.g. 'sounds/ambient_wind.sound')"),
69
+ playOnStart: z
70
+ .boolean()
71
+ .optional()
72
+ .describe("Whether the sound plays automatically when the game starts"),
73
+ }, async (params) => {
74
+ const res = await bridge.send("assign_sound", params);
75
+ if (!res.success) {
76
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
77
+ }
78
+ return {
79
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
80
+ };
81
+ });
82
+ // ── play_sound_preview ───────────────────────────────────────────
83
+ server.tool("play_sound_preview", "Play a sound in the editor for testing without entering play mode", {
84
+ sound: z
85
+ .string()
86
+ .describe("Sound event or asset path to preview"),
87
+ volume: z
88
+ .number()
89
+ .optional()
90
+ .describe("Preview volume (0-1). Defaults to 1.0"),
91
+ }, async (params) => {
92
+ const res = await bridge.send("play_sound_preview", params);
93
+ if (!res.success) {
94
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
95
+ }
96
+ return {
97
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
98
+ };
99
+ });
100
+ }
101
+ //# sourceMappingURL=audio.js.map
@@ -0,0 +1,11 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BridgeClient } from "../transport/bridge-client.js";
3
+ /**
4
+ * Component inspection and manipulation tools.
5
+ *
6
+ * Registers: get_property, get_all_properties, list_available_components,
7
+ * add_component_with_properties. These tools read/write component data on
8
+ * GameObjects and discover available component types (both built-in and custom).
9
+ */
10
+ export declare function registerComponentTools(server: McpServer, bridge: BridgeClient): void;
11
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1,78 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Component inspection and manipulation tools.
4
+ *
5
+ * Registers: get_property, get_all_properties, list_available_components,
6
+ * add_component_with_properties. These tools read/write component data on
7
+ * GameObjects and discover available component types (both built-in and custom).
8
+ */
9
+ export function registerComponentTools(server, bridge) {
10
+ // ── get_property ─────────────────────────────────────────────────
11
+ server.tool("get_property", "Read a single property value from a component on a GameObject", {
12
+ id: z.string().describe("GUID of the GameObject"),
13
+ component: z
14
+ .string()
15
+ .describe("Component type name (e.g. 'ModelRenderer', 'PlayerController')"),
16
+ property: z.string().describe("Property name to read"),
17
+ }, async (params) => {
18
+ const res = await bridge.send("get_property", 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_all_properties ───────────────────────────────────────────
27
+ server.tool("get_all_properties", "Dump all public properties of a component as JSON — names, types, and current values", {
28
+ id: z.string().describe("GUID of the GameObject"),
29
+ component: z.string().describe("Component type name"),
30
+ }, async (params) => {
31
+ const res = await bridge.send("get_all_properties", params);
32
+ if (!res.success) {
33
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
34
+ }
35
+ return {
36
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
37
+ };
38
+ });
39
+ // ── list_available_components ────────────────────────────────────
40
+ server.tool("list_available_components", "List all component types available in s&box (built-in and custom). Search by name or filter by category", {
41
+ filter: z
42
+ .string()
43
+ .optional()
44
+ .describe("Search filter — matches against component name and title"),
45
+ category: z
46
+ .string()
47
+ .optional()
48
+ .describe("Filter by category/group (e.g. 'Rendering', 'Physics', 'Audio')"),
49
+ }, async (params) => {
50
+ const res = await bridge.send("list_available_components", params);
51
+ if (!res.success) {
52
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
53
+ }
54
+ return {
55
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
56
+ };
57
+ });
58
+ // ── add_component_with_properties ────────────────────────────────
59
+ server.tool("add_component_with_properties", "Add a component to a GameObject and configure its properties in one call. Use list_available_components to find valid types", {
60
+ id: z.string().describe("GUID of the GameObject"),
61
+ component: z
62
+ .string()
63
+ .describe("Component type name (e.g. 'ModelRenderer', 'Rigidbody', 'BoxCollider')"),
64
+ properties: z
65
+ .record(z.unknown())
66
+ .optional()
67
+ .describe("Key-value map of property names to values. Values are auto-converted to the correct type"),
68
+ }, async (params) => {
69
+ const res = await bridge.send("add_component_with_properties", params);
70
+ if (!res.success) {
71
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
72
+ }
73
+ return {
74
+ content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
75
+ };
76
+ });
77
+ }
78
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1,8 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BridgeClient } from "../transport/bridge-client.js";
3
+ /**
4
+ * Console and error feedback tools: get_console_output, get_compile_errors, clear_console.
5
+ * Reads from the Bridge's circular log buffer (LogCapture) to surface editor output.
6
+ */
7
+ export declare function registerConsoleTools(server: McpServer, bridge: BridgeClient): void;
8
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Console and error feedback tools: get_console_output, get_compile_errors, clear_console.
4
+ * Reads from the Bridge's circular log buffer (LogCapture) to surface editor output.
5
+ */
6
+ export function registerConsoleTools(server, bridge) {
7
+ // ── get_console_output ───────────────────────────────────────────
8
+ server.tool("get_console_output", "Read recent console log entries from s&box. Returns log messages, warnings, and errors with timestamps", {
9
+ count: z
10
+ .number()
11
+ .optional()
12
+ .describe("Maximum number of log entries to return. Defaults to 50"),
13
+ severity: z
14
+ .enum(["all", "info", "warning", "error"])
15
+ .optional()
16
+ .describe("Filter by severity level. Defaults to 'all'"),
17
+ }, async (params) => {
18
+ const res = await bridge.send("get_console_output", params);
19
+ if (!res.success) {
20
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
21
+ }
22
+ return {
23
+ content: [
24
+ { type: "text", text: JSON.stringify(res.data, null, 2) },
25
+ ],
26
+ };
27
+ });
28
+ // ── get_compile_errors ───────────────────────────────────────────
29
+ server.tool("get_compile_errors", "Get current C# compilation errors and warnings from s&box. Returns file path, line number, column, error code, and message for each diagnostic", {}, async () => {
30
+ const res = await bridge.send("get_compile_errors");
31
+ if (!res.success) {
32
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
33
+ }
34
+ const data = res.data;
35
+ const errors = data?.errors ?? [];
36
+ const warnings = data?.warnings ?? [];
37
+ let text;
38
+ if (errors.length === 0 && warnings.length === 0) {
39
+ text = "No compilation errors or warnings. Code is clean!";
40
+ }
41
+ else {
42
+ text = JSON.stringify(res.data, null, 2);
43
+ }
44
+ return {
45
+ content: [{ type: "text", text }],
46
+ };
47
+ });
48
+ // ── clear_console ────────────────────────────────────────────────
49
+ server.tool("clear_console", "Clear all console log entries in the s&box editor", {}, async () => {
50
+ const res = await bridge.send("clear_console");
51
+ if (!res.success) {
52
+ return { content: [{ type: "text", text: `Error: ${res.error}` }] };
53
+ }
54
+ return {
55
+ content: [{ type: "text", text: "Console cleared" }],
56
+ };
57
+ });
58
+ }
59
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1,13 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BridgeClient } from "../transport/bridge-client.js";
3
+ /**
4
+ * Type discovery and code-search tools.
5
+ *
6
+ * These help Claude reference real s&box APIs instead of guessing. Use
7
+ * describe_type before writing code that touches an unfamiliar type — the
8
+ * Game.TypeLibrary reflection returns properties, methods, events, and
9
+ * attributes for any loaded type. Use search_types to find types matching
10
+ * a name pattern. find_in_project greps the user's project for usage examples.
11
+ */
12
+ export declare function registerDiscoveryTools(server: McpServer, bridge: BridgeClient): void;
13
+ //# sourceMappingURL=discovery.d.ts.map